GNU bug report logs - #57551
29.0.50; hide-show in python-mode selects the current block imperfectly

Previous Next

Package: emacs;

Reported by: Dima Kogan <dima <at> secretsauce.net>

Date: Fri, 2 Sep 2022 21:26:01 UTC

Severity: normal

Found in version 29.0.50

To reply to this bug, email your comments to 57551 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Fri, 02 Sep 2022 21:26:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Dima Kogan <dima <at> secretsauce.net>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 02 Sep 2022 21:26:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dima Kogan <dima <at> secretsauce.net>
To: bug-gnu-emacs <at> gnu.org
Cc: Lars Ingebrigtsen <larsi <at> gnus.org>, kobarity <kobarity <at> gmail.com>
Subject: 29.0.50; hide-show in python-mode selects the current block
 imperfectly
Date: Fri, 02 Sep 2022 14:25:39 -0700
Hi. I've been using the recently-committed hide-show functionality from:

  https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56635

It's working well, but I just found a problem. Python lacks explicit
block-end characters that a language like C has. This creates some
ambiguity about what is intended, and I think emacs makes the wrong
choice in at least one spot. Let's say we have a tst.py:

def f():
    if 1:
        11
    elif 2:
        22
    elif 3:
        33
    elif 4:
        44
    else:
        5

If I want to collapse the "elif 2:" block, I move the point to somewhere
inside that block, and (hs-hide-block). Placing the point at the end of
the "elif 2:" line puts us unambiguously inside that block, so this does
the job.

But what if the point is at the start of the "elif 2:" line? Currently
emacs considers this to be INSIDE this block also, so (hs-hide-block)
there also hides the "elif 2" block, but should it? Would it not make
more sense if the START of the "elif 2:" line was considered in the "def
f():" block, but outside all the "if" blocks? Then (hs-hide-block) at
the start of that line would collapse the whole "def f():" block.
Currently the only point where this can be done is at the end of the
"def f():" line.

This also raises a question about what should happen if we
(hs-hide-block) with the point on the "i" in any of the "elif" lines.
Probably this should be outside the "elif" blocks too? Maybe?

Thanks!




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Sun, 04 Sep 2022 15:16:02 GMT) Full text and rfc822 format available.

Message #8 received at 57551 <at> debbugs.gnu.org (full text, mbox):

From: kobarity <kobarity <at> gmail.com>
To: Dima Kogan <dima <at> secretsauce.net>
Cc: 57551 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: 29.0.50;
 hide-show in python-mode selects the current block imperfectly
Date: Mon, 05 Sep 2022 00:15:40 +0900
Dima Kogan wrote:
> But what if the point is at the start of the "elif 2:" line? Currently
> emacs considers this to be INSIDE this block also, so (hs-hide-block)
> there also hides the "elif 2" block, but should it? Would it not make
> more sense if the START of the "elif 2:" line was considered in the "def
> f():" block, but outside all the "if" blocks? Then (hs-hide-block) at
> the start of that line would collapse the whole "def f():" block.
> Currently the only point where this can be done is at the end of the
> "def f():" line.

Hi.  I think current hideshow behavior is in line with block
navigation in Python mode.  For example, if the point is at the start
of the "elif 2:" line, M-x python-nav-beginning-of-block moves the
point to "e" of "elif 2:".  This implies that Emacs Python mode
considers spaces before "elif 2:" to belong to the "elif 2:" block.
So I think this is not a matter of hideshow, but of how the block
should be recognized.

The current implementation seems to assume that the block boundary is
always at the end of the line, as shown in the following figure.

_______________
|def f():      |
|_____________ |
||    if 1:   ||
||________11__||
||    elif 2: ||
||________22__||
|______________|

On the other hand, Dima seems to expect the block boundary to be as
shown in the following figure.

_______________
|def f():      |
|    _________ |
| ___|if 1:  _||
||_______ 11|_ |
| ___|elif 2:_||
||_______ 22|  |
|______________|

Although both models may have pros and cons, the current
implementation seems more natural to me.  In particular, it would be
more natural for "elif" or "else" block to be adjacent to "if" block
with nothing else in between.

Regards,




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Sun, 04 Sep 2022 17:03:01 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andreas Röhler <andreas.roehler <at> easy-emacs.de>
To: bug-gnu-emacs <at> gnu.org
Subject: Re: bug#57551: 29.0.50; hide-show in python-mode selects the current
 block imperfectly
Date: Sun, 4 Sep 2022 19:01:53 +0200
Am 04.09.22 um 17:15 schrieb kobarity:
> Dima Kogan wrote:
>> But what if the point is at the start of the "elif 2:" line? Currently
>> emacs considers this to be INSIDE this block also, so (hs-hide-block)
>> there also hides the "elif 2" block, but should it? Would it not make
>> more sense if the START of the "elif 2:" line was considered in the "def
>> f():" block, but outside all the "if" blocks? Then (hs-hide-block) at
>> the start of that line would collapse the whole "def f():" block.
>> Currently the only point where this can be done is at the end of the
>> "def f():" line.
> Hi.  I think current hideshow behavior is in line with block
> navigation in Python mode.  For example, if the point is at the start
> of the "elif 2:" line, M-x python-nav-beginning-of-block moves the
> point to "e" of "elif 2:".  This implies that Emacs Python mode
> considers spaces before "elif 2:" to belong to the "elif 2:" block.
> So I think this is not a matter of hideshow, but of how the block
> should be recognized.
>
> The current implementation seems to assume that the block boundary is
> always at the end of the line, as shown in the following figure.
>
> _______________
> |def f():      |
> |_____________ |
> ||    if 1:   ||
> ||________11__||
> ||    elif 2: ||
> ||________22__||
> |______________|
>
> On the other hand, Dima seems to expect the block boundary to be as
> shown in the following figure.
>
> _______________
> |def f():      |
> |    _________ |
> | ___|if 1:  _||
> ||_______ 11|_ |
> | ___|elif 2:_||
> ||_______ 22|  |
> |______________|
>
> Although both models may have pros and cons, the current
> implementation seems more natural to me.  In particular, it would be
> more natural for "elif" or "else" block to be adjacent to "if" block
> with nothing else in between.
>
> Regards,
>
>
> Hi,

IMO the if-block starts at column 4, with "if". It ends at any column 
lower than 4 below that number 22.

Assume everything between with no regard of column as part of that block.

Best,

Andreas








Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Mon, 05 Sep 2022 07:49:01 GMT) Full text and rfc822 format available.

Message #14 received at 57551 <at> debbugs.gnu.org (full text, mbox):

From: Dima Kogan <dima <at> secretsauce.net>
To: kobarity <kobarity <at> gmail.com>
Cc: 57551 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: 29.0.50; hide-show in python-mode selects the current block
 imperfectly
Date: Mon, 05 Sep 2022 00:44:22 -0700
Hi. Thanks for the analysis. I guess this isn't the right forum for this
discussion, but I'll put it here anyway. The reason I think the "if" and
"else" text and the preceding whitespace should be considered to lie
outside their block is that this is how cc-mode works. Consider the
C code equivalent to the Python code in the bug report:

void f(void)
{
    if(1)
    {
        11;
    }
    else if(2)
    {
        22;
    }
    else if(3)
    {
        33;
    }
    else if(4)
    {
        44;
    }
    else
    {
        5;
    }

    return 0;
}

Here (hs-hide-block) hides the if/else blocks ONLY if the point is
inside the {}. Otherwise, the whole f() is hidden.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Mon, 05 Sep 2022 09:44:01 GMT) Full text and rfc822 format available.

Message #17 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andreas Röhler <andreas.roehler <at> easy-emacs.de>
To: Dima Kogan <dima <at> secretsauce.net>
Cc: bug-gnu-emacs <at> gnu.org
Subject: Re: bug#57551: 29.0.50; hide-show in python-mode selects the current
 block imperfectly
Date: Mon, 5 Sep 2022 11:42:53 +0200
Am 05.09.22 um 09:44 schrieb Dima Kogan:
> Hi. Thanks for the analysis. I guess this isn't the right forum for this
> discussion, but I'll put it here anyway. The reason I think the "if" and
> "else" text and the preceding whitespace should be considered to lie
> outside their block is that this is how cc-mode works. Consider the
> C code equivalent to the Python code in the bug report:
>
> void f(void)
> {
>      if(1)
>      {
>          11;
>      }
>      else if(2)
>      {
>          22;
>      }
>      else if(3)
>      {
>          33;
>      }
>      else if(4)
>      {
>          44;
>      }
>      else
>      {
>          5;
>      }
>
>      return 0;
> }
>
> Here (hs-hide-block) hides the if/else blocks ONLY if the point is
> inside the {}. Otherwise, the whole f() is hidden.
>
>
>

There is another point: might be more than one if-statement in a 
function. If the whole function-body is collapsed from just one 
statement, the others are invisible too.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#57551; Package emacs. (Sat, 10 Sep 2022 13:21:02 GMT) Full text and rfc822 format available.

Message #20 received at 57551 <at> debbugs.gnu.org (full text, mbox):

From: kobarity <kobarity <at> gmail.com>
To: Andreas Röhler <andreas.roehler <at> easy-emacs.de>, Dima
 Kogan <dima <at> secretsauce.net>
Cc: 57551 <at> debbugs.gnu.org, Lars Ingebrigtsen <larsi <at> gnus.org>
Subject: Re: 29.0.50;
 hide-show in python-mode selects the current block imperfectly
Date: Sat, 10 Sep 2022 22:20:38 +0900
Andreas Röhler wrote:
>> The current implementation seems to assume that the block boundary is
>> always at the end of the line, as shown in the following figure.
>>
>> _______________
>> |def f():      |
>> |_____________ |
>> ||    if 1:   ||
>> ||________11__||
>> ||    elif 2: ||
>> ||________22__||
>> |______________|
>>
>> On the other hand, Dima seems to expect the block boundary to be as
>> shown in the following figure.
>>
>> _______________
>> |def f():      |
>> |    _________ |
>> | ___|if 1:  _||
>> ||_______ 11|_ |
>> | ___|elif 2:_||
>> ||_______ 22|  |
>> |______________|
>>
>IMO the if-block starts at column 4, with "if". It ends at any column 
>lower than 4 below that number 22.

Hi.  Is it correct that you are expecting a single block as shown
below?

_______________
|def f():      |
|    _________ |
| ___|if 1:   ||
||        11  ||
||    elif 2: ||
||_______ 22__||
|______________|

If so, this is another topic.

Dima Kogan wrote:
> Hi. Thanks for the analysis. I guess this isn't the right forum for this
> discussion, but I'll put it here anyway. The reason I think the "if" and
> "else" text and the preceding whitespace should be considered to lie
> outside their block is that this is how cc-mode works. Consider the
> C code equivalent to the Python code in the bug report:
> 
> void f(void)
> {
>     if(1)
>     {
>         11;
>     }
>     else if(2)
>     {
>         22;
>     }
>     else if(3)
>     {
>         33;
>     }
>     else if(4)
>     {
>         44;
>     }
>     else
>     {
>         5;
>     }
> 
>     return 0;
> }
> 
> Here (hs-hide-block) hides the if/else blocks ONLY if the point is
> inside the {}. Otherwise, the whole f() is hidden.

I think this is reasonable for cc-mode, where blocks are explicitly
defined by curly braces only.  Keywords like "if" or "else" have
nothing to do with identifying blocks.  Also, there is no need to
consider how lines are constructed.

However, Python does not have such block boundary characters.  As
Python blocks are identified with keywords and indentation, it is
important how lines are constructed.  It seems to me that limiting the
block boundary to the end of a line is not a bad idea in Python mode.

Andreas Röhler wrote:
> There is another point: might be more than one if-statement in a 
> function. If the whole function-body is collapsed from just one 
> statement, the others are invisible too.

Isn't this an expected behavior when hiding the function? Could you
give an example and your expectation?

Regards,




This bug report was last modified 2 years and 334 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.