44import greenlet
55import logging
66import re
7+ import signal
78import sys
89import threading
910import unicodedata
@@ -148,12 +149,18 @@ class Repl(BpythonRepl):
148149 """
149150
150151 ## initialization, cleanup
151- def __init__ (self , locals_ = None , config = None , request_refresh = lambda : None , banner = None , interp = None ):
152+ def __init__ (self , locals_ = None , config = None ,
153+ request_refresh = lambda : None , get_term_wh = lambda :(50 , 10 ),
154+ get_cursor_vertical_diff = lambda : 0 , banner = None , interp = None ):
152155 """
153156 locals_ is a mapping of locals to pass into the interpreter
154157 config is a bpython config.Struct with config attributes
155158 request_refresh is a function that will be called when the Repl
156159 wants to refresh the display, but wants control returned to it afterwards
160+ get_term_wh is a function that returns the current width and height
161+ of the terminal
162+ get_cursor_vertical_diff is a function that returns how the cursor moved
163+ due to a window size change
157164 banner is a string to display briefly in the status bar
158165 interp is an interpreter to use
159166 """
@@ -183,6 +190,8 @@ def smarter_request_refresh():
183190 else :
184191 request_refresh ()
185192 self .request_refresh = smarter_request_refresh
193+ self .get_term_wh = get_term_wh
194+ self .get_cursor_vertical_diff = get_cursor_vertical_diff
186195
187196 self .status_bar = StatusBar (banner if config .curtsies_fill_terminal else '' , _ (
188197 " <%s> Rewind <%s> Save <%s> Pastebin <%s> Editor"
@@ -233,12 +242,24 @@ def __enter__(self):
233242 sys .stdout = self .stdout
234243 sys .stderr = self .stderr
235244 sys .stdin = self .stdin
245+ self .orig_sigwinch_handler = signal .getsignal (signal .SIGWINCH )
246+ signal .signal (signal .SIGWINCH , self .sigwinch_handler )
236247 return self
237248
238249 def __exit__ (self , * args ):
239250 sys .stdin = self .orig_stdin
240251 sys .stdout = self .orig_stdout
241252 sys .stderr = self .orig_stderr
253+ signal .signal (signal .SIGWINCH , self .orig_sigwinch_handler )
254+
255+ def sigwinch_handler (self , signum , frame ):
256+ old_rows , old_columns = self .height , self .width
257+ self .width , self .height = self .get_term_wh ()
258+ cursor_dy = self .get_cursor_vertical_diff ()
259+ logging .debug ('sigwinch! Changed from %r to %r' , (old_rows , old_columns ), (self .height , self .width ))
260+ logging .debug ('cursor moved %d lines down' , cursor_dy )
261+ self .scroll_offset -= cursor_dy
262+ logging .debug ('scroll offset is now %d' , self .scroll_offset )
242263
243264 def clean_up_current_line_for_exit (self ):
244265 """Called when trying to exit to prep for final paint"""
@@ -264,11 +285,6 @@ def process_event(self, e):
264285 else :
265286 assert self .coderunner .code_is_waiting
266287 self .run_code_and_maybe_finish ()
267- elif isinstance (e , events .WindowChangeEvent ):
268- logging .debug ('window change to %d %d' , e .width , e .height )
269- self .scroll_offset -= e .cursor_dy
270- self .width , self .height = e .width , e .height
271-
272288 elif self .status_bar .has_focus :
273289 return self .status_bar .process_event (e )
274290
0 commit comments