bug#28771: 26.0.60; A couple space display property feature requests

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Alex-2
I've branched this out from the following thread instead of posting it
there:
https://lists.gnu.org/archive/html/help-gnu-emacs/2017-10/msg00037.html

Here's a few features that would be nice for the pixel-specified space
properties.

1. Specifying the pixel width to the left/center/right of the text area.
   This is helpful (I believe it's necessary if I want it to be robust)
   when one wants to pad either side of a string with the same number of
   pixels and the left side uses (:align-to 0).

   I could use (:width (+ left-fringe left-margin)) for the right
   padding, but this doesn't take into account line-number display, as
   well as the scroll-bar width (if it's on the left).

2. Specifying the pixel position relative to the left or right edge of
   the window. The right edge of the window currently may be the right
   edge of the right fringe or the scroll bar, depending on what side it
   is on. Also, just in the case that in the future the
   fringe/scroll-bar may not be the outermost elements, there should be
   a way to explicitly specify one of the edges.

3. Following from "1." and the help-gnu-emacs thread, it would be nice
   if there was a display property that allowed you to pad a string on
   both sides with a pixel-specified space instead of surrounding it
   with 2 pixel-specified spaces.



Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Alex-2
Alex <[hidden email]> writes:

> 1. Specifying the pixel width to the left/center/right of the text area.
>    This is helpful (I believe it's necessary if I want it to be robust)
>    when one wants to pad either side of a string with the same number of
>    pixels and the left side uses (:align-to 0).
>
>    I could use (:width (+ left-fringe left-margin)) for the right
>    padding, but this doesn't take into account line-number display, as
>    well as the scroll-bar width (if it's on the left).
>
> 2. Specifying the pixel position relative to the left or right edge of
>    the window. The right edge of the window currently may be the right
>    edge of the right fringe or the scroll bar, depending on what side it
>    is on. Also, just in the case that in the future the
>    fringe/scroll-bar may not be the outermost elements, there should be
>    a way to explicitly specify one of the edges.
Here's a diff that implements both #1 and #2:


diff --git a/src/xdisp.c b/src/xdisp.c
index b14b7daf2b..d5fa3a1cfe 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -25210,6 +25210,10 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
    + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
       ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
       : 0)));
+          if (EQ (prop, Qleft_edge))
+            return OK_ALIGN_TO (WINDOW_LEFT_PIXEL_EDGE (it->w));
+          if (EQ (prop, Qright_edge))
+            return OK_ALIGN_TO (WINDOW_RIGHT_PIXEL_EDGE (it->w));
  }
       else
  {
@@ -25223,6 +25227,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
     return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
   if (EQ (prop, Qscroll_bar))
     return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
+  if (EQ (prop, Qleft))
+            return OK_PIXELS (window_box_left_offset (it->w, TEXT_AREA));
+          if (EQ (prop, Qright))
+    return OK_PIXELS (window_box_right_offset (it->w, TEXT_AREA));
+  if (EQ (prop, Qcenter))
+    return OK_PIXELS (window_box_left_offset (it->w, TEXT_AREA)
+ + window_box_width (it->w, TEXT_AREA) / 2);
  }
 
       prop = buffer_local_value (prop, it->w->contents);
@@ -32207,6 +32218,8 @@ They are still logged to the *Messages* buffer.  */);
   DEFSYM (Qspace, "space");
   DEFSYM (Qmargin, "margin");
   DEFSYM (Qpointer, "pointer");
+  DEFSYM (Qleft_edge, "left-edge");
+  DEFSYM (Qright_edge, "right-edge");
   DEFSYM (Qleft_margin, "left-margin");
   DEFSYM (Qright_margin, "right-margin");
   DEFSYM (Qcenter, "center");
Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Eli Zaretskii
In reply to this post by Alex-2
> From: Alex <[hidden email]>
> Date: Mon, 09 Oct 2017 18:20:42 -0600
>
> I've branched this out from the following thread instead of posting it
> there:
> https://lists.gnu.org/archive/html/help-gnu-emacs/2017-10/msg00037.html

Sorry, I've somehow missed that.  I answered there now.

> Here's a few features that would be nice for the pixel-specified space
> properties.
>
> 1. Specifying the pixel width to the left/center/right of the text area.
>    This is helpful (I believe it's necessary if I want it to be robust)
>    when one wants to pad either side of a string with the same number of
>    pixels and the left side uses (:align-to 0).
>
>    I could use (:width (+ left-fringe left-margin)) for the right
>    padding, but this doesn't take into account line-number display, as
>    well as the scroll-bar width (if it's on the left).
>
> 2. Specifying the pixel position relative to the left or right edge of
>    the window. The right edge of the window currently may be the right
>    edge of the right fringe or the scroll bar, depending on what side it
>    is on. Also, just in the case that in the future the
>    fringe/scroll-bar may not be the outermost elements, there should be
>    a way to explicitly specify one of the edges.

These two requests are no in the original message, and I admit I don't
really understand the situations they describe.  Can you elaborate
about them, preferably with an example that shows what is currently
possible and an explanation why the current capabilities are
insufficient?  (Yes, I've seen the patches you propose, but I still
would like to understand the problems better.)

> 3. Following from "1." and the help-gnu-emacs thread, it would be nice
>    if there was a display property that allowed you to pad a string on
>    both sides with a pixel-specified space instead of surrounding it
>    with 2 pixel-specified spaces.

I replied on help-gnu-emacs.  In a nutshell, the 'space' display spec
is a replacing spec, so it cannot be easily used on non-space text.
You could probably have a before-string whose value is a space with
the 'space' display spec, if that makes any difference.  Or you could
use the space-width spec, as described on help-gnu-emacs.

Thanks.



Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Alex-2
Eli Zaretskii <[hidden email]> writes:

>> From: Alex <[hidden email]>
>> Date: Mon, 09 Oct 2017 18:20:42 -0600
>>
>> 1. Specifying the pixel width to the left/center/right of the text area.
>>    This is helpful (I believe it's necessary if I want it to be robust)
>>    when one wants to pad either side of a string with the same number of
>>    pixels and the left side uses (:align-to 0).
>>
>>    I could use (:width (+ left-fringe left-margin)) for the right
>>    padding, but this doesn't take into account line-number display, as
>>    well as the scroll-bar width (if it's on the left).
>>
>> 2. Specifying the pixel position relative to the left or right edge of
>>    the window. The right edge of the window currently may be the right
>>    edge of the right fringe or the scroll bar, depending on what side it
>>    is on. Also, just in the case that in the future the
>>    fringe/scroll-bar may not be the outermost elements, there should be
>>    a way to explicitly specify one of the edges.
>
> These two requests are no in the original message, and I admit I don't
> really understand the situations they describe.  Can you elaborate
> about them, preferably with an example that shows what is currently
> possible and an explanation why the current capabilities are
> insufficient?  (Yes, I've seen the patches you propose, but I still
> would like to understand the problems better.)

Right, they're additions that I felt should go directly to a bug report.

1. There is currently no robust way to specify a pixel width to the
   center or left/right edge of the text area in the 'space' display spec.

   This is because there's no way to tell what's before the left edge of
   the text area. If there's a left-side scroll-bar, then its width
   should be included; but if it's on the right, its width shouldn't be.

   :align-to currently allows for this calculation, but :width doesn't.
   The diff adds the same calculation to :width.

   As for an example, try this in a graphical emacs -Q:

(setq header-line-format
      (propertize
       (concat (propertize " "
                           'display
                           '(space :align-to 0))
               "Test"
               (propertize " "
                           'display
                           '(space :width (+ left-fringe left-margin))))
       'face 'highlight))

 
   By default, the spaces before and after test are equally sized. Even
   if you disable fringe-mode or enable margins (e.g. linum-mode), the
   spaces are equal. However, try setting the scroll-bar to appear on
   the left. Now, the left space is noticeably bigger than the right.

   Changing the last space's :width spec to be '(+ left-fringe
   left-margin scroll-bar)' will now make the spaces equal with a left
   scroll-bar, but unequal with a right scroll-bar.

   If you apply my diff and change the second space's :width spec to be
   'left', then it is correct in both cases.

   I don't know of a good use-case for :width center or :width right,
   but I figured that for completeness I might as well implement them.

2. Suppose you want to align a string to the right edge of the window. I
   couldn't find a way to do this currently since there's no guarantee
   what elements are on the left/right edges. Try:

(setq header-line-format
      (concat (propertize " "
                          'display
                          '(space :align-to (- (+ scroll-bar
                                                  scroll-bar)
                                               4)))
              "Test"))

   This works if there's a right scroll-bar (or if there's none, oddly
   enough), but not if there's a left scroll-bar. Replacing `scroll-bar'
   with `right-fringe' doesn't work if there's a right scroll-bar.

   Replacing the :align-to spec with `right-edge' works in all cases.

   A similar argument can be made for aligning from the left edge.


>> 3. Following from "1." and the help-gnu-emacs thread, it would be nice
>>    if there was a display property that allowed you to pad a string on
>>    both sides with a pixel-specified space instead of surrounding it
>>    with 2 pixel-specified spaces.
>
> I replied on help-gnu-emacs.  In a nutshell, the 'space' display spec
> is a replacing spec, so it cannot be easily used on non-space text.
> You could probably have a before-string whose value is a space with
> the 'space' display spec, if that makes any difference.

Can you put overlays in the header-line? That's my use-case at the
moment.

> use the space-width spec, as described on help-gnu-emacs.

I believe in my case (since the text may contain spaces), that's
equivalent to just the :width spec on the first/last spaces.

#3 is just a convenience request -- it makes dealing with pixel-spaces a
bit easier, but as long as #1 is implemented then I don't think it bring
any new functionality.

Is there currently no display spec that allows for appending/prepending
(or would it be hard to add)? If so, then #3 can be ignored.



Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Eli Zaretskii
> From: Alex <[hidden email]>
> Cc: [hidden email]
> Date: Tue, 10 Oct 2017 11:54:41 -0600
>
> 1. There is currently no robust way to specify a pixel width to the
>    center or left/right edge of the text area in the 'space' display spec.

There's some kind of miscommunication here.  For starters, what do you
mean by "text area"?  For me, "text area" is the area of the window
inside the fringes, see the definition in "(elisp)Frame Layout".  But
you must mean something else, because with my interpretation,
specifying pixel width of the text area makes no sense: it is
determined by the window dimensions.

>    This is because there's no way to tell what's before the left edge of
>    the text area. If there's a left-side scroll-bar, then its width
>    should be included; but if it's on the right, its width shouldn't be.

This is only true for a header-line and mode-line, right?  Because the
rest of the window lines don't change their alignment when the scroll
bar switches sides, as their pixel count starts where the left fringe
ends, whether or not there's a scroll bar to the left of the fringe.

>    As for an example, try this in a graphical emacs -Q:
>
> (setq header-line-format
>       (propertize
>        (concat (propertize " "
>                            'display
>                            '(space :align-to 0))
>                "Test"
>                (propertize " "
>                            'display
>                            '(space :width (+ left-fringe left-margin))))
>        'face 'highlight))
>
>  
>    By default, the spaces before and after test are equally sized.

Again, there's some misunderstanding here, because this example shows
"Text" in the header-line flushed all the way to the left, with only
one space before "Test", to account for the left fringe (if I turn off
fringe-mode, that space disappears).  That's not what you are
describing, so I guess the example needs some change?

>    if you disable fringe-mode or enable margins (e.g. linum-mode), the
>    spaces are equal. However, try setting the scroll-bar to appear on
>    the left. Now, the left space is noticeably bigger than the right.

And again, this is limited to header-line, right?

> 2. Suppose you want to align a string to the right edge of the window.

What is "the right edge of the window" in this context?

> Can you put overlays in the header-line?

No, header-line (as any other Lisp string) can only have text
properties.

> That's my use-case at the moment.

If you are talking only about header lines, maybe the solution (if we
need one) doesn't have to be such a general one.  Are there similar
problems with other lines in a window?

> Is there currently no display spec that allows for appending/prepending
> (or would it be hard to add)?

Appending/prepending what and to what kind of text/object?  Sorry,
maybe it's too late, but I have trouble following your
descriptions :-(




Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Alex-2
Eli Zaretskii <[hidden email]> writes:

>> From: Alex <[hidden email]>
>> Cc: [hidden email]
>> Date: Tue, 10 Oct 2017 11:54:41 -0600
>>
>> 1. There is currently no robust way to specify a pixel width to the
>>    center or left/right edge of the text area in the 'space' display spec.
>
> There's some kind of miscommunication here.  For starters, what do you
> mean by "text area"?  For me, "text area" is the area of the window
> inside the fringes, see the definition in "(elisp)Frame Layout".  But
> you must mean something else, because with my interpretation,
> specifying pixel width of the text area makes no sense: it is
> determined by the window dimensions.

I'm using whatever "(elisp) Pixel Specification" uses. In this case, I
believe it's the start of either column 0 or the line-prefix (see the
gnu-emacs-help thread on that point).

To get an idea evaluate:
(setq header-line-format
      (concat (propertize " "
                          'display
                          '(space :align-to 0))
              "test"))

The start of "test" is what I mean by the "left" of the "text-area".
The point here is that :align-to has access to some pixel positions
using `left', `center', and `right'; the diff above allows :width to
return a stretch space as wide as that position.

>>    This is because there's no way to tell what's before the left edge of
>>    the text area. If there's a left-side scroll-bar, then its width
>>    should be included; but if it's on the right, its width shouldn't be.
>
> This is only true for a header-line and mode-line, right?  Because the
> rest of the window lines don't change their alignment when the scroll
> bar switches sides, as their pixel count starts where the left fringe
> ends, whether or not there's a scroll bar to the left of the fringe.

I believe so. I haven't really played around with these specs outside of
the header-line.

>>    As for an example, try this in a graphical emacs -Q:
>>
>> (setq header-line-format
>>       (propertize
>>        (concat (propertize " "
>>                            'display
>>                            '(space :align-to 0))
>>                "Test"
>>                (propertize " "
>>                            'display
>>                            '(space :width (+ left-fringe left-margin))))
>>        'face 'highlight))
>>
>>  
>>    By default, the spaces before and after test are equally sized.
>
> Again, there's some misunderstanding here, because this example shows
> "Text" in the header-line flushed all the way to the left, with only
> one space before "Test", to account for the left fringe (if I turn off
> fringe-mode, that space disappears).  That's not what you are
> describing, so I guess the example needs some change?

So you don't see the space after "Test"? Make sure the background of the
'highlight face is different than the 'header-line background to see the
space clearly. I mentioned `emacs -Q' since the face background should
be different there. Any face with a different background suffices.

For clarification, what you should see is 1 space before and 1 space
after "Test", each the same pixel width as the left fringe.

What should happen is that if you toggle the fringes/margins, then the
spaces shrink and grow accordingly, with the exception of faulty
scroll-bar width calculation. Using '(space :width left) does not have
this faulty calculation.

The point is that the before/after stretch whitespace must have equal
lengths at all times, regardless of fringe/margin/line-number/scroll-bar
statuses.

> And again, this is limited to header-line, right?

I believe so (and the mode-line).

>> 2. Suppose you want to align a string to the right edge of the window.
>
> What is "the right edge of the window" in this context?

The very ends of the window shown in the art in "(elisp) Window Sizes"
(i.e., past RD). Specifically, whatever is returned by
WINDOW_LEFT_PIXEL_EDGE and WINDOW_RIGHT_PIXEL_EDGE is what I'm referring
to.

>> That's my use-case at the moment.
>
> If you are talking only about header lines, maybe the solution (if we
> need one) doesn't have to be such a general one.  Are there similar
> problems with other lines in a window?

Maybe it doesn't, but since the general case is simple enough to
implement, why not do it? I think it fits in with the existing code well
enough.

I don't know of any similar problems, but I don't use these
:align-to/:width outside of the header-line.

>> Is there currently no display spec that allows for appending/prepending
>> (or would it be hard to add)?
>
> Appending/prepending what and to what kind of text/object?  Sorry,
> maybe it's too late, but I have trouble following your
> descriptions :-(

Sorry, I should have been more clear -- appending/prepending a
pixel-specified space string to an arbitrary string. Essentially a
(concat <pixel-space> string <pixel-space>).



Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Eli Zaretskii
> From: Alex <[hidden email]>
> Cc: [hidden email]
> Date: Tue, 10 Oct 2017 15:27:03 -0600
>
> To get an idea evaluate:
> (setq header-line-format
>       (concat (propertize " "
>                           'display
>                           '(space :align-to 0))
>               "test"))
>
> The start of "test" is what I mean by the "left" of the "text-area".

Actually, my understanding is that 'left' is the number of pixels from
the left edge of the window to the start of "Test".  IOW, it's a pixel
width, not a position.  Right?

> For clarification, what you should see is 1 space before and 1 space
> after "Test", each the same pixel width as the left fringe.

Actually, by "space" you mean space displayed with 'highlight' face,
right?  Because there's a lot of "other" space in the header-line, but
you don't mean that space.  That's what tripped me originally.

> What should happen is that if you toggle the fringes/margins, then the
> spaces shrink and grow accordingly, with the exception of faulty
> scroll-bar width calculation. Using '(space :width left) does not have
> this faulty calculation.
>
> The point is that the before/after stretch whitespace must have equal
> lengths at all times, regardless of fringe/margin/line-number/scroll-bar
> statuses.
>
> > And again, this is limited to header-line, right?
>
> I believe so (and the mode-line).

So what is the purpose of having the header-line or mode-line text
move relative to buffer text when some window decorations are
enabled/disabled or moved from left to right?  IOW, why did you need
the "space" on both sides of "Test" to be of the same pixel width,
independently of the scroll-bar position?  Right now, "Test" moves
together with buffer text, and so is always aligned with it, no matter
which side is the scroll bar on.  Why is that not TRT?

> >> 2. Suppose you want to align a string to the right edge of the window.
> >
> > What is "the right edge of the window" in this context?
>
> The very ends of the window shown in the art in "(elisp) Window Sizes"
> (i.e., past RD).

Again, why do you need that?  Also, why cannot you use the existing
functions that return dimensions of the window and its decorations?

> > If you are talking only about header lines, maybe the solution (if we
> > need one) doesn't have to be such a general one.  Are there similar
> > problems with other lines in a window?
>
> Maybe it doesn't, but since the general case is simple enough to
> implement, why not do it? I think it fits in with the existing code well
> enough.

It fits with the code, but not with the conceptual framework.  The
:align-to spec starts counting pixels at the left edge of the text
area, whereas with the new symbols you introduce it will start at a
different point.  That's confusing.

> Sorry, I should have been more clear -- appending/prepending a
> pixel-specified space string to an arbitrary string. Essentially a
> (concat <pixel-space> string <pixel-space>).

The only way to generate a stretch of whitespace is to use a 'space'
display spec.  So no, we don't have that.  The display engine cannot
display a glyph of a character with prepended or appended space,
because we ask the font back-end to produce the glyph metrics for us,
and those metrics come from the font.  That is why we must produce
stretch glyphs separately.



Reply | Threaded
Open this post in threaded view
|

bug#28771: 26.0.60; A couple space display property feature requests

Eli Zaretskii
Would your problems be solved if we provided a function to return the
pixel-width of all the window decorations on the specified side (left
or right) of the window?  Then you could use this function in your
display specs to produce the whitespace of the width you want.