@@ -461,8 +461,11 @@ def process_control_event(self, e):
461461 ctrl_char = compress_paste_event (e )
462462 if ctrl_char is not None :
463463 return self .process_event (ctrl_char )
464+ simple_events = just_simple_events (e .events )
465+ source = bad_empty_lines_removed ('' .join (simple_events ))
466+
464467 with self .in_paste_mode ():
465- for ee in e . events :
468+ for ee in source :
466469 if self .stdin .has_focus :
467470 self .stdin .process_event (ee )
468471 else :
@@ -712,7 +715,9 @@ def send_session_to_external_editor(self, filename=None):
712715 for line in self .getstdout ().split ('\n ' ))
713716 text = self .send_to_external_editor (for_editor )
714717 lines = text .split ('\n ' )
715- self .history = [line for line in lines if line [:4 ] != '### ' ]
718+ from_editor = [line for line in lines if line [:4 ] != '### ' ]
719+ source = bad_empty_lines_removed ('\n ' .join (from_editor ))
720+ self .history = source .split ('\n ' )
716721 self .reevaluate (insert_into_history = True )
717722 self .current_line = lines [- 1 ][4 :]
718723 self .cursor_offset = len (self .current_line )
@@ -822,7 +827,7 @@ def push(self, line, insert_into_history=True):
822827 code_to_run = '\n ' .join (self .buffer )
823828
824829 logger .debug ('running %r in interpreter' , self .buffer )
825- c , code_will_parse = self . buffer_finished_will_parse ( )
830+ c , code_will_parse = code_finished_will_parse ( ' \n ' . join ( self . buffer ) )
826831 self .saved_predicted_parse_error = not code_will_parse
827832 if c :
828833 logger .debug ('finished - buffer cleared' )
@@ -834,21 +839,6 @@ def push(self, line, insert_into_history=True):
834839 self .coderunner .load_code (code_to_run )
835840 self .run_code_and_maybe_finish ()
836841
837- def buffer_finished_will_parse (self ):
838- """Returns a tuple of whether the buffer could be complete and whether it will parse
839-
840- True, True means code block is finished and no predicted parse error
841- True, False means code block is finished because a parse error is predicted
842- False, True means code block is unfinished
843- False, False isn't possible - an predicted error makes code block done"""
844- try :
845- finished = bool (code .compile_command ('\n ' .join (self .buffer )))
846- code_will_parse = True
847- except (ValueError , SyntaxError , OverflowError ):
848- finished = True
849- code_will_parse = False
850- return finished , code_will_parse
851-
852842 def run_code_and_maybe_finish (self , for_code = None ):
853843 r = self .coderunner .run_code (for_code = for_code )
854844 if r :
@@ -861,7 +851,6 @@ def run_code_and_maybe_finish(self, for_code=None):
861851 if err :
862852 indent = 0
863853
864-
865854 #TODO This should be printed ABOVE the error that just happened instead
866855 # or maybe just thrown away and not shown
867856 if self .current_stdouterr_line :
@@ -1418,6 +1407,77 @@ def compress_paste_event(paste_event):
14181407 else :
14191408 return None
14201409
1410+ def just_simple_events (event_list ):
1411+ simple_events = []
1412+ for e in event_list :
1413+ if e in (u"<Ctrl-j>" , u"<Ctrl-m>" , u"<PADENTER>" , u"\n " , u"\r " ): # '\n' necessary for pastes
1414+ simple_events .append (u'\n ' )
1415+ elif isinstance (e , events .Event ):
1416+ pass # ignore events
1417+ elif e == '<SPACE>' :
1418+ simple_events .append (' ' )
1419+ else :
1420+ simple_events .append (e )
1421+ return simple_events
1422+
1423+ def code_finished_will_parse (s ):
1424+ """Returns a tuple of whether the buffer could be complete and whether it will parse
1425+
1426+ True, True means code block is finished and no predicted parse error
1427+ True, False means code block is finished because a parse error is predicted
1428+ False, True means code block is unfinished
1429+ False, False isn't possible - an predicted error makes code block done"""
1430+ try :
1431+ finished = bool (code .compile_command (s ))
1432+ code_will_parse = True
1433+ except (ValueError , SyntaxError , OverflowError ):
1434+ finished = True
1435+ code_will_parse = False
1436+ return finished , code_will_parse
1437+
1438+ def bad_empty_lines_removed (s ):
1439+ """Removes empty lines that would cause unfinished input to be evaluated"""
1440+ # If there's a syntax error followed by an empty line, remove the empty line
1441+ lines = s .split ('\n ' )
1442+ #TODO this should be our interpreter object making this decision so it
1443+ # can be compiler directive (__future__ statement) -aware
1444+ #TODO specifically catch IndentationErrors instead of any syntax errors
1445+
1446+ current_block = []
1447+ complete_blocks = []
1448+ for i , line in enumerate (s .split ('\n ' )):
1449+ current_block .append (line )
1450+ could_be_finished , valid = code_finished_will_parse ('\n ' .join (current_block ))
1451+ if could_be_finished and valid :
1452+ complete_blocks .append (current_block )
1453+ current_block = []
1454+ continue
1455+ elif could_be_finished and not valid :
1456+ if complete_blocks :
1457+ complete_blocks [- 1 ].extend (current_block )
1458+ current_block = complete_blocks .pop ()
1459+ if len (current_block ) < 2 :
1460+ return s #TODO return partial result instead of giving up
1461+ last_line = current_block .pop (len (current_block ) - 2 )
1462+ assert not last_line , last_line
1463+ new_finished , new_valid = code_finished_will_parse ('\n ' .join (current_block ))
1464+ if new_valid and new_finished :
1465+ complete_blocks .append (current_block )
1466+ current_block = []
1467+ elif new_valid :
1468+ continue
1469+ else :
1470+ return s #TODO return partial result instead of giving up
1471+
1472+ else :
1473+ return s #TODO return partial result instead of giving up
1474+ else :
1475+ continue
1476+ return '\n ' .join (['\n ' .join (block )
1477+ for block in complete_blocks + [current_block ]
1478+ if block ])
1479+
1480+
14211481#TODO this needs some work to function again and be useful for embedding
14221482def simple_repl ():
14231483 refreshes = []
0 commit comments