Skip to content

Instantly share code, notes, and snippets.

@bcbnz
Created November 28, 2011 10:00
Show Gist options
  • Save bcbnz/1399831 to your computer and use it in GitHub Desktop.
Save bcbnz/1399831 to your computer and use it in GitHub Desktop.
Try to find the size of a terminal window.
import fcntl
import os
import struct
import sys
import termios
def window_size(fd):
"""Try to get the size of a terminal window.
:param fd: The file descriptor of the terminal window.
:return: The size of the terminal window as a tuple (width, height), or None
if it cannot be determined.
"""
try:
# Make an IOCTL call to get the size. The second argument is a constant
# telling IOCTL we want the size. The third argument is a string
# of the same length as the output data, in this case four bytes (two
# each for width and height).
s = fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')
# Unpack the resulting structure into two values.
size = struct.unpack('hh', s)
except:
return None
# Flip the result into the desired order and ensure the values are integers.
return (int(size[1]), int(size[0]))
def terminal_size():
"""Try to get the size of the current terminal. The following series of
steps is used to get the size:
* Try to get the size from one of the sys.stdout, sys.stderr or sys.stdin
file descriptors.
* If that fails, open the controlling terminal of the process (defined in
os.ctermid) and try to get the size from that.
* If that fails, try reading it from the LINES and COLUMNS environment
variables.
* Finally, default to an 80x24 terminal.
:return: The size of the current terminal window as a tuple (width, height).
"""
# Try getting it from one of the standard file descriptors.
print 'Trying IOCTL on stdout...'
size = window_size(sys.stdout.fileno())
if not size:
print 'Trying IOCTL on stderr...'
size = window_size(sys.stderr.fileno())
if not size:
print 'Trying IOCTL on stdin...'
size = window_size(sys.stdin.fileno())
# If that didn't work, open the controlling terminal and try getting the
# size from there.
if not size:
print 'Trying IOCTL on controlling terminal...'
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
size = window_size(fd)
os.close(fd)
except:
pass
# If that didn't work, try the environment variables.
if not size:
print 'Trying COLUMNS/LINES shell variables...'
try:
size = (os.environ['COLUMNS'], os.environ['LINES'])
except:
pass
# Unable to find the real size, assume 80x24.
if not size:
print 'Assuming 80x24...'
size = (80, 24)
# Done.
return size
print terminal_size()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment