-
-
Save gunchev/c73af70357ff8bcfc3250ee6c84e164d to your computer and use it in GitHub Desktop.
Get current terminal size on Linux, Mac, and Windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
''' | |
Get width and height of console | |
works on Linux, OS X, Windows, Cygwin(Windows) originally retrieved from: | |
http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python | |
updated by Doncho Nikolaev Gunchev <[email protected]> to work with python 2 and 3, make pylint happy. | |
shutil.get_terminal_size() should do fine, however this worked a decade before it and demonstrates various | |
techniques to interact with the OS... | |
''' | |
from __future__ import absolute_import, print_function, division, unicode_literals | |
import os | |
import platform | |
import struct | |
import subprocess | |
def get_terminal_size(): | |
"""Get width and height of console""" | |
current_os = platform.system() | |
if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'): | |
width_height = get_terminal_size_linux() | |
if current_os == 'Windows': | |
width_height = get_terminal_size_windows() | |
if width_height is None: | |
# needed for window's python in cygwin's xterm! | |
width_height = get_terminal_size_tput() | |
return width_height if width_height is not None else (80, 25) | |
def get_terminal_size_windows(): | |
'''Return terminal size in Windows OS or None''' | |
try: # https://pycodequ.al/docs/pylint-messages/c0415-import-outside-toplevel.html | |
from ctypes import windll, create_string_buffer # pylint: disable=import-outside-toplevel | |
# stdin, stdout and stderr handles are -10, -11, -12 | |
handle = windll.kernel32.GetStdHandle(-12) | |
csbi = create_string_buffer(22) | |
res = windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi) | |
if res: | |
# bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy | |
left, top, right, bottom = struct.unpack("hhhhHhhhhhh", csbi.raw)[5:9] | |
return right - left + 1, bottom - top + 1 | |
except ImportError: | |
pass | |
return None | |
def get_terminal_size_tput(): | |
'''Return terminal size using tput or None''' | |
# get terminal width | |
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window | |
try: | |
cols = int(subprocess.check_output(('tput', 'cols'))) | |
rows = int(subprocess.check_output(('tput', 'lines'))) | |
return cols, rows | |
except (EnvironmentError, ValueError): | |
return None | |
def get_terminal_size_stty(): | |
'''Return terminal size using stty or None | |
Should be better than get_terminal_size_tput (calls one external command instead of two, "coreutils" vs "ncurses" | |
''' | |
try: | |
height, width = subprocess.check_output(['stty', 'size']).decode('utf-8').strip().split(' ', 1) | |
return int(width), int(height) | |
except (EnvironmentError, ValueError): | |
return None | |
def ioctl_gwinsz(fd_): | |
'''Get terminal size from a file descriptor using termios.TIOCGWINSZ''' | |
try: # https://pycodequ.al/docs/pylint-messages/c0415-import-outside-toplevel.html | |
import fcntl # pylint: disable=import-outside-toplevel | |
import termios # pylint: disable=import-outside-toplevel | |
return struct.unpack('hh', fcntl.ioctl(fd_, termios.TIOCGWINSZ, '1234')) | |
except (ImportError, EnvironmentError): | |
return None | |
def get_terminal_size_linux(): | |
'''Get terminal size in Linux or None''' | |
width_height = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2) | |
if not width_height: | |
try: | |
fd_ = os.open(os.ctermid(), os.O_RDONLY) | |
width_height = ioctl_gwinsz(fd_) | |
os.close(fd_) | |
except EnvironmentError: | |
pass | |
if width_height: | |
return width_height | |
try: | |
return int(os.environ['COLUMNS']), int(os.environ['LINES']) | |
except (KeyError, ValueError): | |
return None | |
def print_terminal_size(): | |
'''Terminal test function, prints the size''' | |
width, height = get_terminal_size() | |
print('width =', width, 'height =', height) | |
print(get_terminal_size_tput()) | |
print(get_terminal_size_stty()) | |
print(ioctl_gwinsz(1)) | |
if __name__ == "__main__": | |
print_terminal_size() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment