Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 2 additions & 29 deletions Lib/idlelib/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from idlelib import grep
from idlelib import help
from idlelib import help_about
from idlelib import hyperparser
from idlelib import macosx
from idlelib.multicall import MultiCallCreator
from idlelib import pyparse
Expand Down Expand Up @@ -248,13 +249,6 @@ def __init__(self, flist=None, filename=None, key=None, root=None):
idleConf.blink_off_time = self.text['insertofftime']
self.update_cursor_blink()

# When searching backwards for a reliable place to begin parsing,
# first start num_context_lines[0] lines back, then
# num_context_lines[1] lines back if that didn't work, and so on.
# The last value should be huge (larger than the # of lines in a
# conceivable file).
# Making the initial values larger slows things down more often.
self.num_context_lines = 50, 500, 5000000
self.per = per = self.Percolator(text)
self.undo = undo = self.UndoDelegator()
per.insertfilter(undo)
Expand Down Expand Up @@ -1396,28 +1390,7 @@ def newline_and_indent_event(self, event):

# Adjust indentation for continuations and block open/close.
# First need to find the last statement.
lno = index2line(text.index('insert'))
y = pyparse.Parser(self.indentwidth, self.tabwidth)
if not self.prompt_last_line:
for context in self.num_context_lines:
startat = max(lno - context, 1)
startatindex = repr(startat) + ".0"
rawtext = text.get(startatindex, "insert")
y.set_code(rawtext)
bod = y.find_good_parse_start(
self._build_char_in_string_func(startatindex))
if bod is not None or startat == 1:
break
y.set_lo(bod or 0)
else:
r = text.tag_prevrange("console", "insert")
if r:
startatindex = r[1]
else:
startatindex = "1.0"
rawtext = text.get(startatindex, "insert")
y.set_code(rawtext)
y.set_lo(0)
y = hyperparser.parser(self)

c = y.get_continuation_type()
if c != pyparse.C_NONE:
Expand Down
81 changes: 43 additions & 38 deletions Lib/idlelib/hyperparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,54 +22,59 @@
[(chr(x) in _ASCII_ID_FIRST_CHARS) for x in range(128)]


def parser(editwin, index="insert", lineend=""):
"Create a PyParse instance and find the last statement."
text = editwin.text

p = pyparse.Parser(editwin.indentwidth, editwin.tabwidth)
lineno = editwin.getlineno(index)
stopatindex = index if not lineend else f"{lineno}.end"

if editwin.prompt_last_line:
r = text.tag_prevrange("console", index)
startatindex = r[1] if r else "1.0"
p.set_code(text.get(startatindex, stopatindex) + lineend)
return p

# When searching backwards for a reliable place to begin parsing,
# first start num_context_lines[0] lines back, then
# num_context_lines[1] lines back if that didn't work, and so on.
# The last value should be huge (larger than the # of lines in a
# conceivable file).
# Making the initial values larger slows things down more often.
num_context_lines = 50, 500, 5000000
for context in num_context_lines:
startat = max(lineno - context, 1)
startatindex = f"{startat}.0"
p.set_code(text.get(startatindex, stopatindex) + lineend)
bod = p.find_good_parse_start(
editwin._build_char_in_string_func(startatindex))
if bod is not None or startat == 1:
break
p.set_lo(bod or 0)
return p


class HyperParser:
def __init__(self, editwin, index):
"To initialize, analyze the surroundings of the given index."

self.editwin = editwin
self.text = text = editwin.text

parser = pyparse.Parser(editwin.indentwidth, editwin.tabwidth)

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)
self.text = editwin.text

# 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.
p = parser(editwin, index=index, lineend=" \n")

# We want what the parser has, minus the last newline and space.
self.rawtext = parser.code[:-2]
self.rawtext = p.code[:-2]
# 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.bracketing = parser.get_last_stmt_bracketing()
self.stopatindex = f"{editwin.getlineno(index)}.end"
self.bracketing = p.get_last_stmt_bracketing()
# find which pairs of bracketing are openers. These always
# correspond to a character of rawtext.
self.isopener = [i>0 and self.bracketing[i][1] >
Expand Down
3 changes: 3 additions & 0 deletions Lib/idlelib/idle_test/test_autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def __init__(self, root, text):
self.tabwidth = 8
self.prompt_last_line = '>>>' # Currently not used by autocomplete.

def getlineno(self, index):
return int(float(self.text.index(index)))


class AutoCompleteTest(unittest.TestCase):

Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_hyperparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ def __init__(self, text):
self.indentwidth = 8
self.tabwidth = 8
self.prompt_last_line = '>>>'
self.num_context_lines = 50, 500, 1000

_build_char_in_string_func = EditorWindow._build_char_in_string_func
is_char_in_string = EditorWindow.is_char_in_string
getlineno = EditorWindow.getlineno


class HyperParserTest(unittest.TestCase):
Expand Down
3 changes: 3 additions & 0 deletions Lib/idlelib/idle_test/test_parenmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def __init__(self, text):
self.tabwidth = 8
self.prompt_last_line = '>>>' # Currently not used by parenmatch.

def getlineno(self, index):
return int(float(self.text.index(index)))


class ParenMatchTest(unittest.TestCase):

Expand Down