@@ -1867,6 +1867,60 @@ fn os_strerror(e: i32) -> String {
1867
1867
. into_owned ( )
1868
1868
}
1869
1869
1870
+ #[ pystruct_sequence( name = "os.terminal_size" ) ]
1871
+ #[ allow( dead_code) ]
1872
+ struct PyTerminalSize {
1873
+ columns : usize ,
1874
+ lines : usize ,
1875
+ }
1876
+
1877
+ fn os_get_terminal_size ( fd : OptionalArg < i32 > , vm : & VirtualMachine ) -> PyResult < PyTupleRef > {
1878
+ let ( columns, lines) = {
1879
+ #[ cfg( unix) ]
1880
+ {
1881
+ nix:: ioctl_read_bad!( winsz, libc:: TIOCGWINSZ , libc:: winsize) ;
1882
+ let mut w = libc:: winsize {
1883
+ ws_row : 0 ,
1884
+ ws_col : 0 ,
1885
+ ws_xpixel : 0 ,
1886
+ ws_ypixel : 0 ,
1887
+ } ;
1888
+ unsafe { winsz ( fd. unwrap_or ( libc:: STDOUT_FILENO ) , & mut w) }
1889
+ . map_err ( |e| convert_nix_error ( vm, e) ) ?;
1890
+ ( w. ws_col . into ( ) , w. ws_row . into ( ) )
1891
+ }
1892
+ #[ cfg( windows) ]
1893
+ {
1894
+ use winapi:: um:: { handleapi, processenv, winbase, wincon} ;
1895
+ let stdhandle = match fd {
1896
+ OptionalArg :: Present ( 0 ) => winbase:: STD_INPUT_HANDLE ,
1897
+ OptionalArg :: Present ( 1 ) | OptionalArg :: Missing => winbase:: STD_OUTPUT_HANDLE ,
1898
+ OptionalArg :: Present ( 2 ) => winbase:: STD_ERROR_HANDLE ,
1899
+ _ => return Err ( vm. new_value_error ( "bad file descriptor" . to_owned ( ) ) ) ,
1900
+ } ;
1901
+ let h = unsafe { processenv:: GetStdHandle ( stdhandle) } ;
1902
+ if h. is_null ( ) {
1903
+ return Err ( vm. new_os_error ( "handle cannot be retrieved" . to_owned ( ) ) ) ;
1904
+ }
1905
+ if h == handleapi:: INVALID_HANDLE_VALUE {
1906
+ return Err ( errno_err ( vm) ) ;
1907
+ }
1908
+ let mut csbi = wincon:: CONSOLE_SCREEN_BUFFER_INFO :: default ( ) ;
1909
+ let ret = unsafe { wincon:: GetConsoleScreenBufferInfo ( h, & mut csbi) } ;
1910
+ if ret == 0 {
1911
+ return Err ( errno_err ( vm) ) ;
1912
+ }
1913
+ let w = csbi. srWindow ;
1914
+ (
1915
+ ( w. Right - w. Left + 1 ) as usize ,
1916
+ ( w. Bottom - w. Top + 1 ) as usize ,
1917
+ )
1918
+ }
1919
+ } ;
1920
+ PyTerminalSize { columns, lines }
1921
+ . into_struct_sequence ( vm, vm. try_class ( MODULE_NAME , "terminal_size" ) ?)
1922
+ }
1923
+
1870
1924
pub fn make_module ( vm : & VirtualMachine ) -> PyObjectRef {
1871
1925
let ctx = & vm. ctx ;
1872
1926
@@ -1885,6 +1939,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
1885
1939
} ) ;
1886
1940
1887
1941
let stat_result = StatResult :: make_class ( ctx) ;
1942
+ let terminal_size = PyTerminalSize :: make_class ( ctx) ;
1888
1943
1889
1944
struct SupportFunc < ' a > {
1890
1945
name : & ' a str ,
@@ -1964,6 +2019,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
1964
2019
"ScandirIter" => scandir_iter,
1965
2020
"DirEntry" => dir_entry,
1966
2021
"stat_result" => stat_result,
2022
+ "terminal_size" => terminal_size,
1967
2023
"lstat" => ctx. new_function( os_lstat) ,
1968
2024
"getcwd" => ctx. new_function( os_getcwd) ,
1969
2025
"chdir" => ctx. new_function( os_chdir) ,
@@ -1978,6 +2034,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
1978
2034
"link" => ctx. new_function( os_link) ,
1979
2035
"kill" => ctx. new_function( os_kill) ,
1980
2036
"strerror" => ctx. new_function( os_strerror) ,
2037
+ "get_terminal_size" => ctx. new_function( os_get_terminal_size) ,
1981
2038
1982
2039
"O_RDONLY" => ctx. new_int( libc:: O_RDONLY ) ,
1983
2040
"O_WRONLY" => ctx. new_int( libc:: O_WRONLY ) ,
0 commit comments