* bind faces?
@ 2006-05-13 17:54 Drew Adams
2006-05-13 18:07 ` Chong Yidong
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: Drew Adams @ 2006-05-13 17:54 UTC (permalink / raw
I think the answer to this is "no", but I'm not sure:
Is there some way to get the effect of "binding" a face to a list of face
properties or the properties of another face? That is, do something akin to
this:
(let ((some-face another-face-or-a-list-of-face-properties))
(do-something))
Wouldn't it be useful to be able to do that? We have `let' for variables and
`flet' (via cl.el) for functions, but nothing for faces, IIUC. (Obviously, a
user could work with face variables, but those are not always available and
their use is generally discouraged.)
What is a good way to get such a result currently (i.e. a workaround)? Say
that you want to temporarily make face `x' have all the properties of face
`y'. How would you do that? unwind-protect + defface + defface back again?
Or unwind-protect + loop over all face attributes of `y', assigning them to
`x', then putting back `x's original attributes?
Is there an easy/elegant way to do this?
A special case would be to "wipe out" a face (make it invisible/unnoticable)
temporarily, giving its properties (e.g. fore/background) nil values. Is
there perhaps a good workaround for this special case?
A related feature would be to be able to make an overlay's face
unnoticeable. Not to use the `invisible' property, which hides the text, and
not to delete the overlay, but just to make the face itself
transparent/unnoticeable (e.g. temporarily).
I'm asking here instead of help-gnu-emacs because I suspect there is no easy
way to do this and, if so, I'd propose that we think about creating one
(after the release, of course). Also, in case I'm missing something or
misunderstanding faces or overlays, I know that folks here will help me see
the light. I'd like to know if there is a better way to accomplish what I'm
asking about than fiddling with face properties. Thx.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-13 17:54 bind faces? Drew Adams
@ 2006-05-13 18:07 ` Chong Yidong
2006-05-13 19:40 ` Drew Adams
2006-05-14 0:52 ` Miles Bader
2006-05-14 13:17 ` Stefan Monnier
2 siblings, 1 reply; 16+ messages in thread
From: Chong Yidong @ 2006-05-13 18:07 UTC (permalink / raw
Cc: Emacs-Devel
"Drew Adams" <drew.adams@oracle.com> writes:
> I think the answer to this is "no", but I'm not sure:
>
> Is there some way to get the effect of "binding" a face to a list of face
> properties or the properties of another face? That is, do something akin to
> this:
>
> (let ((some-face another-face-or-a-list-of-face-properties))
> (do-something))
>
> Wouldn't it be useful to be able to do that? We have `let' for variables and
> `flet' (via cl.el) for functions, but nothing for faces, IIUC. (Obviously, a
> user could work with face variables, but those are not always available and
> their use is generally discouraged.)
See face-default-spec, face-spec-set, and the other functions in
faces.el.
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-13 18:07 ` Chong Yidong
@ 2006-05-13 19:40 ` Drew Adams
2006-05-14 2:39 ` Richard Stallman
0 siblings, 1 reply; 16+ messages in thread
From: Drew Adams @ 2006-05-13 19:40 UTC (permalink / raw
> Is there some way to get the effect of "binding" a face to a
> list of face properties or the properties of another face?
> That is, do something akin to this:
>
> (let ((some-face another-face-or-a-list-of-face-properties))
> (do-something))
>
> Wouldn't it be useful to be able to do that? We have `let'
> for variables and `flet' (via cl.el) for functions, but
> nothing for faces, IIUC. (Obviously, a user could work with
> face variables, but those are not always available and
> their use is generally discouraged.)
See face-default-spec, face-spec-set, and the other functions in
faces.el.
Yes, thanks. They can help with saving a face's attributes (spec), setting
the attributes to those of another face (or a constructed spec), and then
restoring the face's original attributes.
But, IIUC, you would still need to do unwind-protect, save the current spec,
set to another spec, and restore current spec. It's not clear to me how they
would provide the convenience of a `let'. One could write one's own macro to
do that (via unwind-protect), but why not have Emacs provide that?
I'm also not clear on how to use those functions to make a face
"unnoticeable", but that's because I'm not sure which face spec to use to do
that. Would it be just this, or is there some general way to nullify all
pertinent face properties?
((t (:foreground nil) (:background nil)))
I've been using this, which does the job (but it doesn't take into account
other face properties, such as underline):
(set-face-foreground 'the-face nil)
(set-face-background 'the-face nil)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-13 17:54 bind faces? Drew Adams
2006-05-13 18:07 ` Chong Yidong
@ 2006-05-14 0:52 ` Miles Bader
2006-05-14 1:02 ` Drew Adams
2006-05-14 13:17 ` Stefan Monnier
2 siblings, 1 reply; 16+ messages in thread
From: Miles Bader @ 2006-05-14 0:52 UTC (permalink / raw
Cc: Emacs-Devel
"Drew Adams" <drew.adams@oracle.com> writes:
> Wouldn't it be useful to be able to do that? We have `let' for variables and
> `flet' (via cl.el) for functions, but nothing for faces, IIUC. (Obviously, a
> user could work with face variables, but those are not always available and
> their use is generally discouraged.)
Why exactly do you want to do this?
[FWIW, you can do it very easily with my `face remapping' patch -- it
ends up being just a normal `let' -- but that's part of Emacs yet:
(let ((face-remapping-alist (cons '(some-face . bold) face-remapping-alist)))
(read-string "blah: "))
]
-Miles
--
Somebody has to do something, and it's just incredibly pathetic that it
has to be us. -- Jerry Garcia
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-14 0:52 ` Miles Bader
@ 2006-05-14 1:02 ` Drew Adams
2006-05-14 2:16 ` Miles Bader
2006-05-14 2:33 ` Miles Bader
0 siblings, 2 replies; 16+ messages in thread
From: Drew Adams @ 2006-05-14 1:02 UTC (permalink / raw
Why exactly do you want to do this?
I thought I explained that. As an analogy to binding variables with `let'
and functions with `flet', we would bind faces. Why does anyone want to bind
variables and functions, as opposed to using `unwind-protect', assigning new
definitions, and restoring afterward?
FWIW, you can do it very easily with my `face remapping' patch -- it
ends up being just a normal `let' -- but that's [not?] part of Emacs
yet:
(let ((face-remapping-alist
(cons '(some-face . bold) face-remapping-alist)))
(read-string "blah: "))
Sounds promising (though I'm not sure how it works or just what it does).
Never heard of it. Will it be in Emacs 22? 23? Where is it available in the
meantime?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-14 1:02 ` Drew Adams
@ 2006-05-14 2:16 ` Miles Bader
2006-05-14 3:13 ` Drew Adams
2006-05-14 2:33 ` Miles Bader
1 sibling, 1 reply; 16+ messages in thread
From: Miles Bader @ 2006-05-14 2:16 UTC (permalink / raw
Cc: Emacs-Devel
On 5/14/06, Drew Adams <drew.adams@oracle.com> wrote:
> Why exactly do you want to do this?
>
> I thought I explained that. As an analogy to binding variables with `let'
> and functions with `flet', we would bind faces. Why does anyone want to bind
> variables and functions, as opposed to using `unwind-protect', assigning new
> definitions, and restoring afterward?
"By analogy with" isn't a very compelling reason for a feature. What
I'm asking is: "What is a real-world problem where you would need
such a thing?"
My impression is that faces in general reflect a more permanent sort
of state, and that the idea of "binding" face definitions is a bit
alien to the way they are used.
-Miles
--
Do not taunt Happy Fun Ball.
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-14 2:16 ` Miles Bader
@ 2006-05-14 3:13 ` Drew Adams
2006-05-14 4:10 ` David Kastrup
0 siblings, 1 reply; 16+ messages in thread
From: Drew Adams @ 2006-05-14 3:13 UTC (permalink / raw
> Why exactly do you want to do this?
>
> I thought I explained that.... Why does anyone want
> to bind variables and functions, as opposed to using
> `unwind-protect', assigning new definitions, and
> restoring afterward?
"By analogy with" isn't a very compelling reason for a feature. What
I'm asking is: "What is a real-world problem where you would need
such a thing?"
Emacs-Lisp programming. Any situation where you might want to redefine a
face only temporarily, for use in a particular context. Is that hard to
imagine?
My impression is that faces in general reflect a more permanent sort
of state
Precisely. You might want to change some properties of a face temporarily in
a function, without affecting its "more permanent" nature. You might want to
use existing code that employs a particular face (e.g. hard-coded - there
are examples of `region' and `highlight' in the standard Emacs code, for
instance), substituting another face, with different face properties, for
it. You might want to use existing code that employs a face, but not have
that face appear (be noticeable) at all.
and that the idea of "binding" face definitions is a bit
alien to the way they are used.
There is not only one way that faces are used - "the way". Binding a face
would be similar to binding a global variable. Like faces, many global
variables (including most user options) have a "more permanent sort of
state", but that doesn't mean it isn't useful sometimes to bind them to
different values locally.
It's precisely because we don't want to change the more permanent state of
global variables that we bind them to new values instead of assigning them
those values. Imagine that you had no `let' binding and you wanted to get a
similar effect. You would use `unwind-protect', save the value, assign the
new value, execute the body, and then restore the original value. That's
where we are today with faces.
"When you have only a hammer, everything looks like a nail", as they say. If
there were no `let', there would be a lot less temporary changing of global
variables (not worth the hassle; lack of appreciation of the
possibility/need), and someone suggesting to add `let' would be asked "Why
do you need that in the real world? Global variables have a permanent sort
of state. That is a bit alien to the way they are used."
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-14 3:13 ` Drew Adams
@ 2006-05-14 4:10 ` David Kastrup
0 siblings, 0 replies; 16+ messages in thread
From: David Kastrup @ 2006-05-14 4:10 UTC (permalink / raw
Cc: Emacs-Devel
"Drew Adams" <drew.adams@oracle.com> writes:
> > Why exactly do you want to do this?
> >
> > I thought I explained that.... Why does anyone want
> > to bind variables and functions, as opposed to using
> > `unwind-protect', assigning new definitions, and
> > restoring afterward?
>
> "By analogy with" isn't a very compelling reason for a feature. What
> I'm asking is: "What is a real-world problem where you would need
> such a thing?"
>
> Emacs-Lisp programming. Any situation where you might want to
> redefine a face only temporarily, for use in a particular
> context. Is that hard to imagine?
That's just a restatement of what you want, but not what for. What is
a real-world problem where you would need such a thing?
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-14 1:02 ` Drew Adams
2006-05-14 2:16 ` Miles Bader
@ 2006-05-14 2:33 ` Miles Bader
1 sibling, 0 replies; 16+ messages in thread
From: Miles Bader @ 2006-05-14 2:33 UTC (permalink / raw
Cc: Emacs-Devel
"Drew Adams" <drew.adams@oracle.com> writes:
> FWIW, you can do it very easily with my `face remapping' patch -- it
> ends up being just a normal `let' -- but that's [not?] part of Emacs
> yet:
> (let ((face-remapping-alist
> (cons '(some-face . bold) face-remapping-alist)))
> (read-string "blah: "))
>
> Sounds promising (though I'm not sure how it works or just what it does).
> Never heard of it. Will it be in Emacs 22? 23? Where is it available in the
> meantime?
It's sitting in my personal source tree; I can cons up a patch.
I don't know when it will go in, but I assume it will at some point.
RMS approved of the feature generally, but disagreed with some of the
implementation details, so I'll have to find the time to either work out
something that is both acceptable to him and maintains all desired
properties.
The essential idea is to make face realization dependent on a variable
binding (a "remapping alist" -- the simplest usage just allows you to
"bind" face names to point to other faces, but you can also bind faces
by feature).
Here's the description (the value you see here is because I have the
"default" face bound to "variable-pitch" in mail composition buffers):
face-remapping-alist is a variable defined in `C source code'.
Its value is
((default variable-pitch))
Local in buffer *wide reply to Drew Adams*; global value is nil
Documentation:
Alist of face remappings.
Each element is of the form:
(FACE REPLACEMENT...),
which causes display of the face FACE to use REPLACEMENT... instead.
REPLACEMENT... is interpreted the same way the value of a `face' text
property is: it may be (1) A face name, (2) A list of face names, (3) A
property-list of face attribute/value pairs, or (4) A list of face names
intermixed with lists containing face attribute/value pairs.
Multiple entries in REPLACEMENT... are merged together to form the final
result, with faces or attributes earlier in the list taking precedence
over those that are later.
Face-name remapping cycles are suppressed; recursive references use the
underlying face instead of the remapped face. So a remapping of the form:
(FACE EXTRA-FACE... FACE)
or:
(FACE (FACE-ATTR VAL ...) FACE)
will cause EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
existing definition of FACE. Note that for the default face, this isn't
necessary, as every face inherits from the default face.
Making this variable buffer-local is a good way to allow buffer-specific
face definitions. For instance, the mode my-mode could define a face
`my-mode-default', and then in the mode setup function, do:
(set (make-local-variable 'face-remapping-alist)
'((default my-mode-default)))).
-Miles
--
Somebody has to do something, and it's just incredibly pathetic that it
has to be us. -- Jerry Garcia
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-13 17:54 bind faces? Drew Adams
2006-05-13 18:07 ` Chong Yidong
2006-05-14 0:52 ` Miles Bader
@ 2006-05-14 13:17 ` Stefan Monnier
2006-05-14 14:32 ` Drew Adams
2 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2006-05-14 13:17 UTC (permalink / raw
Cc: Emacs-Devel
> Is there some way to get the effect of "binding" a face to a list of face
> properties or the properties of another face? That is, do something akin to
> this:
> (let ((some-face another-face-or-a-list-of-face-properties))
> (do-something))
I'm not sure what you expect this to do.
The lookup to map face names to visual properties is done (repeatedly)
during redisplay, so would your let-face binding only affect the visual
appearance of the face in the redisplays that take place during
`do-something' or would you want the effect to outlive the let?
E.g. in the code below:
(let-face ((font-lock-string-face :background "red"))
(put-text-property 1 5 'face 'font-lock-string-face))
do you expect the chars 1-5 to end up with a red background? If so, it's
going to be difficult, because the whole put-text-property expression
doesn't currently know it's manipulating any kind of face.
Stefan
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-14 13:17 ` Stefan Monnier
@ 2006-05-14 14:32 ` Drew Adams
2006-05-14 14:46 ` Miles Bader
0 siblings, 1 reply; 16+ messages in thread
From: Drew Adams @ 2006-05-14 14:32 UTC (permalink / raw
> Is there some way to get the effect of "binding" a face to a
> list of face properties or the properties of another face?
> That is, do something akin to this:
> (let ((some-face another-face-or-a-list-of-face-properties))
> (do-something))
I'm not sure what you expect this to do.
The lookup to map face names to visual properties is done (repeatedly)
during redisplay, so would your let-face binding only affect the visual
appearance of the face in the redisplays that take place during
`do-something' or would you want the effect to outlive the let?
I'm not sure I understand (I'm no expert on faces or displaying). Could you
elaborate on the first part of that sentence?
Are you saying that adding the face to some text wouldn't be reflected
visually until redisplay takes place, and that might not happen until after
the let is exited? Or are you saying something else? For the second part of
the sentence, IIUC, I would not expect the face to reflect the new
definition after the let is exited.
E.g. in the code below:
(let-face ((font-lock-string-face :background "red"))
(put-text-property 1 5 'face 'font-lock-string-face))
do you expect the chars 1-5 to end up with a red background?
If so, it's going to be difficult, because the whole
put-text-property expression doesn't currently know it's
manipulating any kind of face.
I'm guessing that you mean that put-text-property would make chars 1-5 have
font-lock-string-face (which would be defined at that point to have a red
background), but those chars wouldn't get redisplayed until after the let is
exited. If that's the case, then I'd say that users can use let to bind the
face to a new definition, and they can use put-text-property to add that
(newly defined) face to text, but they also need to (do something to) force
redisplay inside the let, if they want to see the effect.
Again, I'm no expert on this, so I don't know how this should be implemented
(assuming I'm understanding the problem). If face definition and application
to text are separated from redisplay (manifestation of the face change) in
Emacs, then that fact will need to be taken into account. Either redisplay
would need to be done automatically (but when?) or users would need to take
care of redisplay themselves. The latter sounds fine to me (IIUC).
Would (sit-for 0) or (force-mode-line-update) accomplish that? That is,
could a user take care of the problem by simply doing this?
(let-face ((font-lock-string-face :background "red"))
(put-text-property 1 5 'face 'font-lock-string-face)
...
(force-mode-line-update) ; Redisplay now.
...
)
If I'm not understanding you well, perhaps you can elaborate a bit on the
problem and possible alternatives.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-14 14:32 ` Drew Adams
@ 2006-05-14 14:46 ` Miles Bader
2006-05-14 16:13 ` Drew Adams
0 siblings, 1 reply; 16+ messages in thread
From: Miles Bader @ 2006-05-14 14:46 UTC (permalink / raw
Cc: Emacs-Devel
On 5/14/06, Drew Adams <drew.adams@oracle.com> wrote:
> I'm guessing that you mean that put-text-property would make chars 1-5 have
> font-lock-string-face (which would be defined at that point to have a red
> background), but those chars wouldn't get redisplayed until after the let is
> exited. If that's the case, then I'd say that users can use let to bind the
> face to a new definition, and they can use put-text-property to add that
> (newly defined) face to text, but they also need to (do something to) force
> redisplay inside the let, if they want to see the effect.
Reading this, it's extremely unclear what you actually want to happen.
Again: Give a real world example of a UI problem using your proposed
feature. Not only will that help justify it, it will clarify what
exactly you think it should do.
(The example I gave causes the given face's display to change _during
the binding_ -- I used a call to read-string in my example because
that causes redisplay and user interaction within the binding; the
display of the given face changes back again after the binding ceases
to be active)
-Miles
--
Do not taunt Happy Fun Ball.
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-14 14:46 ` Miles Bader
@ 2006-05-14 16:13 ` Drew Adams
2006-05-14 17:49 ` Stefan Monnier
0 siblings, 1 reply; 16+ messages in thread
From: Drew Adams @ 2006-05-14 16:13 UTC (permalink / raw
The example I gave causes the given face's display to change _during
the binding_ -- I used a call to read-string in my example because
that causes redisplay and user interaction within the binding; the
display of the given face changes back again after the binding ceases
to be active
That's what I was saying also: the user (programmer) can do something
(read-string is one possibility) to force redisplay within the scope of the
binding. And the "face changes back again after the binding ceases to be
active". The example I gave used `force-mode-line-update' to cause
redisplay. I also mentioned (sit-for 0). You used `read-string'. There are
many ways to cause redisplay, I believe.
We seem to be saying the same thing about this aspect - you about what your
feature does and I about what my requested feature would do.
If I understand Stefan's point, it is that redisplay does not automatically
occur just because you've made a face binding and changed some text
properties. The user would be responsible for doing something to cause
redisplay, or else the face change wouldn't be manifested visually.
I have no problem with the user taking responsibility for redisplay. Unless
I misunderstand, that is no different from what happens now when you assign
(not bind) new properties to a face and then put that face on some text.
Without redisplay the change is not seen. Again, I'm no expert on faces and
the display process - correct me if I'm wrong on this.
I'm not saying that your implementation wouldn't satisfy my request. If it
does, and if it's the best implementation for such a feature, then I'm all
for it. I am not proposing any particular implementation, and I am not
saying anything about your implementation. I didn't follow the thread about
face remapping. If my request is nothing new, and this question has already
been decided, then ignore my request.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: bind faces?
2006-05-14 16:13 ` Drew Adams
@ 2006-05-14 17:49 ` Stefan Monnier
2006-05-14 18:43 ` Drew Adams
0 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2006-05-14 17:49 UTC (permalink / raw
Cc: Emacs-Devel
> If I understand Stefan's point, it is that redisplay does not automatically
> occur just because you've made a face binding and changed some text
> properties.
Yes, Emacs does redisplay automatically, but not while executing Lisp.
Only when all execution is done and the control comes back to the toplevel.
So in my example, the redisplay takes place after the `let' is finished.
But even if you force redisplay within the `let', that doesn't mean that it
won't be done again later (maybe because you (de)iconify windows, ...).
In that case, would you want the subsequent auto-redisplay to take the
let-face into account or is it OK if it reverts the display to the default
definition of the face?
Stefan
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: bind faces?
2006-05-14 17:49 ` Stefan Monnier
@ 2006-05-14 18:43 ` Drew Adams
0 siblings, 0 replies; 16+ messages in thread
From: Drew Adams @ 2006-05-14 18:43 UTC (permalink / raw
> If I understand Stefan's point, it is that redisplay does not
> automatically occur just because you've made a face binding
> and changed some text
> properties.
Yes, Emacs does redisplay automatically, but not while executing Lisp.
Only when all execution is done and the control comes back to
the toplevel.
So in my example, the redisplay takes place after the `let' is finished.
But even if you force redisplay within the `let', that doesn't
mean that it
won't be done again later (maybe because you (de)iconify windows, ...).
In that case, would you want the subsequent auto-redisplay to take the
let-face into account or is it OK if it reverts the display to
the default definition of the face?
If I understand the problem/question, I'd say that any (re-)display
(explicit by program, automatic, or provoked by user action such as
iconification) after the let is finished (outside its scope) should show the
original face, not the face as bound inside the let. And any redisplay (no
matter how initiated) while the let is in effect should show the face as
bound inside the let.
I suspect I might be missing the point of your question, however. If so,
perhaps you can detect what I'm missing and let me know.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2006-05-14 18:43 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-13 17:54 bind faces? Drew Adams
2006-05-13 18:07 ` Chong Yidong
2006-05-13 19:40 ` Drew Adams
2006-05-14 2:39 ` Richard Stallman
2006-05-14 0:52 ` Miles Bader
2006-05-14 1:02 ` Drew Adams
2006-05-14 2:16 ` Miles Bader
2006-05-14 3:13 ` Drew Adams
2006-05-14 4:10 ` David Kastrup
2006-05-14 2:33 ` Miles Bader
2006-05-14 13:17 ` Stefan Monnier
2006-05-14 14:32 ` Drew Adams
2006-05-14 14:46 ` Miles Bader
2006-05-14 16:13 ` Drew Adams
2006-05-14 17:49 ` Stefan Monnier
2006-05-14 18:43 ` Drew Adams
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).