4343#TODO use events instead of length-one queues for interthread communication
4444
4545#TODO raw_input should be bytes in python2
46+ #TODO check py3 compatibility
4647
4748
4849from bpython .keys import cli_key_dispatch as key_dispatch
@@ -145,7 +146,12 @@ def __init__(self, locals_=None, config=None, stuff_a_refresh_request=lambda: No
145146 self .cursor_offset_in_line = 0 # from the left, 0 means first char
146147 self .done = True
147148
148- self .coderunner = CodeRunner (self .interp , stuff_a_refresh_request )
149+ def request_refresh ():
150+ self .refresh_requests += 1
151+ stuff_a_refresh_request ()
152+ self .refresh_requests = 0
153+ self .stuff_a_refresh_request = request_refresh
154+ self .coderunner = CodeRunner (self .interp , request_refresh )
149155 self .stdout = FakeOutput (self .coderunner , self .send_to_stdout )
150156 self .stderr = FakeOutput (self .coderunner , self .send_to_stderr )
151157 self .stdin = FakeStdin (self .coderunner , self )
@@ -154,6 +160,7 @@ def __init__(self, locals_=None, config=None, stuff_a_refresh_request=lambda: No
154160 self .request_paint_to_clear_screen = False
155161 self .last_events = [None ] * 50
156162 self .presentation_mode = False
163+ self .reevaluating = False
157164
158165 self .width = None # will both be set by a window resize event
159166 self .height = None
@@ -195,7 +202,13 @@ def process_event(self, e):
195202
196203 logging .debug ("processing event %r" , e )
197204 if isinstance (e , events .RefreshRequestEvent ):
198- self .run_code_and_maybe_finish ()
205+ assert self .refresh_requests > 0
206+ self .refresh_requests -= 1
207+ assert self .coderunner .code_is_waiting or self .reevaluating
208+ if self .coderunner .code_is_waiting :
209+ self .run_code_and_maybe_finish ()
210+ if self .refresh_requests == 0 and self .reevaluating :
211+ self .reevaluate ()
199212 return
200213 self .last_events .append (e )
201214 self .last_events .pop (0 )
@@ -263,7 +276,6 @@ def process_event(self, e):
263276 self .on_tab (back = True )
264277 elif e in ('' ,) + key_dispatch [self .config .undo_key ]:
265278 self .undo ()
266- self .update_completion ()
267279 elif e in ('\x13 ' ,) + key_dispatch [self .config .save_key ]: # ctrl-s for save
268280 t = threading .Thread (target = self .write2file )
269281 t .daemon = True
@@ -740,6 +752,15 @@ def reprint_line(self, lineno, tokens):
740752 self .display_buffer [lineno ] = bpythonparse (format (tokens , self .formatter ))
741753 def reevaluate (self , insert_into_history = False ):
742754 """bpython.Repl.undo calls this"""
755+ #TODO This almost works, but events are necessary to keep it going!
756+ if not self .reevaluating :
757+ self .reevaluating = self .reevaluation_generator (insert_into_history = insert_into_history )
758+ try :
759+ self .reevaluating .next ()
760+ except StopIteration :
761+ self .reevaluating = False
762+
763+ def reevaluation_generator (self , insert_into_history ):
743764 #TODO other implementations have a enter no-history method, could do
744765 # that instead of clearing history and getting it rewritten
745766 old_logical_lines = self .history
@@ -748,6 +769,7 @@ def reevaluate(self, insert_into_history=False):
748769
749770 self .done = True # this keeps the first prompt correct
750771 self .interp = code .InteractiveInterpreter ()
772+ self .coderunner .interp = self .interp
751773 self .completer = Autocomplete (self .interp .locals , self .config )
752774 self .completer .autocomplete_mode = 'simple'
753775 self .buffer = []
@@ -757,8 +779,14 @@ def reevaluate(self, insert_into_history=False):
757779 for line in old_logical_lines :
758780 self ._current_line = line
759781 self .on_enter (insert_into_history = insert_into_history )
782+ if self .refresh_requests > 0 :
783+ yield line # use up remaining refresh requests
784+ else :
785+ self .stuff_a_refresh_request ()
786+ yield line
760787 self .cursor_offset_in_line = 0
761788 self ._current_line = ''
789+
762790 def getstdout (self ):
763791 lines = self .lines_for_display + [self .current_line_formatted ]
764792 s = '\n ' .join ([x .s if isinstance (x , FmtStr ) else x
0 commit comments