51
51
52
52
logger = logging .getLogger (__name__ )
53
53
54
- HELP_MESSAGE = """
54
+ INCONSISTENT_HISTORY_MSG = u"#<---History inconsistent with output shown--->"
55
+ CONTIGUITY_BROKEN_MSG = u"#<---History contiguity broken by rewind--->"
56
+ HELP_MESSAGE = u"""
55
57
Thanks for using bpython!
56
58
57
59
See http://bpython-interpreter.org/ for info, http://docs.bpython-interpreter.org/ for docs, and https://github.com/bpython/bpython for source.
@@ -270,12 +272,7 @@ def smarter_request_reload(desc):
270
272
self .get_term_hw = get_term_hw
271
273
self .get_cursor_vertical_diff = get_cursor_vertical_diff
272
274
273
- self .status_bar = StatusBar (
274
- (_ (" <%s> Rewind <%s> Save <%s> Pastebin <%s> Editor" )
275
- % (config .undo_key , config .save_key , config .pastebin_key , config .external_editor_key )
276
- if config .curtsies_fill_terminal else '' ),
277
- refresh_request = self .request_refresh
278
- )
275
+ self .status_bar = StatusBar ('' , refresh_request = self .request_refresh )
279
276
self .edit_keys = edit_keys .mapping_with_config (config , key_dispatch )
280
277
logger .debug ("starting parent init" )
281
278
super (Repl , self ).__init__ (interp , config )
@@ -308,6 +305,8 @@ def smarter_request_reload(desc):
308
305
self .stdin = FakeStdin (self .coderunner , self , self .edit_keys )
309
306
310
307
self .request_paint_to_clear_screen = False # next paint should clear screen
308
+ self .inconsistent_history = False # offscreen command yields different result from history
309
+ self .history_already_messed_up = False # history error message displayed
311
310
self .last_events = [None ] * 50 # some commands act differently based on the prev event
312
311
# this list doesn't include instances of event.Event,
313
312
# only keypress-type events (no refresh screen events etc.)
@@ -1011,41 +1010,72 @@ def paint(self, about_to_exit=False, user_quit=False):
1011
1010
self .clean_up_current_line_for_exit () # exception to not changing state!
1012
1011
1013
1012
width , min_height = self .width , self .height
1014
- show_status_bar = bool (self .status_bar .should_show_message ) or ( self .config . curtsies_fill_terminal or self . status_bar .has_focus )
1013
+ show_status_bar = bool (self .status_bar .should_show_message ) or self .status_bar .has_focus
1015
1014
if show_status_bar :
1016
- min_height -= 1
1015
+ min_height -= 1 # because we're going to tack the status bar on at the end,
1016
+ # shoot for an array one less than the height of the screen
1017
1017
1018
1018
current_line_start_row = len (self .lines_for_display ) - max (0 , self .scroll_offset )
1019
+ #TODO how is the situation of self.scroll_offset < 0 possible?
1019
1020
#current_line_start_row = len(self.lines_for_display) - self.scroll_offset
1020
1021
if self .request_paint_to_clear_screen : # or show_status_bar and about_to_exit ?
1021
1022
self .request_paint_to_clear_screen = False
1022
- if self .config .curtsies_fill_terminal : #TODO clean up this logic - really necessary check?
1023
- arr = FSArray (self .height - 1 + current_line_start_row , width )
1024
- else :
1025
- arr = FSArray (self .height + current_line_start_row , width )
1023
+ arr = FSArray (min_height + current_line_start_row , width )
1026
1024
else :
1027
1025
arr = FSArray (0 , width )
1028
1026
#TODO test case of current line filling up the whole screen (there aren't enough rows to show it)
1029
1027
1030
- if current_line_start_row < 0 : #if current line trying to be drawn off the top of the screen
1031
- logger .debug ('#<---History contiguity broken by rewind--->' )
1032
- msg = "#<---History contiguity broken by rewind--->"
1033
- arr [0 , 0 :min (len (msg ), width )] = [msg [:width ]]
1034
-
1028
+ def move_screen_up (current_line_start_row ):
1035
1029
# move screen back up a screen minus a line
1036
1030
while current_line_start_row < 0 :
1031
+ logger .debug ('scroll_offset was %s, current_line_start_row was %s' , self .scroll_offset , current_line_start_row )
1037
1032
self .scroll_offset = self .scroll_offset - self .height
1038
1033
current_line_start_row = len (self .lines_for_display ) - max (- 1 , self .scroll_offset )
1034
+ logger .debug ('scroll_offset changed to %s, current_line_start_row changed to %s' , self .scroll_offset , current_line_start_row )
1035
+ return current_line_start_row
1036
+
1037
+ if self .inconsistent_history == True and not self .history_already_messed_up :
1038
+ logger .debug (INCONSISTENT_HISTORY_MSG )
1039
+ self .history_already_messed_up = True
1040
+ msg = INCONSISTENT_HISTORY_MSG
1041
+ arr [0 , 0 :min (len (msg ), width )] = [msg [:width ]]
1042
+ current_line_start_row += 1 # for the message
1043
+ self .scroll_offset -= 1 # to make up for the scroll we're going to receive
1044
+ # after we render scrolls down a line
1045
+
1046
+ current_line_start_row = move_screen_up (current_line_start_row )
1047
+ logger .debug ('current_line_start_row: %r' , current_line_start_row )
1048
+
1049
+ history = paint .paint_history (max (0 , current_line_start_row - 1 ), width , self .lines_for_display )
1050
+ arr [1 :history .height + 1 ,:history .width ] = history
1051
+
1052
+ if arr .height <= min_height :
1053
+ arr [min_height , 0 ] = ' ' # force scroll down to hide broken history message
1054
+
1055
+ elif current_line_start_row < 0 : #if current line trying to be drawn off the top of the screen
1056
+ logger .debug (CONTIGUITY_BROKEN_MSG )
1057
+ msg = CONTIGUITY_BROKEN_MSG
1058
+ arr [0 , 0 :min (len (msg ), width )] = [msg [:width ]]
1059
+
1060
+ current_line_start_row = move_screen_up (current_line_start_row )
1039
1061
1040
1062
history = paint .paint_history (max (0 , current_line_start_row - 1 ), width , self .lines_for_display )
1041
1063
arr [1 :history .height + 1 ,:history .width ] = history
1042
1064
1043
1065
if arr .height <= min_height :
1044
1066
arr [min_height , 0 ] = ' ' # force scroll down to hide broken history message
1067
+
1045
1068
else :
1069
+ assert current_line_start_row >= 0
1070
+ logger .debug ("no history issues. start %i" ,current_line_start_row )
1046
1071
history = paint .paint_history (current_line_start_row , width , self .lines_for_display )
1047
1072
arr [:history .height ,:history .width ] = history
1048
1073
1074
+
1075
+
1076
+
1077
+ self .inconsistent_history = False
1078
+
1049
1079
current_line = paint .paint_current_line (min_height , width , self .current_cursor_line )
1050
1080
if user_quit : # quit() or exit() in interp
1051
1081
current_line_start_row = current_line_start_row - current_line .height
@@ -1072,7 +1102,7 @@ def paint(self, about_to_exit=False, user_quit=False):
1072
1102
assert cursor_column >= 0 , (cursor_column , len (self .current_cursor_line ), len (self .current_line ), self .cursor_offset )
1073
1103
cursor_row += current_line_start_row
1074
1104
1075
- if self .list_win_visible :
1105
+ if self .list_win_visible and not self . coderunner . running :
1076
1106
logger .debug ('infobox display code running' )
1077
1107
visible_space_above = history .height
1078
1108
visible_space_below = min_height - current_line_end_row - 1
@@ -1095,23 +1125,11 @@ def paint(self, about_to_exit=False, user_quit=False):
1095
1125
1096
1126
logger .debug ('about to exit: %r' , about_to_exit )
1097
1127
if show_status_bar :
1098
- if self .config .curtsies_fill_terminal :
1099
- if about_to_exit :
1100
- arr [max (arr .height , min_height ), :] = FSArray (1 , width )
1101
- else :
1102
- arr [max (arr .height , min_height ), :] = paint .paint_statusbar (1 , width , self .status_bar .current_line , self .config )
1103
-
1104
- if self .presentation_mode :
1105
- rows = arr .height
1106
- columns = arr .width
1107
- last_key_box = paint .paint_last_events (rows , columns , [events .pp_event (x ) for x in self .last_events if x ])
1108
- arr [arr .height - last_key_box .height :arr .height , arr .width - last_key_box .width :arr .width ] = last_key_box
1128
+ statusbar_row = min_height if arr .height == min_height else arr .height
1129
+ if about_to_exit :
1130
+ arr [statusbar_row , :] = FSArray (1 , width )
1109
1131
else :
1110
- statusbar_row = min_height + 1 if arr .height == min_height else arr .height
1111
- if about_to_exit :
1112
- arr [statusbar_row , :] = FSArray (1 , width )
1113
- else :
1114
- arr [statusbar_row , :] = paint .paint_statusbar (1 , width , self .status_bar .current_line , self .config )
1132
+ arr [statusbar_row , :] = paint .paint_statusbar (1 , width , self .status_bar .current_line , self .config )
1115
1133
1116
1134
if self .config .color_scheme ['background' ] not in ('d' , 'D' ):
1117
1135
for r in range (arr .height ):
@@ -1240,6 +1258,7 @@ def reevaluate(self, insert_into_history=False):
1240
1258
"""bpython.Repl.undo calls this"""
1241
1259
if self .watcher : self .watcher .reset ()
1242
1260
old_logical_lines = self .history
1261
+ old_display_lines = self .display_lines
1243
1262
self .history = []
1244
1263
self .display_lines = []
1245
1264
@@ -1263,6 +1282,16 @@ def reevaluate(self, insert_into_history=False):
1263
1282
sys .stdin = self .stdin
1264
1283
self .reevaluating = False
1265
1284
1285
+ num_lines_onscreen = len (self .lines_for_display ) - max (0 , self .scroll_offset )
1286
+ display_lines_offscreen = self .display_lines [:len (self .display_lines ) - num_lines_onscreen ]
1287
+ old_display_lines_offscreen = old_display_lines [:len (self .display_lines ) - num_lines_onscreen ]
1288
+ logger .debug ('old_display_lines_offscreen %s' , '|' .join ([str (x ) for x in old_display_lines_offscreen ]))
1289
+ logger .debug (' display_lines_offscreen %s' , '|' .join ([str (x ) for x in display_lines_offscreen ]))
1290
+ if old_display_lines_offscreen [:len (display_lines_offscreen )] != display_lines_offscreen and not self .history_already_messed_up :
1291
+ #self.scroll_offset = self.scroll_offset + (len(old_display_lines)-len(self.display_lines))
1292
+ self .inconsistent_history = True
1293
+ logger .debug ('after rewind, self.inconsistent_history is %r' , self .inconsistent_history )
1294
+
1266
1295
self .cursor_offset = 0
1267
1296
self .current_line = ''
1268
1297
0 commit comments