77import select
88import shlex
99import struct
10- import sys
1110import termios
11+ import time
1212from pty import CHILD , fork
1313from unittest import TestCase
1414
1919from kitty .options .parse import merge_result_dicts
2020from kitty .options .types import Options , defaults
2121from kitty .types import MouseEvent
22- from kitty .utils import no_echo , write_all
22+ from kitty .utils import read_screen_size , write_all
2323
2424
2525class Callbacks :
@@ -139,9 +139,9 @@ def create_screen(self, cols=5, lines=5, scrollback=5, cell_width=10, cell_heigh
139139 s = Screen (c , lines , cols , scrollback , cell_width , cell_height , 0 , c )
140140 return s
141141
142- def create_pty (self , argv , cols = 80 , lines = 25 , scrollback = 100 , cell_width = 10 , cell_height = 20 , options = None , cwd = None ):
142+ def create_pty (self , argv , cols = 80 , lines = 25 , scrollback = 100 , cell_width = 10 , cell_height = 20 , options = None , cwd = None , env = None ):
143143 self .set_options (options )
144- return PTY (argv , lines , cols , scrollback , cell_width , cell_height , cwd )
144+ return PTY (argv , lines , cols , scrollback , cell_width , cell_height , cwd , env )
145145
146146 def assertEqualAttributes (self , c1 , c2 ):
147147 x1 , y1 , c1 .x , c1 .y = c1 .x , c1 .y , 0 , 0
@@ -154,23 +154,27 @@ def assertEqualAttributes(self, c1, c2):
154154
155155class PTY :
156156
157- def __init__ (self , argv , rows = 25 , columns = 80 , scrollback = 100 , cell_width = 10 , cell_height = 20 , cwd = None ):
157+ def __init__ (self , argv , rows = 25 , columns = 80 , scrollback = 100 , cell_width = 10 , cell_height = 20 , cwd = None , env = None ):
158158 pid , self .master_fd = fork ()
159159 self .is_child = pid == CHILD
160160 if self .is_child :
161+ while read_screen_size ().width != columns * cell_width :
162+ time .sleep (0.01 )
161163 if cwd :
162164 os .chdir (cwd )
165+ if env :
166+ os .environ .clear ()
167+ os .environ .update (env )
163168 if isinstance (argv , str ):
164169 argv = shlex .split (argv )
165- with no_echo ():
166- sys .stdin .readline ()
167170 os .execlp (argv [0 ], * argv )
168171 os .set_blocking (self .master_fd , False )
172+ self .cell_width = cell_width
173+ self .cell_height = cell_height
169174 self .set_window_size (rows = rows , columns = columns )
170175 new = termios .tcgetattr (self .master_fd )
171176 new [3 ] = new [3 ] & ~ termios .ECHO
172177 termios .tcsetattr (self .master_fd , termios .TCSADRAIN , new )
173- self .write_to_child ('ready\r \n ' )
174178 self .callbacks = Callbacks ()
175179 self .screen = Screen (self .callbacks , rows , columns , scrollback , cell_width , cell_height , 0 , self .callbacks )
176180
@@ -186,7 +190,11 @@ def wait_for_input_from_child(self, timeout=10):
186190 rd = select .select ([self .master_fd ], [], [], timeout )[0 ]
187191 return bool (rd )
188192
189- def process_input_from_child (self ):
193+ def send_cmd_to_child (self , cmd ):
194+ self .write_to_child (cmd + '\r ' )
195+
196+ def process_input_from_child (self , timeout = 10 ):
197+ self .wait_for_input_from_child (timeout = 10 )
190198 bytes_read = 0
191199 while True :
192200 try :
@@ -199,7 +207,16 @@ def process_input_from_child(self):
199207 parse_bytes (self .screen , data )
200208 return bytes_read
201209
202- def set_window_size (self , rows = 25 , columns = 80 , x_pixels = 0 , y_pixels = 0 ):
210+ def wait_till (self , q , timeout = 10 ):
211+ st = time .monotonic ()
212+ while not q () and time .monotonic () - st < timeout :
213+ self .process_input_from_child (timeout = timeout - (time .monotonic () - st ))
214+ if not q ():
215+ raise TimeoutError ('The condition was not met' )
216+
217+ def set_window_size (self , rows = 25 , columns = 80 ):
218+ x_pixels = columns * self .cell_width
219+ y_pixels = rows * self .cell_height
203220 s = struct .pack ('HHHH' , rows , columns , x_pixels , y_pixels )
204221 fcntl .ioctl (self .master_fd , termios .TIOCSWINSZ , s )
205222
@@ -210,3 +227,9 @@ def screen_contents(self):
210227 if x :
211228 lines .append (x )
212229 return '\n ' .join (lines )
230+
231+ def last_cmd_output (self , as_ansi = False , add_wrap_markers = False ):
232+ lines = []
233+ from kitty .window import CommandOutput
234+ self .screen .cmd_output (CommandOutput .last_run , lines .append , as_ansi , add_wrap_markers )
235+ return '' .join (lines )
0 commit comments