unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* `vertical-motion', `goto-line' set point to invisible text
@ 2011-07-03  2:59 Dmitry Kurochkin
  2011-07-03  6:55 ` Eli Zaretskii
  2011-07-03 14:50 ` Stefan Monnier
  0 siblings, 2 replies; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-03  2:59 UTC (permalink / raw)
  To: emacs-devel

Hi all.

While working on notmuch [1] emacs client, I stumbled upon an unexpected
behavior: `beginning-of-visual-line' places point to invisible text in
the beginning to the line.  I.e. you have:

  line1
  line2    <--- this line is not visible
  line3    <--- point is on this line

in this case, `beginning-of-visual-line' will set the position to start
of line2 (which is invisible), not line3.  It differs from what
`move-beginning-of-line' and even does not match
`line-beginning-position'.  `beginning-of-visual-line' uses
`vertical-motion' to do the job.  `goto-line' has a similar behavior.  I
believe there are more functions like this.

This does not look right to me.  I expect these functions never set
point inside invisible text and there should be some general way to
protect from this.  But perhaps I am wrong and we have to manually skip
all invisible text forward after any point move?

Here is a small test to demonstrate the issue:

(progn (message "test begin")
       (switch-to-buffer "test")
       (insert "line1\nline2\nline3\n")
       (goto-line 2)
       (put-text-property (line-beginning-position)
                          (line-beginning-position 2)
                          'invisible 'invis1)
       (goto-line 3)
       (message "point #1: %s" (point))
       (add-to-invisibility-spec 'invis1)
       (move-beginning-of-line nil)
       (message "point #2: %s" (point))
       (vertical-motion 0)
       (message "point #3: %s, invisible-p: %s" (point) (invisible-p (point)))
       (message "test end"))

Regards,
  Dmitry

[1] http://notmuchmail.org/



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03  2:59 `vertical-motion', `goto-line' set point to invisible text Dmitry Kurochkin
@ 2011-07-03  6:55 ` Eli Zaretskii
  2011-07-03  7:31   ` Dmitry Kurochkin
  2011-07-03 14:50 ` Stefan Monnier
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-03  6:55 UTC (permalink / raw)
  To: Dmitry Kurochkin; +Cc: emacs-devel

> From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> Date: Sun, 03 Jul 2011 06:59:49 +0400
> 
> While working on notmuch [1] emacs client, I stumbled upon an unexpected
> behavior: `beginning-of-visual-line' places point to invisible text in
> the beginning to the line.  I.e. you have:
> 
>   line1
>   line2    <--- this line is not visible
>   line3    <--- point is on this line
> 
> in this case, `beginning-of-visual-line' will set the position to start
> of line2 (which is invisible), not line3.  It differs from what
> `move-beginning-of-line' and even does not match
> `line-beginning-position'.  `beginning-of-visual-line' uses
> `vertical-motion' to do the job.  `goto-line' has a similar behavior.  I
> believe there are more functions like this.

See the node "Invisible Text" in the ELisp manual.  Some functions are
explicitly programmed to special behavior in the vicinity of invisible
text, others aren't.

> This does not look right to me.  I expect these functions never set
> point inside invisible text and there should be some general way to
> protect from this.

Are you sure you don't mix invisible with intangible?  Invisible means
just that: not shown on the screen.  It doesn't mean point cannot
enter the invisible portion.  Emacs does try to move point out of
invisible range of text, but it does so in its command loop, _after_
the cursor motion functions and the display engine did their job.  So
your test program just shows that cursor motion has no problem getting
into the invisible region, which I think is not a bug.

> But perhaps I am wrong and we have to manually skip
> all invisible text forward after any point move?

Yes.

There is something strange in how we behave in this example, though.
To see it, modify your test program to make each line's 1st character
different from other lines.  Then, after the program ends, C-a on the
3rd line and type "C-x =": Emacs says the character at point is the
first character of the invisible line 2, which seems wrong, as the
display shows line 3.  In fact, you cannot place point on the 1st
character of line 3: C-b from the 2nd character of line 3 gets you to
the 1st character of line 2!  I think this happens because the range
of invisible characters includes the newline of line 2.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03  6:55 ` Eli Zaretskii
@ 2011-07-03  7:31   ` Dmitry Kurochkin
  2011-07-03 13:33     ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-03  7:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Hi Eli.

On Sun, 03 Jul 2011 02:55:31 -0400, Eli Zaretskii <eliz@gnu.org> wrote:
> > From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> > Date: Sun, 03 Jul 2011 06:59:49 +0400
> > 
> > While working on notmuch [1] emacs client, I stumbled upon an unexpected
> > behavior: `beginning-of-visual-line' places point to invisible text in
> > the beginning to the line.  I.e. you have:
> > 
> >   line1
> >   line2    <--- this line is not visible
> >   line3    <--- point is on this line
> > 
> > in this case, `beginning-of-visual-line' will set the position to start
> > of line2 (which is invisible), not line3.  It differs from what
> > `move-beginning-of-line' and even does not match
> > `line-beginning-position'.  `beginning-of-visual-line' uses
> > `vertical-motion' to do the job.  `goto-line' has a similar behavior.  I
> > believe there are more functions like this.
> 
> See the node "Invisible Text" in the ELisp manual.  Some functions are
> explicitly programmed to special behavior in the vicinity of invisible
> text, others aren't.
> 

Thanks for the hint.

> > This does not look right to me.  I expect these functions never set
> > point inside invisible text and there should be some general way to
> > protect from this.
> 
> Are you sure you don't mix invisible with intangible?

Yes, I know invisible is not the same as intangible.

>  Invisible means
> just that: not shown on the screen.  It doesn't mean point cannot
> enter the invisible portion.  Emacs does try to move point out of
> invisible range of text, but it does so in its command loop, _after_
> the cursor motion functions and the display engine did their job.

I guess that explains why in notmuch (which has multiple lines hidden,
i.e. email body) I hit C-a, then M-: "(point)" I get X, then if I do M-:
"(point)" again, I get Y.  Is there a way to ask Emacs to sync point to
visible position, so that I do not have to do it by hand?

>  So
> your test program just shows that cursor motion has no problem getting
> into the invisible region, which I think is not a bug.
> 
> > But perhaps I am wrong and we have to manually skip
> > all invisible text forward after any point move?
> 
> Yes.
> 

Thanks for your answers.

> There is something strange in how we behave in this example, though.
> To see it, modify your test program to make each line's 1st character
> different from other lines.  Then, after the program ends, C-a on the
> 3rd line and type "C-x =": Emacs says the character at point is the
> first character of the invisible line 2, which seems wrong, as the
> display shows line 3.  In fact, you cannot place point on the 1st
> character of line 3: C-b from the 2nd character of line 3 gets you to
> the 1st character of line 2!  I think this happens because the range
> of invisible characters includes the newline of line 2.

Indeed, I did not notice that when testing in notmuch (I guess because
there are many lines hidden).

`backward-char' steps 1 position as expected.  I.e. M-: (progn
(backward-char) (point)) works fine.  But after that M-: (point) returns
another position which corresponds to the beginning of the hidden line.
I guess this has to do command loop I know nothing about.  IMO Emacs
should not touch the point in this case, because it is already visible.
Sounds like a bug to me.

Regards,
  Dmitry



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03  7:31   ` Dmitry Kurochkin
@ 2011-07-03 13:33     ` Eli Zaretskii
  2011-07-04  2:08       ` Dmitry Kurochkin
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-03 13:33 UTC (permalink / raw)
  To: Dmitry Kurochkin; +Cc: emacs-devel

> From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> Cc: emacs-devel@gnu.org
> Date: Sun, 03 Jul 2011 11:31:23 +0400
> 
> Is there a way to ask Emacs to sync point to visible position, so
> that I do not have to do it by hand?

Not sure what that means.  Can you explain more about what you are
looking for?

> I.e. M-: (progn (backward-char) (point)) works fine.  But after that
> M-: (point) returns another position which corresponds to the
> beginning of the hidden line.  I guess this has to do command loop I
> know nothing about.

When a command finishes and Emacs is idle (i.e. has nothing else to
do), it examines the position of point.  If it finds that point is on
some character where it shouldn't be, it moves point to the next
"suitable" character in the direction of last move.  Text where point
shouldn't be includes: invisible text, non-base character that belongs
to a composed character, and text covered by a "replacing" `display'
property.

> IMO Emacs should not touch the point in this case, because it is
> already visible.  Sounds like a bug to me.

If no one comes up with a plausible explanation until tomorrow, feel
free to submit a bug report.

Btw, I just tried past releases, and Emacs 21.4 didn't have this
problem, but Emacs 22.3 did.  I guess that's a side effect of point
adjustment described above, which Emacs 21.4 didn't have: in Emacs
21.4, the cursor stays put for several C-f or C-b commands, as long as
point is on invisible text.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03  2:59 `vertical-motion', `goto-line' set point to invisible text Dmitry Kurochkin
  2011-07-03  6:55 ` Eli Zaretskii
@ 2011-07-03 14:50 ` Stefan Monnier
  2011-07-03 15:14   ` Eli Zaretskii
  1 sibling, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2011-07-03 14:50 UTC (permalink / raw)
  To: Dmitry Kurochkin; +Cc: emacs-devel

> While working on notmuch [1] emacs client, I stumbled upon an unexpected
> behavior: `beginning-of-visual-line' places point to invisible text in
> the beginning to the line.  I.e. you have:

>   line1
>   line2    <--- this line is not visible
>   line3    <--- point is on this line

> in this case, `beginning-of-visual-line' will set the position to start
> of line2 (which is invisible), not line3.  It differs from what
> `move-beginning-of-line' and even does not match
> `line-beginning-position'.  `beginning-of-visual-line' uses
> `vertical-motion' to do the job.  `goto-line' has a similar behavior.  I
> believe there are more functions like this.

> This does not look right to me.  I expect these functions never set
> point inside invisible text and there should be some general way to
> protect from this.

AFAIK none of those positions are *inside* invisible text (remember
that point is always between two chars).


        Stefan



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03 14:50 ` Stefan Monnier
@ 2011-07-03 15:14   ` Eli Zaretskii
  2011-07-04 14:01     ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-03 15:14 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dmitry.kurochkin, emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sun, 03 Jul 2011 10:50:21 -0400
> Cc: emacs-devel@gnu.org
> 
> AFAIK none of those positions are *inside* invisible text

Try "M-x describe-text-properties RET", and you will see this isn't
true.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03 13:33     ` Eli Zaretskii
@ 2011-07-04  2:08       ` Dmitry Kurochkin
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-04  2:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On Sun, 03 Jul 2011 16:33:54 +0300, Eli Zaretskii <eliz@gnu.org> wrote:
> > From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> > Cc: emacs-devel@gnu.org
> > Date: Sun, 03 Jul 2011 11:31:23 +0400
> > 
> > Is there a way to ask Emacs to sync point to visible position, so
> > that I do not have to do it by hand?
> 
> Not sure what that means.  Can you explain more about what you are
> looking for?
> 

I am looking for a function that does something like what you described
below.  I.e. moves point to the next suitable character in the given
direction.  At the moment I do it with smth like:

  ;; if point is invisible, skip forward to visible text
  (while (invisible-p p)
    (setq p (next-single-char-property-change p 'invisible)))

> > I.e. M-: (progn (backward-char) (point)) works fine.  But after that
> > M-: (point) returns another position which corresponds to the
> > beginning of the hidden line.  I guess this has to do command loop I
> > know nothing about.
> 
> When a command finishes and Emacs is idle (i.e. has nothing else to
> do), it examines the position of point.  If it finds that point is on
> some character where it shouldn't be, it moves point to the next
> "suitable" character in the direction of last move.  Text where point
> shouldn't be includes: invisible text, non-base character that belongs
> to a composed character, and text covered by a "replacing" `display'
> property.
> 

Thanks for the detailed explanation.

> > IMO Emacs should not touch the point in this case, because it is
> > already visible.  Sounds like a bug to me.
> 
> If no one comes up with a plausible explanation until tomorrow, feel
> free to submit a bug report.
> 

ok

> Btw, I just tried past releases, and Emacs 21.4 didn't have this
> problem, but Emacs 22.3 did.  I guess that's a side effect of point
> adjustment described above, which Emacs 21.4 didn't have: in Emacs
> 21.4, the cursor stays put for several C-f or C-b commands, as long as
> point is on invisible text.

I will put a reference in the bug report.

Regards,
  Dmitry



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-03 15:14   ` Eli Zaretskii
@ 2011-07-04 14:01     ` Stefan Monnier
  2011-07-04 15:14       ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2011-07-04 14:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dmitry.kurochkin, emacs-devel

>> AFAIK none of those positions are *inside* invisible text
> Try "M-x describe-text-properties RET", and you will see this isn't
> true.

AFAIK, describe-text-properties describes the properties of the char
*after* point, so if you're at the beginning of invisible text (yet not
inside it), describe-text-properties will show the `invisible' property.


        Stefan



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-04 14:01     ` Stefan Monnier
@ 2011-07-04 15:14       ` Eli Zaretskii
  2011-07-04 18:10         ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-04 15:14 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dmitry.kurochkin, emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: dmitry.kurochkin@gmail.com,  emacs-devel@gnu.org
> Date: Mon, 04 Jul 2011 10:01:10 -0400
> 
> >> AFAIK none of those positions are *inside* invisible text
> > Try "M-x describe-text-properties RET", and you will see this isn't
> > true.
> 
> AFAIK, describe-text-properties describes the properties of the char
> *after* point, so if you're at the beginning of invisible text (yet not
> inside it), describe-text-properties will show the `invisible' property.

So how many character positions are invisible after this:

       (insert "line1\nline2\nline3\n")
       (goto-line 2)
       (put-text-property (line-beginning-position)
                          (line-beginning-position 2)
                          'invisible 'invis1)

?

Also, since we show cursor on the character after point, which is
invisible, what exactly do we mean to achieve in this case by
adjust_point_for_property?

Finally, what do you think of this:

  (progn (switch-to-buffer "test")
	 (insert "aline1\nbline2\ncline3\n")
	 (goto-line 2)
	 (put-text-property (line-beginning-position)
			    (line-beginning-position 2)
			    'invisible 'invis1)
	 (add-to-invisibility-spec 'invis1)
	 (goto-char (point-max)))

Eval this in *scratch*, then type "C-p C-x =".  You will see that
Emacs reports that point is position 8 and the character at point is
`b', whereas what is shown (correctly) under the cursor is `c' whose
buffer position is 15.  Do you think this is correct behavior?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-04 15:14       ` Eli Zaretskii
@ 2011-07-04 18:10         ` Stefan Monnier
  2011-07-04 20:06           ` Eli Zaretskii
                             ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Stefan Monnier @ 2011-07-04 18:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dmitry.kurochkin, emacs-devel

>> >> AFAIK none of those positions are *inside* invisible text
>> > Try "M-x describe-text-properties RET", and you will see this isn't
>> > true.
>> AFAIK, describe-text-properties describes the properties of the char
>> *after* point, so if you're at the beginning of invisible text (yet not
>> inside it), describe-text-properties will show the `invisible' property.

> So how many character positions are invisible after this:
>        (insert "line1\nline2\nline3\n")
>        (goto-line 2)
>        (put-text-property (line-beginning-position)
>                           (line-beginning-position 2)
>                           'invisible 'invis1)
> ?

Without running the code, I'd say 6 ("line2\n").  Why?

> Also, since we show cursor on the character after point,

By default, yes.

> which is invisible, what exactly do we mean to achieve in this case by
> adjust_point_for_property?

The intention is just to avoid having point in the middle of invisible
text and have things like C-f and C-b appear to do nothing (because
they only move within some invisible text chunk).
Also it's so that inserting text will usually result in this text being
visible (and hopefully inserted right where the cursor was displayed).

None of those properties are guaranteed by adjust_point_for_property,
sadly, but it's the motivation behind it.

> Finally, what do you think of this:

>   (progn (switch-to-buffer "test")
> 	 (insert "aline1\nbline2\ncline3\n")
> 	 (goto-line 2)
> 	 (put-text-property (line-beginning-position)
> 			    (line-beginning-position 2)
> 			    'invisible 'invis1)
> 	 (add-to-invisibility-spec 'invis1)
> 	 (goto-char (point-max)))

> Eval this in *scratch*, then type "C-p C-x =".  You will see that
> Emacs reports that point is position 8 and the character at point is
> `b', whereas what is shown (correctly) under the cursor is `c' whose
> buffer position is 15.  Do you think this is correct behavior?

In this area, I don't think there's a clear cut definition of what is
correct and what is not.  Depending on what is being done some behavior
is preferable, and in other cases another behavior is preferable.
If point is anywhere between "bline2\n" the display will be identical,
so the fact that the cursor is drawn over the "c" that follows it does
not necessarily imply that point should be "at the end of "bline2\n",
since the cursor is also drawn right after the "aline1\n" and by that
logic point should be at the beginning of "bline2\n".

What tilts the decision one way rather than the other here is the
stickiness: for all positions other than right before "bline2\n",
self-insert-command at point will result in an invisible char being
inserted, which is very rarely the intention of the user.  Of course, in
a read-only buffer this consideration may not matter, but note that this
stickiness issue also happens to be a way by which Elisp packages can
control in which part of the invisible text point will end up.


        Stefan



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-04 18:10         ` Stefan Monnier
@ 2011-07-04 20:06           ` Eli Zaretskii
  2011-07-04 20:06           ` Eli Zaretskii
  2011-07-05  2:22           ` Dmitry Kurochkin
  2 siblings, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-04 20:06 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dmitry.kurochkin, emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: dmitry.kurochkin@gmail.com,  emacs-devel@gnu.org
> Date: Mon, 04 Jul 2011 14:10:11 -0400
> 
> >> >> AFAIK none of those positions are *inside* invisible text
> >> > Try "M-x describe-text-properties RET", and you will see this isn't
> >> > true.
> >> AFAIK, describe-text-properties describes the properties of the char
> >> *after* point, so if you're at the beginning of invisible text (yet not
> >> inside it), describe-text-properties will show the `invisible' property.
> 
> > So how many character positions are invisible after this:
> >        (insert "line1\nline2\nline3\n")
> >        (goto-line 2)
> >        (put-text-property (line-beginning-position)
> >                           (line-beginning-position 2)
> >                           'invisible 'invis1)
> > ?
> 
> Without running the code, I'd say 6 ("line2\n").  Why?

Because with your reasoning it's only 5.

> >   (progn (switch-to-buffer "test")
> > 	 (insert "aline1\nbline2\ncline3\n")
> > 	 (goto-line 2)
> > 	 (put-text-property (line-beginning-position)
> > 			    (line-beginning-position 2)
> > 			    'invisible 'invis1)
> > 	 (add-to-invisibility-spec 'invis1)
> > 	 (goto-char (point-max)))
> 
> > Eval this in *scratch*, then type "C-p C-x =".  You will see that
> > Emacs reports that point is position 8 and the character at point is
> > `b', whereas what is shown (correctly) under the cursor is `c' whose
> > buffer position is 15.  Do you think this is correct behavior?
> 
> In this area, I don't think there's a clear cut definition of what is
> correct and what is not.

??? How could having a cursor on `c' and reporting it on `b' be
"correct" by any measure?

> If point is anywhere between "bline2\n" the display will be identical,
> so the fact that the cursor is drawn over the "c" that follows it does
> not necessarily imply that point should be "at the end of "bline2\n",
> since the cursor is also drawn right after the "aline1\n" and by that
> logic point should be at the beginning of "bline2\n".

But what about the fact that you cannot have point at position 15,
which is outside the invisible portion?  How can that be anything but
a bug?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-04 18:10         ` Stefan Monnier
  2011-07-04 20:06           ` Eli Zaretskii
@ 2011-07-04 20:06           ` Eli Zaretskii
  2011-07-05  2:22           ` Dmitry Kurochkin
  2 siblings, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-04 20:06 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dmitry.kurochkin, emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: dmitry.kurochkin@gmail.com,  emacs-devel@gnu.org
> Date: Mon, 04 Jul 2011 14:10:11 -0400
> 
> >> >> AFAIK none of those positions are *inside* invisible text
> >> > Try "M-x describe-text-properties RET", and you will see this isn't
> >> > true.
> >> AFAIK, describe-text-properties describes the properties of the char
> >> *after* point, so if you're at the beginning of invisible text (yet not
> >> inside it), describe-text-properties will show the `invisible' property.
> 
> > So how many character positions are invisible after this:
> >        (insert "line1\nline2\nline3\n")
> >        (goto-line 2)
> >        (put-text-property (line-beginning-position)
> >                           (line-beginning-position 2)
> >                           'invisible 'invis1)
> > ?
> 
> Without running the code, I'd say 6 ("line2\n").  Why?

Because with your reasoning it's only 5.

> >   (progn (switch-to-buffer "test")
> > 	 (insert "aline1\nbline2\ncline3\n")
> > 	 (goto-line 2)
> > 	 (put-text-property (line-beginning-position)
> > 			    (line-beginning-position 2)
> > 			    'invisible 'invis1)
> > 	 (add-to-invisibility-spec 'invis1)
> > 	 (goto-char (point-max)))
> 
> > Eval this in *scratch*, then type "C-p C-x =".  You will see that
> > Emacs reports that point is position 8 and the character at point is
> > `b', whereas what is shown (correctly) under the cursor is `c' whose
> > buffer position is 15.  Do you think this is correct behavior?
> 
> In this area, I don't think there's a clear cut definition of what is
> correct and what is not.

??? How could having a cursor on `c' and reporting it on `b' be
"correct" by any measure?

> If point is anywhere between "bline2\n" the display will be identical,
> so the fact that the cursor is drawn over the "c" that follows it does
> not necessarily imply that point should be "at the end of "bline2\n",
> since the cursor is also drawn right after the "aline1\n" and by that
> logic point should be at the beginning of "bline2\n".

But what about the fact that you cannot have point at position 15,
which is outside the invisible portion?  How can that be anything but
a bug?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-04 18:10         ` Stefan Monnier
  2011-07-04 20:06           ` Eli Zaretskii
  2011-07-04 20:06           ` Eli Zaretskii
@ 2011-07-05  2:22           ` Dmitry Kurochkin
  2011-07-05  2:55             ` Eli Zaretskii
  2011-07-05  3:52             ` Dmitry Kurochkin
  2 siblings, 2 replies; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-05  2:22 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: emacs-devel

On Mon, 04 Jul 2011 14:10:11 -0400, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> >> >> AFAIK none of those positions are *inside* invisible text
> >> > Try "M-x describe-text-properties RET", and you will see this isn't
> >> > true.
> >> AFAIK, describe-text-properties describes the properties of the char
> >> *after* point, so if you're at the beginning of invisible text (yet not
> >> inside it), describe-text-properties will show the `invisible' property.
> 
> > So how many character positions are invisible after this:
> >        (insert "line1\nline2\nline3\n")
> >        (goto-line 2)
> >        (put-text-property (line-beginning-position)
> >                           (line-beginning-position 2)
> >                           'invisible 'invis1)
> > ?
> 
> Without running the code, I'd say 6 ("line2\n").  Why?
> 
> > Also, since we show cursor on the character after point,
> 
> By default, yes.
> 
> > which is invisible, what exactly do we mean to achieve in this case by
> > adjust_point_for_property?
> 
> The intention is just to avoid having point in the middle of invisible
> text and have things like C-f and C-b appear to do nothing (because
> they only move within some invisible text chunk).
> Also it's so that inserting text will usually result in this text being
> visible (and hopefully inserted right where the cursor was displayed).
> 
> None of those properties are guaranteed by adjust_point_for_property,
> sadly, but it's the motivation behind it.
> 
> > Finally, what do you think of this:
> 
> >   (progn (switch-to-buffer "test")
> > 	 (insert "aline1\nbline2\ncline3\n")
> > 	 (goto-line 2)
> > 	 (put-text-property (line-beginning-position)
> > 			    (line-beginning-position 2)
> > 			    'invisible 'invis1)
> > 	 (add-to-invisibility-spec 'invis1)
> > 	 (goto-char (point-max)))
> 
> > Eval this in *scratch*, then type "C-p C-x =".  You will see that
> > Emacs reports that point is position 8 and the character at point is
> > `b', whereas what is shown (correctly) under the cursor is `c' whose
> > buffer position is 15.  Do you think this is correct behavior?
> 
> In this area, I don't think there's a clear cut definition of what is
> correct and what is not.  Depending on what is being done some behavior
> is preferable, and in other cases another behavior is preferable.
> If point is anywhere between "bline2\n" the display will be identical,
> so the fact that the cursor is drawn over the "c" that follows it does
> not necessarily imply that point should be "at the end of "bline2\n",
> since the cursor is also drawn right after the "aline1\n" and by that
> logic point should be at the beginning of "bline2\n".
> 
> What tilts the decision one way rather than the other here is the
> stickiness: for all positions other than right before "bline2\n",
> self-insert-command at point will result in an invisible char being
> inserted, which is very rarely the intention of the user.  Of course, in
> a read-only buffer this consideration may not matter, but note that this
> stickiness issue also happens to be a way by which Elisp packages can
> control in which part of the invisible text point will end up.
> 

That makes sense.  Thank you.

Perhaps in case of notmuch the best way is to hide the preceding newline
character instead of the trailing one.  This way there will always be a
visible newline between different messages and cursor-moving functions
(e.g. `vertical-motion') should not move beyond it.

Still looking for an answer to the following question earlier in this
thread:

    I am looking for a function that does something like what you described
    below.  I.e. moves point to the next suitable character in the given
    direction.  At the moment I do it with smth like:

      ;; if point is invisible, skip forward to visible text
      (while (invisible-p p)
        (setq p (next-single-char-property-change p 'invisible)))

Regards,
  Dmitry

> 
>         Stefan



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-05  2:22           ` Dmitry Kurochkin
@ 2011-07-05  2:55             ` Eli Zaretskii
  2011-07-05  3:52             ` Dmitry Kurochkin
  1 sibling, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-05  2:55 UTC (permalink / raw)
  To: Dmitry Kurochkin; +Cc: monnier, emacs-devel

> From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> Date: Tue, 05 Jul 2011 06:22:56 +0400
> Cc: emacs-devel@gnu.org
> 
> Still looking for an answer to the following question earlier in this
> thread:
> 
>     I am looking for a function that does something like what you described
>     below.  I.e. moves point to the next suitable character in the given
>     direction.  At the moment I do it with smth like:
> 
>       ;; if point is invisible, skip forward to visible text
>       (while (invisible-p p)
>         (setq p (next-single-char-property-change p 'invisible)))

I think your code is the right way.  I don't think anything
ready-to-use exists.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-05  2:22           ` Dmitry Kurochkin
  2011-07-05  2:55             ` Eli Zaretskii
@ 2011-07-05  3:52             ` Dmitry Kurochkin
  2011-07-05  7:56               ` Eli Zaretskii
  1 sibling, 1 reply; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-05  3:52 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: emacs-devel

On Tue, 05 Jul 2011 06:22:56 +0400, Dmitry Kurochkin <dmitry.kurochkin@gmail.com> wrote:
> On Mon, 04 Jul 2011 14:10:11 -0400, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> > >> >> AFAIK none of those positions are *inside* invisible text
> > >> > Try "M-x describe-text-properties RET", and you will see this isn't
> > >> > true.
> > >> AFAIK, describe-text-properties describes the properties of the char
> > >> *after* point, so if you're at the beginning of invisible text (yet not
> > >> inside it), describe-text-properties will show the `invisible' property.
> > 
> > > So how many character positions are invisible after this:
> > >        (insert "line1\nline2\nline3\n")
> > >        (goto-line 2)
> > >        (put-text-property (line-beginning-position)
> > >                           (line-beginning-position 2)
> > >                           'invisible 'invis1)
> > > ?
> > 
> > Without running the code, I'd say 6 ("line2\n").  Why?
> > 
> > > Also, since we show cursor on the character after point,
> > 
> > By default, yes.
> > 
> > > which is invisible, what exactly do we mean to achieve in this case by
> > > adjust_point_for_property?
> > 
> > The intention is just to avoid having point in the middle of invisible
> > text and have things like C-f and C-b appear to do nothing (because
> > they only move within some invisible text chunk).
> > Also it's so that inserting text will usually result in this text being
> > visible (and hopefully inserted right where the cursor was displayed).
> > 
> > None of those properties are guaranteed by adjust_point_for_property,
> > sadly, but it's the motivation behind it.
> > 
> > > Finally, what do you think of this:
> > 
> > >   (progn (switch-to-buffer "test")
> > > 	 (insert "aline1\nbline2\ncline3\n")
> > > 	 (goto-line 2)
> > > 	 (put-text-property (line-beginning-position)
> > > 			    (line-beginning-position 2)
> > > 			    'invisible 'invis1)
> > > 	 (add-to-invisibility-spec 'invis1)
> > > 	 (goto-char (point-max)))
> > 
> > > Eval this in *scratch*, then type "C-p C-x =".  You will see that
> > > Emacs reports that point is position 8 and the character at point is
> > > `b', whereas what is shown (correctly) under the cursor is `c' whose
> > > buffer position is 15.  Do you think this is correct behavior?
> > 
> > In this area, I don't think there's a clear cut definition of what is
> > correct and what is not.  Depending on what is being done some behavior
> > is preferable, and in other cases another behavior is preferable.
> > If point is anywhere between "bline2\n" the display will be identical,
> > so the fact that the cursor is drawn over the "c" that follows it does
> > not necessarily imply that point should be "at the end of "bline2\n",
> > since the cursor is also drawn right after the "aline1\n" and by that
> > logic point should be at the beginning of "bline2\n".
> > 
> > What tilts the decision one way rather than the other here is the
> > stickiness: for all positions other than right before "bline2\n",
> > self-insert-command at point will result in an invisible char being
> > inserted, which is very rarely the intention of the user.  Of course, in
> > a read-only buffer this consideration may not matter, but note that this
> > stickiness issue also happens to be a way by which Elisp packages can
> > control in which part of the invisible text point will end up.
> > 
> 
> That makes sense.  Thank you.
> 
> Perhaps in case of notmuch the best way is to hide the preceding newline
> character instead of the trailing one.  This way there will always be a
> visible newline between different messages and cursor-moving functions
> (e.g. `vertical-motion') should not move beyond it.
> 

While trying this, I found another issue with how emacs adjusts the
point when it is idle.  We have 3 lines and the second one is hidden.
But now we hide the newline on line1 instead of line2:

  (progn (switch-to-buffer "test")
         (insert "aline1\nbline2\ncline3\n")
         (put-text-property 7 14 'invisible t)
         (goto-char (point-min)))

Now if you run M-: (progn (end-of-visual-line) (point)), it moves to
point 14, which is end of line 2 as expected.  But then emacs adjusts
the point and moves it to beginning of line3, C-x = says point is 15.

Also, global-hl-line-mode does not work correctly for line1.  Just go to
the start of buffer and move forward to see some weird behavior.

Regards,
  Dmitry

> Still looking for an answer to the following question earlier in this
> thread:
> 
>     I am looking for a function that does something like what you described
>     below.  I.e. moves point to the next suitable character in the given
>     direction.  At the moment I do it with smth like:
> 
>       ;; if point is invisible, skip forward to visible text
>       (while (invisible-p p)
>         (setq p (next-single-char-property-change p 'invisible)))
> 
> Regards,
>   Dmitry
> 
> > 
> >         Stefan



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-05  3:52             ` Dmitry Kurochkin
@ 2011-07-05  7:56               ` Eli Zaretskii
  2011-07-09 13:13                 ` Dmitry Kurochkin
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2011-07-05  7:56 UTC (permalink / raw)
  To: Dmitry Kurochkin; +Cc: monnier, emacs-devel

> From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> Cc: emacs-devel@gnu.org
> Date: Tue, 05 Jul 2011 07:52:09 +0400
> 
>   (progn (switch-to-buffer "test")
>          (insert "aline1\nbline2\ncline3\n")
>          (put-text-property 7 14 'invisible t)
>          (goto-char (point-min)))
> 
> Now if you run M-: (progn (end-of-visual-line) (point)), it moves to
> point 14, which is end of line 2 as expected.  But then emacs adjusts
> the point and moves it to beginning of line3, C-x = says point is 15.

Interestingly, the first time you do this, there's no adjustment from
14 to 15.  Sounds like some snafu with the last point position?

I can confirm that this happens because point adjustment: setting
global-disable-point-adjustment to non-nil eliminates the problem:
point stays at position 14.

Also, C-e behaves correctly no matter what.  So it's something
specific to end-of-visual-line or vertical-motion.

Perhaps stepping through adjust_point_for_property with a debugger
will show what's wrong.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: `vertical-motion', `goto-line' set point to invisible text
  2011-07-05  7:56               ` Eli Zaretskii
@ 2011-07-09 13:13                 ` Dmitry Kurochkin
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry Kurochkin @ 2011-07-09 13:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

On Tue, 05 Jul 2011 03:56:55 -0400, Eli Zaretskii <eliz@gnu.org> wrote:
> > From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
> > Cc: emacs-devel@gnu.org
> > Date: Tue, 05 Jul 2011 07:52:09 +0400
> > 
> >   (progn (switch-to-buffer "test")
> >          (insert "aline1\nbline2\ncline3\n")
> >          (put-text-property 7 14 'invisible t)
> >          (goto-char (point-min)))
> > 
> > Now if you run M-: (progn (end-of-visual-line) (point)), it moves to
> > point 14, which is end of line 2 as expected.  But then emacs adjusts
> > the point and moves it to beginning of line3, C-x = says point is 15.
> 
> Interestingly, the first time you do this, there's no adjustment from
> 14 to 15.  Sounds like some snafu with the last point position?
> 
> I can confirm that this happens because point adjustment: setting
> global-disable-point-adjustment to non-nil eliminates the problem:
> point stays at position 14.
> 
> Also, C-e behaves correctly no matter what.  So it's something
> specific to end-of-visual-line or vertical-motion.
> 
> Perhaps stepping through adjust_point_for_property with a debugger
> will show what's wrong.

I have opened a bug report #9034 [1] for this issue.  Hopefully it would
get some attention.  Seems it should not be too hard to investigate
investigate the problem for somebody how understands the code well
enough.

Please provide additional details for the bug report if I missed
anything.

Regards,
  Dmitry

[1] http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9034



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2011-07-09 13:13 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-03  2:59 `vertical-motion', `goto-line' set point to invisible text Dmitry Kurochkin
2011-07-03  6:55 ` Eli Zaretskii
2011-07-03  7:31   ` Dmitry Kurochkin
2011-07-03 13:33     ` Eli Zaretskii
2011-07-04  2:08       ` Dmitry Kurochkin
2011-07-03 14:50 ` Stefan Monnier
2011-07-03 15:14   ` Eli Zaretskii
2011-07-04 14:01     ` Stefan Monnier
2011-07-04 15:14       ` Eli Zaretskii
2011-07-04 18:10         ` Stefan Monnier
2011-07-04 20:06           ` Eli Zaretskii
2011-07-04 20:06           ` Eli Zaretskii
2011-07-05  2:22           ` Dmitry Kurochkin
2011-07-05  2:55             ` Eli Zaretskii
2011-07-05  3:52             ` Dmitry Kurochkin
2011-07-05  7:56               ` Eli Zaretskii
2011-07-09 13:13                 ` Dmitry Kurochkin

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).