* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
@ 2013-11-15 2:04 Michael Heerdegen
2013-11-15 2:47 ` Michael Heerdegen
` (2 more replies)
0 siblings, 3 replies; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-15 2:04 UTC (permalink / raw)
To: 15900
Hello,
`foreground-color-at-point' doesn't return the expected result when
there are several faces at point present.
For example, on the red subject in a Gnus article buffer, or on a blue
link in w3m, it returns "black". Looking at the code, I see that
`foreground-color-at-point' uses
(face-at-point)
i.e., it looks only at one face and disregards the others. This is
especially meaningless when this first face doesn't specify any
foreground at all.
Thanks,
Michael.
P.S. Some background: I'm working on an addition to stripe-buffer.el
that changes the foreground color continuously, instead of changing the
background. This is for better readability.
I want to keep the foreground colors already present, so that e.g. links
in w3m are still recognizable. Paragraphs in italic can be colored
OTOH.
So, what I need is a reliable `foreground-color-at-point'. Tips and
alternatives welcome.
In GNU Emacs 24.3.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.8.4)
of 2013-11-13 on drachen
Windowing system distributor `The X.Org Foundation', version 11.0.11403000
System Description: Debian GNU/Linux testing (jessie)
Configured using:
`configure --prefix=/usr/local/built/'
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 2:04 Michael Heerdegen
@ 2013-11-15 2:47 ` Michael Heerdegen
2013-11-15 8:26 ` Eli Zaretskii
2022-04-22 13:30 ` Lars Ingebrigtsen
2 siblings, 0 replies; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-15 2:47 UTC (permalink / raw)
To: 15900
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Hello,
>
> `foreground-color-at-point' doesn't return the expected result when
> there are several faces at point present.
>
> For example, on the red subject in a Gnus article buffer, or on a blue
> link in w3m, it returns "black". Looking at the code, I see that
> `foreground-color-at-point' uses
>
> (face-at-point)
>
> i.e., it looks only at one face and disregards the others. This is
> especially meaningless when this first face doesn't specify any
> foreground at all.
Even
(face-at-point nil 'multiple)
is not correct. Evaluated in w3m with point on a link, i get
==> (w3m-current-anchor)
This is what I get for M-1 C-x = (excerpt)
,----------------------------------------------------------------------
| There is an overlay here:
| From 7785 to 7798
| evaporate t
| face w3m-current-anchor
| w3m-momentary-overlay t
|
|
| There are text properties here:
| balloon-help nil
| face (w3m-anchor)
| help-echo [Show]
| keymap [Show]
| mouse-face highlight
| rear-nonsticky t
| w3m-anchor-sequence 75
| w3m-anchor-title nil
| w3m-balloon-help [Show]
| w3m-href-anchor [Show]
| w3m-name-anchor [Show]
| w3m-name-anchor2 ("showmodes" "gb_70")
| w3m-safe-url-regexp nil
`----------------------------------------------------------------------
`face-at-point' disregards the face text property, it only returns the
face overlay property.
> So, what I need is a reliable `foreground-color-at-point'. Tips and
> alternatives welcome.
I try to use something like this as a workaround now:
--8<---------------cut here---------------start------------->8---
(cl-some
(lambda (face) (not (memq (face-foreground face nil t)
`(nil ,(face-attribute 'default :foreground)))))
(cl-mapcan (lambda (face-or-list) (if (facep face-or-list)
(list face-or-list)
face-or-list))
(list
(get-text-property (point) 'face)
(get-text-property (point) 'font-lock-face))))
--8<---------------cut here---------------end--------------->8---
Regards,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 2:04 Michael Heerdegen
2013-11-15 2:47 ` Michael Heerdegen
@ 2013-11-15 8:26 ` Eli Zaretskii
2013-11-15 22:18 ` Michael Heerdegen
2022-04-22 13:30 ` Lars Ingebrigtsen
2 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-15 8:26 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Fri, 15 Nov 2013 03:04:56 +0100
>
> `foreground-color-at-point' doesn't return the expected result when
> there are several faces at point present.
>
> For example, on the red subject in a Gnus article buffer, or on a blue
> link in w3m, it returns "black". Looking at the code, I see that
> `foreground-color-at-point' uses
>
> (face-at-point)
>
> i.e., it looks only at one face and disregards the others. This is
> especially meaningless when this first face doesn't specify any
> foreground at all.
As you later discovered, even (face-at-point nil t) doesn't do the
job.
Which doesn't surprise me a bit: this kind of things cannot be done
reliably from Lisp, even at a price of the kind of obfuscated code
that face-at-point and foreground-color-at-point use. It is much
simpler to write a C primitive that simulates the display, then
returns the resulting face at a given character position, a simple and
straightforward task on the C level, something the display engine does
all the time.
> P.S. Some background: I'm working on an addition to stripe-buffer.el
> that changes the foreground color continuously, instead of changing the
> background. This is for better readability.
>
> I want to keep the foreground colors already present, so that e.g. links
> in w3m are still recognizable. Paragraphs in italic can be colored
> OTOH.
>
> So, what I need is a reliable `foreground-color-at-point'. Tips and
> alternatives welcome.
Why can't you detect that a portion of text is covered by specific
properties (e.g., one of a list of known properties), and leave those
portions alone?
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 8:26 ` Eli Zaretskii
@ 2013-11-15 22:18 ` Michael Heerdegen
2013-11-16 0:26 ` Drew Adams
2013-11-16 8:44 ` Eli Zaretskii
0 siblings, 2 replies; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-15 22:18 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 15900
Hello,
CCing Drew cause the Change Log mentions him with regard to
`foreground-color-at-point'.
Eli Zaretskii <eliz@gnu.org> writes:
> As you later discovered, even (face-at-point nil t) doesn't do the
> job.
>
> Which doesn't surprise me a bit: this kind of things cannot be done
> reliably from Lisp, even at a price of the kind of obfuscated code
> that face-at-point and foreground-color-at-point use. It is much
> simpler to write a C primitive that simulates the display, then
> returns the resulting face at a given character position, a simple and
> straightforward task on the C level, something the display engine does
> all the time.
That sounds good. Can we just do that?
> > P.S. Some background: I'm working on an addition to stripe-buffer.el
> > that changes the foreground color continuously, instead of changing the
> > background. This is for better readability.
> >
> > I want to keep the foreground colors already present, so that e.g. links
> > in w3m are still recognizable. Paragraphs in italic can be colored
> > OTOH.
> >
> > So, what I need is a reliable `foreground-color-at-point'. Tips and
> > alternatives welcome.
>
> Why can't you detect that a portion of text is covered by specific
> properties (e.g., one of a list of known properties), and leave those
> portions alone?
What do you mean with "properties" - text and overlay properties? If
faces are among them, I still must figure out if one of these faces
changes the foreground. If not, i.e., if a face e.g. just underlines, I
do want to color the text nevertheless. Probably I didn't understand
what you meant. This expression works ok for me:
--8<---------------cut here---------------start------------->8---
(cl-some
(lambda (face) (not (memq (face-foreground face nil t)
`(nil
,(face-attribute 'default :foreground)
"unspecified-fg" "unspecified-bg"))))
(cl-mapcan (lambda (face-or-list) (if (facep face-or-list)
(list face-or-list)
face-or-list))
(list
(get-text-property (point) 'face)
(get-text-property (point) 'font-lock-face))))
--8<---------------cut here---------------end--------------->8---
Overlays are not covered by this - which is not even necessary, because
overlays have priorities that can be controlled.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 22:18 ` Michael Heerdegen
@ 2013-11-16 0:26 ` Drew Adams
2013-11-16 8:57 ` Eli Zaretskii
2013-11-16 8:44 ` Eli Zaretskii
1 sibling, 1 reply; 22+ messages in thread
From: Drew Adams @ 2013-11-16 0:26 UTC (permalink / raw)
To: Michael Heerdegen, Eli Zaretskii; +Cc: 15900
> CCing Drew cause the Change Log mentions him with regard to
> `foreground-color-at-point'.
Thanks, Michael. I wasn't reading this thread.
1. Let me first butt in with this preliminary comment, having now
diff'd the current code (as of an MS Windows snapshot from 11/12)
against the Emacs 24.3 code (which is the same as what I submitted).
I think it is a mistake to fudge `face-at-point' so that it returns
a face named in the buffer. That is NOT at all "the face of the
character after point", which is what the doc string first line
says. And it is (was) not the intention of `face-at-point' at all.
See below for a suggestion, for those who want a face named at point.
In addition, that argument should not be called THING. It is NOT
(as is usually the case for an argument so named) a symbol or a
string naming an Emacs THING, as in `thingatpt.el'. It is just a
Boolean which if non-nil means to try first for a face name at point.
IOW, it should be called something like CHECK-FOR-FACE-NAMED-IN-TEXT.
2. Now on to the addition of argument MULTIPLE, which is mainly what
this bug is about, IIUC.
In the bug report, Michael said this:
it looks only at one face and disregards the others. This is
especially meaningless when this first face doesn't specify any
foreground at all.
Yes, `face-at-point' returned only the first of a list of faces.
No, it is not meaningless for `face-at-point' to return a face that
does not specify a foreground. Or does not specify a background.
Or an underline. Or any other face attribute. By default, it was
designed to return face `default' if no other face was found at
point but if another face was found it returned that face.
`face-at-point' should give you a face at point, regardless of the
attributes that face might specify explicitly.
Does it make sense for `foreground-color-at-point' to return nil
if the face returned by `face-at-point' specifies no foreground?
Yes. It was designed to return the color specified by a given
face, and if no such color was specified, to return nil. But it
uses `face-at-point', which looks at face `default' if no other
face is found at point.
If there is a non-`default' face at point, then its foreground
should be used, and if there is none, then nil should be the result.
3. But MULTIPLE is something else. It aims to give you all of the
faces at point, whether used as a text property or an overlay
property. Like THING, MULTIPLE was added after I contributed the
code. But unlike THING, MULTIPLE is a good addition.
I can imagine that it might be useful to optionally get only faces
used as a text property or only those used as an overlay property.
Michael's use case is apparently one such.
Perhaps `*face-at-point' should provide an argument for this.
(That would certainly be more useful than the THING argument,
which has nothing to do with the properties at point.)
It looks like there is a bug wrt the use of `get-char-property'.
`get-char-property' itself always favors an overlay property over
the same property used as a text property at the same position.
Furthermore, this important part of the `get-char-property'
behavior is not even mentioned in the doc string (it is mentioned
in the Elisp manual). This DOC BUG should be the first thing to
be fixed.
Given this limitation, it seems that the right thing for
`face-at-point' to do is to gather faces using both
`get-text-property' and `get-overlay-property', and not
`get-char-property'. And it might be good to add an argument that
lets you specify one or the other of these or both.
Given that fix, MULTIPLE should DTRT. And Michael should be
have what he needs.
4. So I would propose the following:
a. REMOVE the misnamed argument THING altogether. It does not
belong in `face-at-point'. Create a function
`face-named-at-point' that returns the face named at point.
Anyone wanting the behavior of first-look-for-face-named-...
would use (or (face-named-at-point...) (face-at-point...)).
The time to make this change is NOW, before 24.4 is released.
b. Add an optional argument TYPE, with a nil value meaning
both overlay and text property. Possible values would be
`overlay', `text', and nil.
c. TYPE would be taken into account regardless of the value
of MULTIPLE. For non-nil MULTIPLE the function would return a
list of all faces at point, whether in overlays or the `face'
text property. `face-at-point' would use `get-text-property'
or `get-overlay-property', or both, and not `get-char-property'.
> > As you later discovered, even (face-at-point nil t) doesn't
> > do the job. Which doesn't surprise me a bit: this kind of
> > things cannot be done reliably from Lisp
I don't see any basis for saying that. See above. Sounds
pretty straightforward in Lisp, to me. What am I missing?
> > even at a price of the kind of obfuscated code that
> > face-at-point and foreground-color-at-point use.
Care to back that up? Just where do you see obfuscation?
> > It is much simpler to write a C primitive that simulates
> > the display, then returns the resulting face at a given
> > character position, a simple and straightforward task on
> > the C level, something the display engine does all the
> > time.
Overengineering, IMO. Not needed for `face-at-point', that
I can see.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 22:18 ` Michael Heerdegen
2013-11-16 0:26 ` Drew Adams
@ 2013-11-16 8:44 ` Eli Zaretskii
2013-11-17 2:33 ` Michael Heerdegen
1 sibling, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-16 8:44 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: 15900@debbugs.gnu.org, Drew Adams <drew.adams@oracle.com>
> Date: Fri, 15 Nov 2013 23:18:11 +0100
>
> > As you later discovered, even (face-at-point nil t) doesn't do the
> > job.
> >
> > Which doesn't surprise me a bit: this kind of things cannot be done
> > reliably from Lisp, even at a price of the kind of obfuscated code
> > that face-at-point and foreground-color-at-point use. It is much
> > simpler to write a C primitive that simulates the display, then
> > returns the resulting face at a given character position, a simple and
> > straightforward task on the C level, something the display engine does
> > all the time.
>
> That sounds good. Can we just do that?
For some value of "we", yes. If "we" includes me and you, then it
will have to be you, as my plate is pretty much full these days,
sorry. In my defense, I can tell that this should be a nice exercise
for someone who wants to get accustomed to hacking the display engine,
as it shouldn't be too hard, and there's abundant example code that
does similar things.
> > > P.S. Some background: I'm working on an addition to stripe-buffer.el
> > > that changes the foreground color continuously, instead of changing the
> > > background. This is for better readability.
> > >
> > > I want to keep the foreground colors already present, so that e.g. links
> > > in w3m are still recognizable. Paragraphs in italic can be colored
> > > OTOH.
> > >
> > > So, what I need is a reliable `foreground-color-at-point'. Tips and
> > > alternatives welcome.
> >
> > Why can't you detect that a portion of text is covered by specific
> > properties (e.g., one of a list of known properties), and leave those
> > portions alone?
>
> What do you mean with "properties" - text and overlay properties?
Yes.
> If faces are among them, I still must figure out if one of these
> faces changes the foreground.
You can know them in advance, I think. Your example talks about
links, which use a known face. I presume there are only a few faces
that needs such a special treatment, which would make the list of them
quite short.
IOW, why not test against a known list of properties that you want to
leave alone, instead of digging into their color?
> If not, i.e., if a face e.g. just underlines, I do want to color the
> text nevertheless.
The face used by links is different not only in its underline, but
also in its color. If you want links to remain instantly
recognizable, you should probably keep their appearance intact
wholesale, not just the underline, otherwise how would the user
distinguish between a link and underlined text?
> Probably I didn't understand what you meant.
More probable that I didn't understand what you meant. Hopefully the
above tells enough about my misunderstanding to allow you to correct
me.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-16 0:26 ` Drew Adams
@ 2013-11-16 8:57 ` Eli Zaretskii
0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-16 8:57 UTC (permalink / raw)
To: Drew Adams; +Cc: michael_heerdegen, 15900
> Date: Fri, 15 Nov 2013 16:26:15 -0800 (PST)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: 15900@debbugs.gnu.org
>
> > > As you later discovered, even (face-at-point nil t) doesn't
> > > do the job. Which doesn't surprise me a bit: this kind of
> > > things cannot be done reliably from Lisp
>
> I don't see any basis for saying that. See above. Sounds
> pretty straightforward in Lisp, to me. What am I missing?
You are missing the fact that only part of what the display engine
does to compute the appearance of a given character on display is
exposed to Lisp.
> > > even at a price of the kind of obfuscated code that
> > > face-at-point and foreground-color-at-point use.
>
> Care to back that up? Just where do you see obfuscation?
Everywhere. I don't understand why that code does what it does, for
starters. It looks to me as a series of kludges one upon another,
with the sole purpose of outsmarting the display engine. These kinds
of things should never be done in Lisp, because they all will look
like that: complicated, fragile, and unreliable.
> > > It is much simpler to write a C primitive that simulates
> > > the display, then returns the resulting face at a given
> > > character position, a simple and straightforward task on
> > > the C level, something the display engine does all the
> > > time.
>
> Overengineering, IMO.
In my book, a simple and elegant solution is always better than a
complex and inelegant one. That's the opposite of over-engineering.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
[not found] ` <<83vbzshggy.fsf@gnu.org>
@ 2013-11-16 16:20 ` Drew Adams
2013-11-16 16:40 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Drew Adams @ 2013-11-16 16:20 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: michael_heerdegen, 15900
> > > > As you later discovered, even (face-at-point nil t) doesn't
> > > > do the job. Which doesn't surprise me a bit: this kind of
> > > > things cannot be done reliably from Lisp
> >
> > I don't see any basis for saying that. See above. Sounds
> > pretty straightforward in Lisp, to me. What am I missing?
>
> You are missing the fact that only part of what the display engine
> does to compute the appearance of a given character on display is
> exposed to Lisp.
Please be specific. Just what, in the current context, cannot
be done?
The point of `face-at-point' is to give Lisp code a face at point.
Clearly Lisp code can have access only to faces that it can access!
What else is needed here, for `face-at-point'?
> > Just where do you see obfuscation?
>
> Everywhere. I don't understand why that code does what it does, for
> starters. It looks to me as a series of kludges one upon another,
> with the sole purpose of outsmarting the display engine.
Generalities. What things? In what way do you think it is trying
to outsmart the display engine? If you criticize the code, that's
good - but please speak about it specifically. Otherwise, there is
no way to know what you are talking about, and no one can learn
anything other than the fact that you don't understand the code.
> These kinds of things should never be done in Lisp, because they
> all will look like that: complicated, fragile, and unreliable.
What kinds of things? What things? Why should they, whatever they
are "never be done in Lisp"? I ask you to point to something
specific that is problematic, and you just reply "Everywhere" and
"these things" and "should never be done". That's not constructive.
Talk about obfuscation!
> In my book, a simple and elegant solution is always better than a
> complex and inelegant one. That's the opposite of over-engineering.
No one would disagree with that first sentence. Just a platitude,
unfortunately. Please explain what complexity and inelegance you
perceive, so we all can learn, instead of just mouthing "obfuscation"
"everywhere".
And while you're at it, please describe the Lisp-level function(s)
that you propose to provide in C. I have no doubt they will be
useful - I am confident in you for that. My questions are about
your problems with the code of `face-at-point', not about your
ability to provide something useful to Lisp from C. I look forward
to some real, helpful information about both.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-16 16:20 ` Drew Adams
@ 2013-11-16 16:40 ` Eli Zaretskii
0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-16 16:40 UTC (permalink / raw)
To: Drew Adams; +Cc: michael_heerdegen, 15900
> Date: Sat, 16 Nov 2013 08:20:01 -0800 (PST)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: michael_heerdegen@web.de, 15900@debbugs.gnu.org
>
> > > > > As you later discovered, even (face-at-point nil t) doesn't
> > > > > do the job. Which doesn't surprise me a bit: this kind of
> > > > > things cannot be done reliably from Lisp
> > >
> > > I don't see any basis for saying that. See above. Sounds
> > > pretty straightforward in Lisp, to me. What am I missing?
> >
> > You are missing the fact that only part of what the display engine
> > does to compute the appearance of a given character on display is
> > exposed to Lisp.
>
> Please be specific. Just what, in the current context, cannot
> be done?
What foreground-color-at-point tries to do.
> The point of `face-at-point' is to give Lisp code a face at point.
I wasn't talking about face-at-point (although it, too, has its
measure of difficulties, as the face of a character can come from
umpteen different sources). This discussion is about
foreground-color-at-point.
> Clearly Lisp code can have access only to faces that it can access!
> What else is needed here, for `face-at-point'?
I was not talking about face-at-point.
> > > Just where do you see obfuscation?
> >
> > Everywhere. I don't understand why that code does what it does, for
> > starters. It looks to me as a series of kludges one upon another,
> > with the sole purpose of outsmarting the display engine.
>
> Generalities. What things? In what way do you think it is trying
> to outsmart the display engine?
It tries to second-guess what the display engine would do given the
faces and overlays at or around point. It is much better to ask the
display engine to provide that information directly.
> > These kinds of things should never be done in Lisp, because they
> > all will look like that: complicated, fragile, and unreliable.
>
> What kinds of things? What things?
foreground-color-at-point, of course.
> Why should they, whatever they are "never be done in Lisp"?
Because, for the umpteenth time, Lisp code is not given enough
information to do that.
> please describe the Lisp-level function(s) that you propose to
> provide in C
foreground-color-at-point, obviously. Maybe also
background-color-at-point, for symmetry. I would also propose
face-at-point, but that's another discussion.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
[not found] ` <<83li0ogv14.fsf@gnu.org>
@ 2013-11-16 17:47 ` Drew Adams
2013-11-16 18:18 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Drew Adams @ 2013-11-16 17:47 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: michael_heerdegen, 15900
> > Please be specific. Just what, in the current context, cannot
> > be done?
>
> What foreground-color-at-point tries to do.
Please be specific. You have said nothing about it, so far.
> > The point of `face-at-point' is to give Lisp code a face at point.
>
> I wasn't talking about face-at-point (although it, too, has its
> measure of difficulties, as the face of a character can come from
> umpteen different sources). This discussion is about
> foreground-color-at-point.
Fine. Replace `face-at-point' with `foreground-at-point' in my
questions to you: Please be specific about the `foreground-at-point'
code. So far, you have said nothing concrete about it.
> > > Everywhere. I don't understand why that code does what it does,
> > > for starters. It looks to me as a series of kludges one upon
> > > another, with the sole purpose of outsmarting the display engine.
> >
> > Generalities. What things? In what way do you think it is trying
> > to outsmart the display engine?
>
> It tries to second-guess what the display engine would do given the
> faces and overlays at or around point.
How so? Please point to something in the code that you think "tries
to second-guess what the display engine would do..." Stop
hand-waving, please.
> It is much better to ask the display engine to provide that
> information directly.
What information? Please point to specifics in the Lisp code.
> > > These kinds of things should never be done in Lisp, because they
> > > all will look like that: complicated, fragile, and unreliable.
> >
> > What kinds of things? What things?
>
> foreground-color-at-point, of course.
Again, just hand-waving. Just what things in the code of
`foreground-color-at-point' are problematic, for you?
> > Why should they, whatever they are, "never be done in Lisp"?
>
> Because, for the umpteenth time, Lisp code is not given enough
> information to do that.
To do what? What information are you hinting about?
Please stop with the generalities about "Lisp code" and "these
kinds of things" and "information", and get down to Earth with
your criticism of the `foreground-color-at-point' code. You claim
that the code is obfuscated. I want to learn just how that is.
What is unclear about it?
> > please describe the Lisp-level function(s) that you propose to
> > provide in C
>
> foreground-color-at-point, obviously.
I see. And what is the spec of what that function would do?
What would it do differently? Just what is the problem you would
be trying to solve by moving the implementation of this function
to C?
Please don't just reply that you will remove obfuscation or some
such. Be specific about the problems you see in the Lisp code
and how you will solve those problems by moving the code to C.
I'm sure that if you do that I will understand, and will likely be
convinced. But so far you have just been hand-waving, and its
hard to learn anything from that.
Clearly, if Lisp code cannot be used to accomplish something that
C code can, then we want to that something in C. So far, you have
said nothing about what that something is. Except for generalities:
get the foreground color at point or some such. Speak about the
specific differences, please.
The lisp code for `foreground-color-at-point' uses `face-at-point'
(which you say you don't see as the problem) and text properties
`read-face-name' and `face'. That is the design - simple, and
perhaps too simple for all purposes.
But I don't see obfuscation there - it's pretty clear what is
going on. It would be clearer perhaps if the doc string said
explicitly that the foreground color returned, if any, is taken
from `face-at-point' or text property `read-face-name' or `face',
in that order.
I'm certainly willing to believe that those three things will not
always provide all possible information about the foreground
color at point. But there is no confusion or hiding of just what
the code does, IMO. It confuses me that you say the code is
confusing, so I ask you, "How so?"
If you become specific in this discussion then there might be
some hope of light, instead of just smoke.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-16 17:47 ` Drew Adams
@ 2013-11-16 18:18 ` Eli Zaretskii
0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-16 18:18 UTC (permalink / raw)
To: Drew Adams; +Cc: michael_heerdegen, 15900
> Date: Sat, 16 Nov 2013 09:47:29 -0800 (PST)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: michael_heerdegen@web.de, 15900@debbugs.gnu.org
>
> > > Please be specific. Just what, in the current context, cannot
> > > be done?
> >
> > What foreground-color-at-point tries to do.
>
> Please be specific.
This is silly. You do know the purpose of foreground-color-at-point,
don't you? Here's a scoop in case you didn't: it's trying to return
the foreground color of the character at point. This is what I say
cannot be reliably done in Lisp: you cannot reliably determine the
colors of any specific character at any specific buffer position.
Now, how more specific than that can one be??
> > It is much better to ask the display engine to provide that
> > information directly.
>
> What information?
The color of the character at point, of course.
> > > please describe the Lisp-level function(s) that you propose to
> > > provide in C
> >
> > foreground-color-at-point, obviously.
>
> I see. And what is the spec of what that function would do?
Same one as the Lisp implementation, except that it will do that
correctly and reliably. IOW, the implementation will change
completely, while the API will remain unchanged, and the contract will
also remain unchanged, except that it will now be always honored.
> What would it do differently?
It would simulate the display, as if Emacs actually did display the
character at point, and return the color produced by that. You cannot
do that in Lisp.
> Just what is the problem you would be trying to solve by moving the
> implementation of this function to C?
The current Lisp code collects face information at or around point,
and tries to deduce from that how the character will be displayed.
Instead, the C implementation will actually display it (without
putting the result on the glass). The result is guaranteed to be
correct. By contrast, the Lisp implementation cannot promise such
correctness, because it in effect tries to reproduce the logic used by
the display engine, and the result is a different implementation, that
cannot possibly be 100% compatible with what the display does.
> I'm sure that if you do that I will understand, and will likely be
> convinced. But so far you have just been hand-waving, and its
> hard to learn anything from that.
There's a lot of experience in hacking the display engine behind that
hand-waving, so you may wish to accept what I'm saying. Or not, I
really don't care much.
> Clearly, if Lisp code cannot be used to accomplish something that
> C code can, then we want to that something in C. So far, you have
> said nothing about what that something is. Except for generalities:
> get the foreground color at point or some such. Speak about the
> specific differences, please.
I can't: you lack too much knowledge for me to discuss the details.
Just read xdisp.c, if you really want to know. I assure you that once
you've done that, it will become crystal clear to you that producing
the color at point is almost trivial on the C level, since code that
simulates display is readily available and widely used by many Emacs
features. Reimplementing that in Lisp is waste of energy.
> The lisp code for `foreground-color-at-point' uses `face-at-point'
> (which you say you don't see as the problem) and text properties
> `read-face-name' and `face'. That is the design - simple, and
> perhaps too simple for all purposes.
Except that a face of a character can come from many different places,
and there could be several different faces in effect at a given buffer
position, some coming from text properties, others from overlays,
still others from display strings, etc. etc. And what if the
character at point is not even displayed, e.g. if it's covered by some
invisibility spec? Why try to untangle all this complexity, when the
display engine already does?
> But I don't see obfuscation there - it's pretty clear what is
> going on.
It's wrong, for starters -- this is why this discussion started. And
it's nowhere near clear, either; but I'm not going to try to convince
you in that.
> It would be clearer perhaps if the doc string said explicitly that
> the foreground color returned, if any, is taken from `face-at-point'
> or text property `read-face-name' or `face', in that order.
As a user of this API, I don't really care. I want to know the
foreground color of the character at point, and I don't care how the
implementation does that. So any clarifications in the doc string
about implementation details will not help me, as a user, to
understand the answer to a simple question: does this API produce what
it promises, or doesn't it?
> I'm certainly willing to believe that those three things will not
> always provide all possible information about the foreground
> color at point.
I'm trying to explain that you shouldn't even _try_ doing that in
Lisp. If you do, you will just waste effort, and likely come up with
unreliable results, because what the display engine does cannot be
reliably reimplemented in Lisp, not with the current design.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
[not found] ` <<83iovsgqhn.fsf@gnu.org>
@ 2013-11-16 22:53 ` Drew Adams
0 siblings, 0 replies; 22+ messages in thread
From: Drew Adams @ 2013-11-16 22:53 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: michael_heerdegen, 15900
Fair enough. Now you've made clear the intent. Thank you for
the effort.
I agree that it would be worthwhile to have the true foreground
color at point, and not just the foreground color of a face at
point. Looking forward to it.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-16 8:44 ` Eli Zaretskii
@ 2013-11-17 2:33 ` Michael Heerdegen
2013-11-17 3:52 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-17 2:33 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 15900
Eli Zaretskii <eliz@gnu.org> writes:
> > That sounds good. Can we just do that?
>
> For some value of "we", yes. If "we" includes me and you, then it
> will have to be you, as my plate is pretty much full these days,
> sorry. In my defense, I can tell that this should be a nice exercise
> for someone who wants to get accustomed to hacking the display engine,
> as it shouldn't be too hard, and there's abundant example code that
> does similar things.
Sorry Eli, but I can't do it. I'm a real noob to C.
> > If faces are among them, I still must figure out if one of these
> > faces changes the foreground.
>
> You can know them in advance, I think. Your example talks about
> links, which use a known face. I presume there are only a few faces
> that needs such a special treatment, which would make the list of them
> quite short.
>
> IOW, why not test against a known list of properties that you want to
> leave alone, instead of digging into their color?
I think the missing information you didn't have is that this is a
general mode, it must work in any Emacs buffer. w3m was only an example
- info, man, and gnus are others. So, testing for hardcoded face or
property lists is not really an option.
> > If not, i.e., if a face e.g. just underlines, I do want to color the
> > text nevertheless.
>
> The face used by links is different not only in its underline, but
> also in its color. If you want links to remain instantly
> recognizable, you should probably keep their appearance intact
> wholesale, not just the underline, otherwise how would the user
> distinguish between a link and underlined text?
Yes, that's what I actually do ;-)
> > Probably I didn't understand what you meant.
>
> More probable that I didn't understand what you meant. Hopefully the
> above tells enough about my misunderstanding to allow you to correct
> me.
I think that you thought that what I do is w3m specific, but it's not.
It should work in any buffer, with any modes. And it should change the
foreground color for every piece of text that has the default foreground
color.
Thanks, and regards,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 2:33 ` Michael Heerdegen
@ 2013-11-17 3:52 ` Eli Zaretskii
2013-11-17 5:35 ` Michael Heerdegen
0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-17 3:52 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: 15900@debbugs.gnu.org, drew.adams@oracle.com
> Date: Sun, 17 Nov 2013 03:33:47 +0100
>
> > > If faces are among them, I still must figure out if one of these
> > > faces changes the foreground.
> >
> > You can know them in advance, I think. Your example talks about
> > links, which use a known face. I presume there are only a few faces
> > that needs such a special treatment, which would make the list of them
> > quite short.
> >
> > IOW, why not test against a known list of properties that you want to
> > leave alone, instead of digging into their color?
>
> I think the missing information you didn't have is that this is a
> general mode, it must work in any Emacs buffer. w3m was only an example
> - info, man, and gnus are others. So, testing for hardcoded face or
> property lists is not really an option.
I still don't see why it isn't an option, even for a general-purpose
mode. The list of faces that need such special treatment must be
quite short, and it can be a defcustom.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 3:52 ` Eli Zaretskii
@ 2013-11-17 5:35 ` Michael Heerdegen
2013-11-17 17:21 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-17 5:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 15900
Eli Zaretskii <eliz@gnu.org> writes:
> > > IOW, why not test against a known list of properties that you want to
> > > leave alone, instead of digging into their color?
> >
> > I think the missing information you didn't have is that this is a
> > general mode, it must work in any Emacs buffer. w3m was only an example
> > - info, man, and gnus are others. So, testing for hardcoded face or
> > property lists is not really an option.
>
> I still don't see why it isn't an option, even for a general-purpose
> mode. The list of faces that need such special treatment must be
> quite short, and it can be a defcustom.
From the user's point of view, yes, it's an option. But you mentioned
it saying it would be easier to realize in Lisp. This is what I have:
(cl-some
(lambda (face) (not (memq (face-foreground face nil t)
`(nil
,(face-attribute 'default :foreground)
"unspecified-fg" "unspecified-bg"))))
(cl-mapcan (lambda (face-or-list) (if (facep face-or-list)
(list face-or-list)
face-or-list))
(list
(get-text-property (point) 'face)
(get-text-property (point) 'font-lock-face))))
For your solution, I can use a different predicate, but would still have
to find all faces at point, no? What do I miss?
Regards,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 5:35 ` Michael Heerdegen
@ 2013-11-17 17:21 ` Eli Zaretskii
0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-17 17:21 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: 15900@debbugs.gnu.org, drew.adams@oracle.com
> Date: Sun, 17 Nov 2013 06:35:03 +0100
>
> For your solution, I can use a different predicate, but would still have
> to find all faces at point, no? What do I miss?
I don't know, and I don't know what am I missing, either.
When you say "all the faces at point", what exactly do you mean by
that? There can only be one 'face' text property at point, so do you
mean faces that come from overlays? If that is what you mean, then
why isn't get-char-property all you need to have your answer? I feel
I'm missing something very basic here.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
[not found] ` <<83d2lzgd04.fsf@gnu.org>
@ 2013-11-17 17:29 ` Drew Adams
2013-11-17 17:47 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Drew Adams @ 2013-11-17 17:29 UTC (permalink / raw)
To: Eli Zaretskii, Michael Heerdegen; +Cc: 15900
> > For your solution, I can use a different predicate, but would
> > still have to find all faces at point, no? What do I miss?
>
> I don't know, and I don't know what am I missing, either.
>
> When you say "all the faces at point", what exactly do you mean by
> that? There can only be one 'face' text property at point, so do
> you mean faces that come from overlays? If that is what you mean,
> then why isn't get-char-property all you need to have your answer?
> I feel I'm missing something very basic here.
I think he means that the value of property `face' (whether from
a text property or an overlay property) can be a list of faces.
Normally, the attributes of the faces in the list are merged for
display. See (elisp) `Special Properties' and (elisp `Overlay
Properties'.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 17:29 ` Drew Adams
@ 2013-11-17 17:47 ` Eli Zaretskii
2013-11-17 22:38 ` Michael Heerdegen
0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-17 17:47 UTC (permalink / raw)
To: Drew Adams; +Cc: michael_heerdegen, 15900
> Date: Sun, 17 Nov 2013 09:29:57 -0800 (PST)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: 15900@debbugs.gnu.org, drew.adams@oracle.com
>
> > When you say "all the faces at point", what exactly do you mean by
> > that? There can only be one 'face' text property at point, so do
> > you mean faces that come from overlays? If that is what you mean,
> > then why isn't get-char-property all you need to have your answer?
> > I feel I'm missing something very basic here.
>
> I think he means that the value of property `face' (whether from
> a text property or an overlay property) can be a list of faces.
Yes, but then you get all that list in a single call to
get-char-property, right? So where's the difficulty in collecting
"all the faces at point"?
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 17:47 ` Eli Zaretskii
@ 2013-11-17 22:38 ` Michael Heerdegen
2013-11-18 3:42 ` Eli Zaretskii
0 siblings, 1 reply; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-17 22:38 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 15900
Hello,
> > I think he means that the value of property `face' (whether from
> > a text property or an overlay property) can be a list of faces.
Indeed. Plus, I want to look at the font-lock-face property.
> Yes, but then you get all that list in a single call to
> get-char-property, right? So where's the difficulty in collecting
> "all the faces at point"?
There's no difficulty. Eli, did you ever read the code snip I had
included? Here it is again:
(cl-some
(lambda (face) (not (memq (face-foreground face nil t)
`(nil
,(face-attribute 'default :foreground)
"unspecified-fg" "unspecified-bg"))))
(cl-mapcan (lambda (face-or-list) (if (facep face-or-list)
(list face-or-list)
face-or-list))
(list
(get-text-property (point) 'face)
(get-text-property (point) 'font-lock-face))))
I think what you mean, and what I do in the code, are quite the same
(except for the predicate maybe). I appreciate your help, but please
tell me if the snipped is ok or if you mean something else, and if so,
what. I've just the feeling that we to talk at cross-purposes.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-17 22:38 ` Michael Heerdegen
@ 2013-11-18 3:42 ` Eli Zaretskii
2013-11-18 7:50 ` Michael Heerdegen
0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2013-11-18 3:42 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: Drew Adams <drew.adams@oracle.com>, 15900@debbugs.gnu.org
> Date: Sun, 17 Nov 2013 23:38:11 +0100
>
> Hello,
>
> > > I think he means that the value of property `face' (whether from
> > > a text property or an overlay property) can be a list of faces.
>
> Indeed. Plus, I want to look at the font-lock-face property.
>
> > Yes, but then you get all that list in a single call to
> > get-char-property, right? So where's the difficulty in collecting
> > "all the faces at point"?
>
> There's no difficulty.
Then I don't understand why you still want to analyze colors instead
of analyzing faces. This is what my suggestion boiled down to:
instead of trying to figure out the foreground color of the text at
point, just compare its face(s) with a list of known faces whose
appearance you don't want to override.
> Eli, did you ever read the code snip I had included?
Of course, I did. But it still talks about colors, something I
suggested to avoid.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-18 3:42 ` Eli Zaretskii
@ 2013-11-18 7:50 ` Michael Heerdegen
0 siblings, 0 replies; 22+ messages in thread
From: Michael Heerdegen @ 2013-11-18 7:50 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 15900
Eli Zaretskii <eliz@gnu.org> writes:
> > There's no difficulty.
>
> Then I don't understand why you still want to analyze colors instead
> of analyzing faces. This is what my suggestion boiled down to:
> instead of trying to figure out the foreground color of the text at
> point, just compare its face(s) with a list of known faces whose
> appearance you don't want to override.
Ok, I think now I understand your point. And I see that my approach has
its difficulties: faces can be customized (a foreground attribute can be
removed or added), faces can even be frame dependent, etc. What I do is
just a heuristic. Mmh, let me think about it. Thanks for your opinion.
Regards,
Michael.
^ permalink raw reply [flat|nested] 22+ messages in thread
* bug#15900: 24.3.50; foreground-color-at-point returns wrong results
2013-11-15 2:04 Michael Heerdegen
2013-11-15 2:47 ` Michael Heerdegen
2013-11-15 8:26 ` Eli Zaretskii
@ 2022-04-22 13:30 ` Lars Ingebrigtsen
2 siblings, 0 replies; 22+ messages in thread
From: Lars Ingebrigtsen @ 2022-04-22 13:30 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 15900
Michael Heerdegen <michael_heerdegen@web.de> writes:
> `foreground-color-at-point' doesn't return the expected result when
> there are several faces at point present.
>
> For example, on the red subject in a Gnus article buffer, or on a blue
> link in w3m, it returns "black". Looking at the code, I see that
> `foreground-color-at-point' uses
>
> (face-at-point)
>
> i.e., it looks only at one face and disregards the others. This is
> especially meaningless when this first face doesn't specify any
> foreground at all.
It looks like this was fixed a couple years later in this commit:
commit 7ccedcb486ee4e37da54dd82a8557c80616d9467
Author: Artur Malabarba <bruce.connor.am@gmail.com>
AuthorDate: Fri Oct 30 15:00:37 2015 +0000
* lisp/faces.el: Refactor common code and fix a bug
(faces--attribute-at-point): New function. Fix a bug when the
face at point is a list of faces and the desired attribute is not
on the first one.
(foreground-color-at-point, background-color-at-point): Use it.
And I've verified that (foreground-color-at-point) seems to return
sensible results in the test cases in Emacs 29, so I'm closing this bug
report.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2022-04-22 13:30 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <<c18e0f8c-e172-497d-b572-69162d77132b@default>
[not found] ` <<83iovsgqhn.fsf@gnu.org>
2013-11-16 22:53 ` bug#15900: 24.3.50; foreground-color-at-point returns wrong results Drew Adams
[not found] <<6bc49739-fae0-4688-a3cc-8bbbc2fe1c04@default>
[not found] ` <<83li0ogv14.fsf@gnu.org>
2013-11-16 17:47 ` Drew Adams
2013-11-16 18:18 ` Eli Zaretskii
[not found] <<87siuyxvw7.fsf@web.de>
[not found] ` <<83li0qhxyl.fsf@gnu.org>
[not found] ` <<878uwpgvh8.fsf@web.de>
[not found] ` <<b0006d1c-b470-4297-a6d7-97d7ed118c28@default>
[not found] ` <<83vbzshggy.fsf@gnu.org>
2013-11-16 16:20 ` Drew Adams
2013-11-16 16:40 ` Eli Zaretskii
[not found] ` <<83y54ohh1n.fsf@gnu.org>
[not found] ` <<87siuv21v8.fsf@web.de>
[not found] ` <<83eh6fhegu.fsf@gnu.org>
[not found] ` <<87eh6flhfc.fsf@web.de>
[not found] ` <<83d2lzgd04.fsf@gnu.org>
2013-11-17 17:29 ` Drew Adams
2013-11-17 17:47 ` Eli Zaretskii
2013-11-17 22:38 ` Michael Heerdegen
2013-11-18 3:42 ` Eli Zaretskii
2013-11-18 7:50 ` Michael Heerdegen
2013-11-15 2:04 Michael Heerdegen
2013-11-15 2:47 ` Michael Heerdegen
2013-11-15 8:26 ` Eli Zaretskii
2013-11-15 22:18 ` Michael Heerdegen
2013-11-16 0:26 ` Drew Adams
2013-11-16 8:57 ` Eli Zaretskii
2013-11-16 8:44 ` Eli Zaretskii
2013-11-17 2:33 ` Michael Heerdegen
2013-11-17 3:52 ` Eli Zaretskii
2013-11-17 5:35 ` Michael Heerdegen
2013-11-17 17:21 ` Eli Zaretskii
2022-04-22 13:30 ` Lars Ingebrigtsen
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.