Skip to content

bpo-37903: IDLE: Shell sidebar with prompts (take #2) #22682

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 68 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
7adb9ad
initial working shell sidebar
taleinat Aug 5, 2019
26bbaec
fix recall and handling of prompt and input lines
taleinat Aug 23, 2019
9076da5
update only as needed during editing, accounting for line wrapping
taleinat Aug 23, 2019
cad2cd1
properly insert delegators into their proper place in the percolator
taleinat Aug 24, 2019
4040e26
move non-syntax tag highlighting out of ColorDelegator
taleinat Aug 24, 2019
9b31031
replace shell sidebar prompt and input line recognition method
taleinat Aug 24, 2019
37a0db3
minor code cleanup
taleinat Aug 24, 2019
c766822
remove unnecessary .replace() delegator method
taleinat Aug 24, 2019
50bd082
fix inverted condition in deciding whether to update sidebar (oops!)
taleinat Aug 24, 2019
6f186f0
fix "stdin" tag removed when undo-ing a deletion
taleinat Aug 24, 2019
f7f3de9
fix sidebar update on new prompt
taleinat Aug 24, 2019
e929ea7
add a NEWS entry
taleinat Aug 24, 2019
d04bfa3
fix recall handling with multiple successive statements
taleinat Aug 24, 2019
81f4852
remove a dead line
taleinat Aug 24, 2019
46be85e
remove commented out initial attempt
taleinat Aug 24, 2019
1fc4bcb
update shell sidebar font upon font config changes
taleinat Aug 25, 2019
6f1c975
update sidebar text colors upon highlight config changes
taleinat Sep 17, 2020
083fede
use the prompt ("console") foreground color for the shell sidebar text
taleinat Sep 17, 2020
4ad72a1
show continuation prompts ("...") for multi-line history recall
taleinat Sep 17, 2020
009e08d
show continuation prompts ("...") after multi-line replace in the shell
taleinat Sep 17, 2020
e524cce
show continuation prompts ("...") after multi-line undo/redo in the s…
taleinat Sep 17, 2020
3ea2986
don't show continuation prompts ("...") for print() outputs
taleinat Sep 17, 2020
7f9182f
allow deleting ">>> " at the beginning of a line in shell windows
taleinat Sep 17, 2020
10aaf1d
update shell sidebar on shell output squeeze/unsqueeze
taleinat Sep 17, 2020
7c91901
remove failing editor window test that is no longer relevant
taleinat Sep 17, 2020
50ca9c6
add several tests for the shell sidebar
taleinat Sep 18, 2020
23c218f
reduce shell sidebar test run time by reusing the PyShell
taleinat Sep 18, 2020
6cef0a9
revert removal of the "hit" tag from Colorizer.tag_defs
taleinat Oct 11, 2020
a018135
hide unnecessary extra "root" Tk window in tests
taleinat Oct 11, 2020
525fe44
fix test method names
taleinat Oct 11, 2020
7b8913d
fix test comments according to pep-8 style
taleinat Oct 11, 2020
8c8d0c0
rename sidebar test class according to convention
taleinat Oct 11, 2020
7ecc843
re-word doc-strings for BaseSideBar and EndLineDelegator
taleinat Oct 12, 2020
bedb1cb
re-word doc-strings for get_lineno and get_end_linenumber
taleinat Oct 12, 2020
eee0453
optimize tests and make them more robust
taleinat Oct 12, 2020
7afcb57
handle mouse buttons except for button 1 (left-click)
taleinat Oct 12, 2020
8a7dd60
add tests for text font and color configs
taleinat Oct 12, 2020
6efb968
remove show/hide_sidebar from the shell sidebar
taleinat Oct 12, 2020
cc37924
add more test cases
taleinat Oct 12, 2020
97576da
update coverage percentage
taleinat Oct 12, 2020
2aa4e1a
re-word squeeze_current_text() doc-string
taleinat Oct 12, 2020
71f343e
update coverage percentage
taleinat Oct 13, 2020
45e66a5
Merge branch 'master' into idle-shell-sidebar
taleinat Oct 13, 2020
dbe931c
fix wrong colors at ends of input lines/blocks
taleinat Oct 14, 2020
779adc4
fix some sidebar tests affected by losing window focus
taleinat Oct 14, 2020
8f81915
fix highlighting and sidebar prompts after syntax errors
taleinat Oct 15, 2020
ddc0026
better long-term disabling of line numbers tests
taleinat Oct 15, 2020
d1e0d32
update unittest coverage percentage
taleinat Oct 15, 2020
0516db9
run sidebar tests with PyShell without a sub-process
taleinat Oct 22, 2020
afa6669
avoid creating text widgets for whitespace shell prompts
taleinat Oct 22, 2020
9d06f26
simplify some test code
taleinat Oct 22, 2020
73146fb
remove unnecessary parentheses
taleinat Oct 22, 2020
19b16a4
fix first prompt when shown text starts with the end of a wrapped line
taleinat Oct 22, 2020
ecab884
fix failing tests on Azure Devops
taleinat Nov 1, 2020
7b2d9dc
Merge remote-tracking branch 'upstream/master' into pr_22682
terryjreedy Jan 22, 2021
d6e35cc
Merge remote-tracking branch 'upstream/master' into pr_22682
terryjreedy Apr 25, 2021
f6c9a7c
revert indentation change
taleinat Apr 25, 2021
990cef4
revert InteractiveInterpreter.runsource return values
taleinat Apr 25, 2021
e86353b
fix removal of final newline and surrounding whitespace
taleinat Apr 25, 2021
a1891a4
simplify fixed newline+whitespace removal using \Z
taleinat Apr 25, 2021
3e52c5d
revert unneeded changes to ResetColorizer
taleinat Apr 26, 2021
cc709ab
wrap some overly long lines of code
taleinat Apr 26, 2021
093544a
fix tests failing on Azure Pipelines
taleinat Apr 27, 2021
474c11a
rename and refactor Tk mainloop function decorator
taleinat Apr 28, 2021
fde793a
simplify code by making use_subprocess default to False
taleinat Apr 28, 2021
916e0d3
rename "*_command" -> "*_statement"
taleinat Apr 28, 2021
8ada0a7
improve test with squeezer
taleinat Apr 28, 2021
c1871f2
fix missed renaming of update_colors() back to ResetColorizer()
taleinat Apr 28, 2021
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
1 change: 0 additions & 1 deletion Lib/idlelib/colorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ def LoadTagDefs(self):
# non-modal alternative.
"hit": idleConf.GetHighlight(theme, "hit"),
}

if DEBUG: print('tagdefs', self.tagdefs)

def insert(self, index, chars, tags=None):
Expand Down
30 changes: 15 additions & 15 deletions Lib/idlelib/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ class EditorWindow:
from idlelib.sidebar import LineNumbers
from idlelib.format import FormatParagraph, FormatRegion, Indents, Rstrip
from idlelib.parenmatch import ParenMatch
from idlelib.squeezer import Squeezer
from idlelib.zoomheight import ZoomHeight

filesystemencoding = sys.getfilesystemencoding() # for file names
help_url = None

allow_code_context = True
allow_line_numbers = True
user_input_insert_tags = None

def __init__(self, flist=None, filename=None, key=None, root=None):
# Delay import: runscript imports pyshell imports EditorWindow.
Expand Down Expand Up @@ -784,9 +784,7 @@ def _addcolorizer(self):
self.color = self.ColorDelegator()
# can add more colorizers here...
if self.color:
self.per.removefilter(self.undo)
self.per.insertfilter(self.color)
self.per.insertfilter(self.undo)
self.per.insertfilterafter(filter=self.color, after=self.undo)

def _rmcolorizer(self):
if not self.color:
Expand Down Expand Up @@ -1303,8 +1301,6 @@ def smart_backspace_event(self, event):
# Debug prompt is multilined....
ncharsdeleted = 0
while 1:
if chars == self.prompt_last_line: # '' unless PyShell
break
chars = chars[:-1]
ncharsdeleted = ncharsdeleted + 1
have = len(chars.expandtabs(tabwidth))
Expand All @@ -1313,7 +1309,8 @@ def smart_backspace_event(self, event):
text.undo_block_start()
text.delete("insert-%dc" % ncharsdeleted, "insert")
if have < want:
text.insert("insert", ' ' * (want - have))
text.insert("insert", ' ' * (want - have),
self.user_input_insert_tags)
text.undo_block_stop()
return "break"

Expand Down Expand Up @@ -1346,7 +1343,7 @@ def smart_indent_event(self, event):
effective = len(prefix.expandtabs(self.tabwidth))
n = self.indentwidth
pad = ' ' * (n - effective % n)
text.insert("insert", pad)
text.insert("insert", pad, self.user_input_insert_tags)
text.see("insert")
return "break"
finally:
Expand Down Expand Up @@ -1377,13 +1374,14 @@ def newline_and_indent_event(self, event):
if i == n:
# The cursor is in or at leading indentation in a continuation
# line; just inject an empty line at the start.
text.insert("insert linestart", '\n')
text.insert("insert linestart", '\n',
self.user_input_insert_tags)
return "break"
indent = line[:i]

# Strip whitespace before insert point unless it's in the prompt.
i = 0
while line and line[-1] in " \t" and line != self.prompt_last_line:
while line and line[-1] in " \t":
line = line[:-1]
i += 1
if i:
Expand All @@ -1394,7 +1392,7 @@ def newline_and_indent_event(self, event):
text.delete("insert")

# Insert new line.
text.insert("insert", '\n')
text.insert("insert", '\n', self.user_input_insert_tags)

# Adjust indentation for continuations and block open/close.
# First need to find the last statement.
Expand Down Expand Up @@ -1430,7 +1428,7 @@ def newline_and_indent_event(self, event):
elif c == pyparse.C_STRING_NEXT_LINES:
# Inside a string which started before this line;
# just mimic the current indent.
text.insert("insert", indent)
text.insert("insert", indent, self.user_input_insert_tags)
elif c == pyparse.C_BRACKET:
# Line up with the first (if any) element of the
# last open bracket structure; else indent one
Expand All @@ -1444,7 +1442,8 @@ def newline_and_indent_event(self, event):
# beyond leftmost =; else to beyond first chunk of
# non-whitespace on initial line.
if y.get_num_lines_in_stmt() > 1:
text.insert("insert", indent)
text.insert("insert", indent,
self.user_input_insert_tags)
else:
self.reindent_to(y.compute_backslash_indent())
else:
Expand All @@ -1455,7 +1454,7 @@ def newline_and_indent_event(self, event):
# indentation of initial line of closest preceding
# interesting statement.
indent = y.get_base_indent_string()
text.insert("insert", indent)
text.insert("insert", indent, self.user_input_insert_tags)
if y.is_block_opener():
self.smart_indent_event(event)
elif indent and y.is_block_closer():
Expand Down Expand Up @@ -1502,7 +1501,8 @@ def reindent_to(self, column):
if text.compare("insert linestart", "!=", "insert"):
text.delete("insert linestart", "insert")
if column:
text.insert("insert", self._make_blanks(column))
text.insert("insert", self._make_blanks(column),
self.user_input_insert_tags)
text.undo_block_stop()

# Guess indentwidth from text content.
Expand Down
4 changes: 2 additions & 2 deletions Lib/idlelib/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ def fetch(self, reverse):
else:
if self.text.get("iomark", "end-1c") != prefix:
self.text.delete("iomark", "end-1c")
self.text.insert("iomark", prefix)
self.text.insert("iomark", prefix, "stdin")
pointer = prefix = None
break
item = self.history[pointer]
if item[:nprefix] == prefix and len(item) > nprefix:
self.text.delete("iomark", "end-1c")
self.text.insert("iomark", item)
self.text.insert("iomark", item, "stdin")
break
self.text.see("insert")
self.text.tag_remove("sel", "1.0", "end")
Expand Down
8 changes: 0 additions & 8 deletions Lib/idlelib/idle_test/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ def test_indent_and_newline_event(self):
'2.end'),
)

w.prompt_last_line = ''
for test in tests:
with self.subTest(label=test.label):
insert(text, test.text)
Expand All @@ -182,13 +181,6 @@ def test_indent_and_newline_event(self):
# Deletes selected text before adding new line.
eq(get('1.0', 'end'), ' def f1(self, a,\n \n return a + b\n')

# Preserves the whitespace in shell prompt.
w.prompt_last_line = '>>> '
insert(text, '>>> \t\ta =')
text.mark_set('insert', '1.5')
nl(None)
eq(get('1.0', 'end'), '>>> \na =\n')


class RMenuTest(unittest.TestCase):

Expand Down
84 changes: 84 additions & 0 deletions Lib/idlelib/idle_test/test_pyshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,89 @@ def test_init(self):
## self.assertIsInstance(ps, pyshell.PyShell)


class PyShellRemoveLastNewlineAndSurroundingWhitespaceTest(unittest.TestCase):
regexp = pyshell.PyShell._last_newline_re

def all_removed(self, text):
self.assertEqual('', self.regexp.sub('', text))

def none_removed(self, text):
self.assertEqual(text, self.regexp.sub('', text))

def check_result(self, text, expected):
self.assertEqual(expected, self.regexp.sub('', text))

def test_empty(self):
self.all_removed('')

def test_newline(self):
self.all_removed('\n')

def test_whitespace_no_newline(self):
self.all_removed(' ')
self.all_removed(' ')
self.all_removed(' ')
self.all_removed(' ' * 20)
self.all_removed('\t')
self.all_removed('\t\t')
self.all_removed('\t\t\t')
self.all_removed('\t' * 20)
self.all_removed('\t ')
self.all_removed(' \t')
self.all_removed(' \t \t ')
self.all_removed('\t \t \t')

def test_newline_with_whitespace(self):
self.all_removed(' \n')
self.all_removed('\t\n')
self.all_removed(' \t\n')
self.all_removed('\t \n')
self.all_removed('\n ')
self.all_removed('\n\t')
self.all_removed('\n \t')
self.all_removed('\n\t ')
self.all_removed(' \n ')
self.all_removed('\t\n ')
self.all_removed(' \n\t')
self.all_removed('\t\n\t')
self.all_removed('\t \t \t\n')
self.all_removed(' \t \t \n')
self.all_removed('\n\t \t \t')
self.all_removed('\n \t \t ')

def test_multiple_newlines(self):
self.check_result('\n\n', '\n')
self.check_result('\n' * 5, '\n' * 4)
self.check_result('\n' * 5 + '\t', '\n' * 4)
self.check_result('\n' * 20, '\n' * 19)
self.check_result('\n' * 20 + ' ', '\n' * 19)
self.check_result(' \n \n ', ' \n')
self.check_result(' \n\n ', ' \n')
self.check_result(' \n\n', ' \n')
self.check_result('\t\n\n', '\t\n')
self.check_result('\n\n ', '\n')
self.check_result('\n\n\t', '\n')
self.check_result(' \n \n ', ' \n')
self.check_result('\t\n\t\n\t', '\t\n')

def test_non_whitespace(self):
self.none_removed('a')
self.check_result('a\n', 'a')
self.check_result('a\n ', 'a')
self.check_result('a \n ', 'a')
self.check_result('a \n\t', 'a')
self.none_removed('-')
self.check_result('-\n', '-')
self.none_removed('.')
self.check_result('.\n', '.')

def test_unsupported_whitespace(self):
self.none_removed('\v')
self.none_removed('\n\v')
self.check_result('\v\n', '\v')
self.none_removed(' \n\v')
self.check_result('\v\n ', '\v')


if __name__ == '__main__':
unittest.main(verbosity=2)
Loading