terminal.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. """
  2. get_terminal_size() -- return width and height of terminal as a tuple
  3. code from:
  4. http://stackoverflow.com/questions/566746/how-to-get-console- window-width-in-
  5. python
  6. written by
  7. Harco Kuppens (http://stackoverflow.com/users/825214/harco-kuppens)
  8. It is mentioned in the stackoverflow response that this code works
  9. on linux, os x, windows and cygwin (windows).
  10. """
  11. from __future__ import print_function
  12. import os
  13. import shutil
  14. import subprocess
  15. from pandas.compat import PY3
  16. __all__ = ['get_terminal_size', 'is_terminal']
  17. def get_terminal_size():
  18. """
  19. Detect terminal size and return tuple = (width, height).
  20. Only to be used when running in a terminal. Note that the IPython notebook,
  21. IPython zmq frontends, or IDLE do not run in a terminal,
  22. """
  23. import platform
  24. if PY3:
  25. return shutil.get_terminal_size()
  26. current_os = platform.system()
  27. tuple_xy = None
  28. if current_os == 'Windows':
  29. tuple_xy = _get_terminal_size_windows()
  30. if tuple_xy is None:
  31. tuple_xy = _get_terminal_size_tput()
  32. # needed for window's python in cygwin's xterm!
  33. if (current_os == 'Linux' or current_os == 'Darwin' or
  34. current_os.startswith('CYGWIN')):
  35. tuple_xy = _get_terminal_size_linux()
  36. if tuple_xy is None:
  37. tuple_xy = (80, 25) # default value
  38. return tuple_xy
  39. def is_terminal():
  40. """
  41. Detect if Python is running in a terminal.
  42. Returns True if Python is running in a terminal or False if not.
  43. """
  44. try:
  45. ip = get_ipython()
  46. except NameError: # assume standard Python interpreter in a terminal
  47. return True
  48. else:
  49. if hasattr(ip, 'kernel'): # IPython as a Jupyter kernel
  50. return False
  51. else: # IPython in a terminal
  52. return True
  53. def _get_terminal_size_windows():
  54. try:
  55. from ctypes import windll, create_string_buffer
  56. # stdin handle is -10
  57. # stdout handle is -11
  58. # stderr handle is -12
  59. h = windll.kernel32.GetStdHandle(-12)
  60. csbi = create_string_buffer(22)
  61. res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
  62. except (AttributeError, ValueError):
  63. return None
  64. if res:
  65. import struct
  66. (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx,
  67. maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
  68. sizex = right - left + 1
  69. sizey = bottom - top + 1
  70. return sizex, sizey
  71. else:
  72. return None
  73. def _get_terminal_size_tput():
  74. # get terminal width
  75. # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width
  76. # -height-of-a-terminal-window
  77. try:
  78. proc = subprocess.Popen(["tput", "cols"],
  79. stdin=subprocess.PIPE,
  80. stdout=subprocess.PIPE)
  81. output_cols = proc.communicate(input=None)
  82. proc = subprocess.Popen(["tput", "lines"],
  83. stdin=subprocess.PIPE,
  84. stdout=subprocess.PIPE)
  85. output_rows = proc.communicate(input=None)
  86. except OSError:
  87. return None
  88. try:
  89. # Some terminals (e.g. spyder) may report a terminal size of '',
  90. # making the `int` fail.
  91. cols = int(output_cols[0])
  92. rows = int(output_rows[0])
  93. return cols, rows
  94. except (ValueError, IndexError):
  95. return None
  96. def _get_terminal_size_linux():
  97. def ioctl_GWINSZ(fd):
  98. try:
  99. import fcntl
  100. import termios
  101. import struct
  102. cr = struct.unpack(
  103. 'hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
  104. except (struct.error, IOError):
  105. return None
  106. return cr
  107. cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
  108. if not cr:
  109. try:
  110. fd = os.open(os.ctermid(), os.O_RDONLY)
  111. cr = ioctl_GWINSZ(fd)
  112. os.close(fd)
  113. except OSError:
  114. pass
  115. if not cr or cr == (0, 0):
  116. try:
  117. from os import environ as env
  118. cr = (env['LINES'], env['COLUMNS'])
  119. except (ValueError, KeyError):
  120. return None
  121. return int(cr[1]), int(cr[0])
  122. if __name__ == "__main__":
  123. sizex, sizey = get_terminal_size()
  124. print('width = {w} height = {h}'.format(w=sizex, h=sizey))