From 7211d45febdb7c9a684c209192ea2138e88a00c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: 2011年9月24日 23:59:56 +0200 Subject: [PATCH] Use TIOCGWINSZ ioctl to query terminal width COLUMNS is a shell variable (updates whenever the window size changes), that usually isn't exported to programs. Therefore checking for COLUMNS in sys.environ will not work in the majority of cases. The proper check is to use the TIOCGWINSZ ioctl on stdout. Why COLUMNS is not exported? Because it can change during the lifetime of a program. Therefore it is better to use the dynamic ioctl. Windows doesn't have a the termios, fcntl modules, so they should not be imported at the top level. windll.kernel32.GetConsoleScreenBufferInfo should be used instead. --- Lib/argparse.py | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 44 insertions(+), 6 deletions(-) diff --git Lib/argparse.py Lib/argparse.py index f0cfe27..7a44ff3 100644 --- Lib/argparse.py +++ Lib/argparse.py @@ -89,6 +89,7 @@ import os as _os import re as _re import sys as _sys import textwrap as _textwrap +import struct as _struct from gettext import gettext as _, ngettext @@ -140,11 +141,52 @@ def _ensure_value(namespace, name, value): setattr(namespace, name, value) return getattr(namespace, name) - # =============== # Formatting Help # =============== +def _terminal_width(default=80): + try: + # An environment variable has higher priority + width = int(_os.environ['COLUMNS']) + return width + except (KeyError, ValueError): + pass + + try: + import fcntl, termios + except ImportError: + # we're not on unix + pass + else: + format = _struct.pack('HHHH', 0, 0, 0, 0) + try: + output = fcntl.ioctl(1, termios.TIOCGWINSZ, format) + width = _struct.unpack('HHHH', output)[1] + return width + except IOError: + pass + + try: + from ctypes import windll, create_string_buffer + except ImportError: + # we're not on windows + pass + else: + 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) = struct.unpack("hhhhHhhhhhh", csbi.raw) + width = right - left + 1 + return width + + # If nothing worked, let's follow the time-honored tradition + return default + + class HelpFormatter(object): """Formatter for generating usage messages and argument help strings. @@ -160,11 +202,7 @@ class HelpFormatter(object): # default setting for width if width is None: - try: - width = int(_os.environ['COLUMNS']) - except (KeyError, ValueError): - width = 80 - width -= 2 + width = _terminal_width() - 2 self._prog = prog self._indent_increment = indent_increment -- 1.7.6

AltStyle によって変換されたページ (->オリジナル) /