diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-12-23 18:53:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-12-23 18:53:19 +0000 |
commit | 38d39f536e5a6cff5a218c5dc16994d6eee087e9 (patch) | |
tree | 151b916ddadb35113bac2cd954d99ea26ec64cc0 /terminaltables3/terminal_io.py | |
parent | Updating source url in copyright. (diff) | |
download | terminaltables-38d39f536e5a6cff5a218c5dc16994d6eee087e9.tar.xz terminaltables-38d39f536e5a6cff5a218c5dc16994d6eee087e9.zip |
Merging upstream version 4.0.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'terminaltables3/terminal_io.py')
-rw-r--r-- | terminaltables3/terminal_io.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/terminaltables3/terminal_io.py b/terminaltables3/terminal_io.py new file mode 100644 index 0000000..dc04431 --- /dev/null +++ b/terminaltables3/terminal_io.py @@ -0,0 +1,102 @@ +"""Get info about the current terminal window/screen buffer.""" + +import ctypes +import struct +import sys +from typing import Tuple, Union + +DEFAULT_HEIGHT = 24 +DEFAULT_WIDTH = 79 +INVALID_HANDLE_VALUE = -1 +IS_WINDOWS = sys.platform == "win32" +STD_ERROR_HANDLE = -12 +STD_OUTPUT_HANDLE = -11 + + +def get_console_info(kernel32, handle: int) -> Tuple[int, int]: + """Get information about this current console window (Windows only). + + https://github.com/Robpol86/colorclass/blob/ab42da59/colorclass/windows.py#L111 + + :raise OSError: When handle is invalid or GetConsoleScreenBufferInfo API call fails. + + :param ctypes.windll.kernel32 kernel32: Loaded kernel32 instance. + :param int handle: stderr or stdout handle. + + :return: Width (number of characters) and height (number of lines) of the terminal. + :rtype: tuple + """ + if handle == INVALID_HANDLE_VALUE: + raise OSError("Invalid handle.") + + # Query Win32 API. + lpcsbi = ctypes.create_string_buffer(22) # Populated by GetConsoleScreenBufferInfo. + if not kernel32.GetConsoleScreenBufferInfo(handle, lpcsbi): + raise ctypes.WinError() # Subclass of OSError. + + # Parse data. + left, top, right, bottom = struct.unpack("hhhhHhhhhhh", lpcsbi.raw)[5:-2] + width, height = right - left, bottom - top + return width, height + + +def terminal_size(kernel32=None) -> Tuple[int, int]: + """Get the width and height of the terminal. + + http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/ + http://stackoverflow.com/questions/17993814/why-the-irrelevant-code-made-a-difference + + :param kernel32: Optional mock kernel32 object. For testing. + + :return: Width (number of characters) and height (number of lines) of the terminal. + :rtype: tuple + """ + if IS_WINDOWS: + kernel32 = kernel32 or ctypes.windll.kernel32 + try: + return get_console_info(kernel32, kernel32.GetStdHandle(STD_ERROR_HANDLE)) + except OSError: + try: + return get_console_info( + kernel32, kernel32.GetStdHandle(STD_OUTPUT_HANDLE) + ) + except OSError: + return DEFAULT_WIDTH, DEFAULT_HEIGHT + + try: + device = __import__("fcntl").ioctl( + 0, __import__("termios").TIOCGWINSZ, "\0\0\0\0\0\0\0\0" + ) + except OSError: + return DEFAULT_WIDTH, DEFAULT_HEIGHT + height, width = struct.unpack("hhhh", device)[:2] + return width, height + + +def set_terminal_title(title: Union[str, bytes], kernel32=None) -> bool: + """Set the terminal title. + + :param title: The title to set (string, unicode, bytes accepted). + :param kernel32: Optional mock kernel32 object. For testing. + + :return: If title changed successfully (Windows only, always True on Linux/OSX). + :rtype: bool + """ + try: + title_bytes = title.encode("utf-8") + except AttributeError: + title_bytes = title + + if IS_WINDOWS: + kernel32 = kernel32 or ctypes.windll.kernel32 + try: + is_ascii = all(ord(c) < 128 for c in title) # str/unicode. + except TypeError: + is_ascii = all(c < 128 for c in title) # bytes. + if is_ascii: + return kernel32.SetConsoleTitleA(title_bytes) != 0 + return kernel32.SetConsoleTitleW(title) != 0 + + # Linux/OSX. + sys.stdout.write(b"\033]0;" + title_bytes + b"\007") + return True |