Title: IDLE - ParenMatch fails to find closing paren of multi-line statements
Type: behavior Stage: patch review
Components: IDLE Versions: Python 3.7, Python 3.6
Status: open Resolution:
Dependencies: 21686 Superseder:
Assigned To: terry.reedy Nosy List: taleinat, terry.reedy
Priority: normal Keywords: patch

Created on 2014-06-14 09:48 by taleinat, last changed 2017-06-30 00:56 by terry.reedy.

File name Uploaded Description Edit
taleinat.20140614.IDLE_parenmatch_multiline_statement.patch taleinat, 2014-06-14 09:48 patch fixing the issue review
Messages (6)
msg220542 - (view) Author: Tal Einat (taleinat) * (Python committer) Date: 2014-06-14 09:48
Originally reported on issue #21694.

Regarding, for example, the following code:
(3  +
 4 -   1)

Placing the cursor after the opening parenthesis and invoking the "Show surrounding parens" event causes just the first line to be highlighted. Obviously, the second line should be highlighted as well.

I've found a good (clean & fast) solution for shell windows, but can't find any good way for editor windows other than always parsing the entire code. Doing this every time HyperParser is used could significantly degrade IDLE's performance. Therefore I've decided to have this done only by ParenMatch.flash_paren_event(). Note that ParenMatch.paren_closed_event() doesn't need this, since all of the code which is relevant for inspection lies before the closing parenthesis.

See attached patch fixing this issue. Review and additional testing are required.
msg220583 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-06-14 21:41
The current behavior is documented, if not exactly 'chosen' as the best possible. "return the indices of the opening bracket and the closing bracket (or the end of line, whichever comes first". 

As you note, the automatic matching when pausing afte typing a closer only needs to search back, and that should not be affected. When I type ^0, I am willing to wait the extra 1/20? of a second to get a proper highlight.

To see if anything might depend on the truncated search, I grepped

Searching 'get_surrounding_brackets' in C:\Programs\Python34\Lib\idlelib\*.py ... 66:         sur_paren = hp.get_surrounding_brackets('(') 105:     def get_surrounding_brackets(self, openers='([{', mustclose=False): 93:         indices = HyperParser(self.editwin, "insert").get_surrounding_brackets() 109:         indices = hp.get_surrounding_brackets(_openers[closer], True)

So we have to make sure that calltips are not disabled or burdened. (The 'testing' you said is needed.)

I don't understand the call because the goal is to find the expression preceding '('. There usually is no matching ')' after '(' just typed.  I just know that unless unless evalfuncs is True, calltips are not fetched when the function expression contains a function call. 'f(' gives a calltip for f, but 'f()(' does not call f to give a calltip for f().
msg220585 - (view) Author: Tal Einat (taleinat) * (Python committer) Date: 2014-06-14 21:52
Note that the patch changes the behavior only for ParenMatch.flash_paren_event(). Other uses, such as in CallTips, are not affected.

The only possibly unwanted effect that I can think of is in an editor window, on a line missing a closing parenthesis, triggering flash_paren_event() could highlight the entire rest of the code. I'll have to check this tomorrow.

WRT CallTips.open_calltip() calling HyperParser.get_surrounding_parens('('), that is to find the real last opening parenthesis. It is needed since open_calltip() can be triggered manually, not only after '(' is typed.
msg220592 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-06-14 22:54
I suspect that the new end_at_eol parameter should take care of calltips.
msg220612 - (view) Author: Tal Einat (taleinat) * (Python committer) Date: 2014-06-15 05:57
Terry, I'm not sure what you mean but your last comment.

HyperParser.get_surrounding_brackets() will return a previous opening bracket, even if no closing bracket is found for it. CallTips depends on that behavior to find the previous opening parenthesis even if it is not closed.

I can surely say that CallTips profits from the existing behavior of HyperParser, because it doesn't care whether the parenthesis is closed, and this allows HyperParser to do less parsing work.

This patch preserves all of the above and does not affect CallTips at all, since for CallTips it leaves end_at_eol at its default value of True. Likewise for all other uses of HyperParser, including those in ParenMatch, except ParenMatch.flash_paren_event().
msg220616 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-06-15 07:32
I meant what you said in your last paragraph -- not passing a value for the new parameter would keep current behavior.
Date User Action Args
2017-06-30 00:56:48terry.reedysetassignee: terry.reedy
stage: test needed -> patch review
versions: + Python 3.6, Python 3.7, - Python 2.7, Python 3.4, Python 3.5
2014-06-15 07:32:09terry.reedysetmessages: + msg220616
2014-06-15 05:57:10taleinatsetmessages: + msg220612
2014-06-14 23:18:28terry.reedysetdependencies: + IDLE - Test hyperparser
stage: test needed
2014-06-14 22:54:04terry.reedysetmessages: + msg220592
2014-06-14 21:52:55taleinatsetmessages: + msg220585
2014-06-14 21:41:57terry.reedysetmessages: + msg220583
2014-06-14 09:48:56taleinatsettype: behavior
2014-06-14 09:48:15taleinatcreate