From dce981d0f5001f35e4f95fa45f772aa4426b0d76 Mon Sep 17 00:00:00 2001 From: Ujan RoyBandyopadhyay <116058173+ujan-r@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:53:36 -0500 Subject: [PATCH 1/4] Mark start of new statements --- Lib/idlelib/editor.py | 4 ++++ Lib/idlelib/pyshell.py | 1 + 2 files changed, 5 insertions(+) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index c76db20c58792d..cd82c8e4a18990 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -447,6 +447,10 @@ def set_line_and_column(self, event=None): self.status_bar.set_label('column', 'Col: %s' % column) self.status_bar.set_label('line', 'Ln: %s' % line) + def mark_new_stmt(self): + self.text.mark_set('stmt-start', INSERT) + self.text.mark_gravity('stmt-start', LEFT) + """ Menu definitions and functions. * self.menubar - the always visible horizontal menu bar. diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index e882c6cb3b8d19..f62c4253757cca 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -1391,6 +1391,7 @@ def showprompt(self): self.shell_sidebar.update_sidebar() self.text.mark_set("insert", "end-1c") + self.mark_new_stmt() self.set_line_and_column() self.io.reset_undo() From 927e0bc133b852f64c9a18b34ae943b60bf26053 Mon Sep 17 00:00:00 2001 From: Ujan RoyBandyopadhyay <116058173+ujan-r@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:34:55 -0500 Subject: [PATCH 2/4] Ensure parsing begins at statement starts --- Lib/idlelib/hyperparser.py | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 76144ee8fb30f5..28977e7df8dbea 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -31,44 +31,20 @@ def __init__(self, editwin, index): parser = pyparse.Parser(editwin.indentwidth, editwin.tabwidth) + startatindex = text.index('stmt-start') + def index2line(index): return int(float(index)) lno = index2line(text.index(index)) - if not editwin.prompt_last_line: - for context in editwin.num_context_lines: - startat = max(lno - context, 1) - startatindex = repr(startat) + ".0" - stopatindex = "%d.end" % lno - # We add the newline because PyParse requires a newline - # at end. We add a space so that index won't be at end - # of line, so that its status will be the same as the - # char before it, if should. - parser.set_code(text.get(startatindex, stopatindex)+' \n') - bod = parser.find_good_parse_start( - editwin._build_char_in_string_func(startatindex)) - if bod is not None or startat == 1: - break - parser.set_lo(bod or 0) - else: - r = text.tag_prevrange("console", index) - if r: - startatindex = r[1] - else: - startatindex = "1.0" - stopatindex = "%d.end" % lno - # We add the newline because PyParse requires it. We add a - # space so that index won't be at end of line, so that its - # status will be the same as the char before it, if should. - parser.set_code(text.get(startatindex, stopatindex)+' \n') - parser.set_lo(0) - - # We want what the parser has, minus the last newline and space. - self.rawtext = parser.code[:-2] + statement = text.get(startatindex, '%d.end' % lno) + self.rawtext = statement + parser.set_code(statement + '\n') + # Parser.code apparently preserves the statement we are in, so # that stopatindex can be used to synchronize the string with # the text box indices. - self.stopatindex = stopatindex + self.stopatindex = '%d.end' % lno self.bracketing = parser.get_last_stmt_bracketing() # find which pairs of bracketing are openers. These always # correspond to a character of rawtext. From 9d82167dcbc56c1d272eb97b63ac123eb58001a2 Mon Sep 17 00:00:00 2001 From: Ujan RoyBandyopadhyay <116058173+ujan-r@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:41:48 -0500 Subject: [PATCH 3/4] Add basic mark support in mocks --- Lib/idlelib/idle_test/mock_tk.py | 5 ++++- Lib/idlelib/idle_test/test_calltip.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py index 8304734b847a83..9364de1c7ad28d 100644 --- a/Lib/idlelib/idle_test/mock_tk.py +++ b/Lib/idlelib/idle_test/mock_tk.py @@ -111,6 +111,7 @@ def __init__(self, master=None, cnf={}, **kw): There are just a few Text-only options that affect text behavior. ''' self.data = ['', '\n'] + self.marks = {} def index(self, index): "Return string version of index decoded according to current text." @@ -144,6 +145,8 @@ def _decode(self, index, endflag=0): return lastline, len(self.data[lastline]) - 1 elif index == 'end': return self._endex(endflag) + elif '.' not in index: + return self._decode(self.marks['stmt-start']) line, char = index.split('.') line = int(line) @@ -271,7 +274,7 @@ def compare(self, index1, op, index2): def mark_set(self, name, index): "Set mark *name* before the character at index." - pass + self.marks[name] = index def mark_unset(self, *markNames): "Delete all marks in markNames." diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index 28c196a42672fc..ac56f1e1069c92 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -281,6 +281,7 @@ class mock_Shell: "Return mock sufficient to pass to hyperparser." def __init__(self, text): text.tag_prevrange = Mock(return_value=None) + text.mark_set('stmt-start', '1.0') self.text = text self.prompt_last_line = ">>> " self.indentwidth = 4 From ff2a4a50d5c9de31ea5f6ae1e0afd5e986dc0756 Mon Sep 17 00:00:00 2001 From: Ujan RoyBandyopadhyay <116058173+ujan-r@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:00:22 -0500 Subject: [PATCH 4/4] Use existing "iomark" --- Lib/idlelib/editor.py | 4 ---- Lib/idlelib/hyperparser.py | 2 +- Lib/idlelib/idle_test/mock_tk.py | 2 +- Lib/idlelib/idle_test/test_calltip.py | 2 +- Lib/idlelib/pyshell.py | 1 - 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index cd82c8e4a18990..c76db20c58792d 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -447,10 +447,6 @@ def set_line_and_column(self, event=None): self.status_bar.set_label('column', 'Col: %s' % column) self.status_bar.set_label('line', 'Ln: %s' % line) - def mark_new_stmt(self): - self.text.mark_set('stmt-start', INSERT) - self.text.mark_gravity('stmt-start', LEFT) - """ Menu definitions and functions. * self.menubar - the always visible horizontal menu bar. diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 28977e7df8dbea..e75ac450611f95 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -31,7 +31,7 @@ def __init__(self, editwin, index): parser = pyparse.Parser(editwin.indentwidth, editwin.tabwidth) - startatindex = text.index('stmt-start') + startatindex = text.index('iomark') def index2line(index): return int(float(index)) diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py index 9364de1c7ad28d..6c4d14c3d1d298 100644 --- a/Lib/idlelib/idle_test/mock_tk.py +++ b/Lib/idlelib/idle_test/mock_tk.py @@ -146,7 +146,7 @@ def _decode(self, index, endflag=0): elif index == 'end': return self._endex(endflag) elif '.' not in index: - return self._decode(self.marks['stmt-start']) + return self._decode(self.marks[index], endflag) line, char = index.split('.') line = int(line) diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index ac56f1e1069c92..b0d0c3680aed92 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -281,7 +281,7 @@ class mock_Shell: "Return mock sufficient to pass to hyperparser." def __init__(self, text): text.tag_prevrange = Mock(return_value=None) - text.mark_set('stmt-start', '1.0') + text.mark_set('iomark', '1.0') self.text = text self.prompt_last_line = ">>> " self.indentwidth = 4 diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index f62c4253757cca..e882c6cb3b8d19 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -1391,7 +1391,6 @@ def showprompt(self): self.shell_sidebar.update_sidebar() self.text.mark_set("insert", "end-1c") - self.mark_new_stmt() self.set_line_and_column() self.io.reset_undo()