The default behavior of Python's output is if it has output which is too long, it wraps it exactly at the point where the output is too long. Often, it breaks in the middle of a word.
I wrote a method which modifies the behavior to prefer breaking on white space near the end of the line, although it'll wrap mid-non-writespace (blackspace? Is there a word for this?) if it has to.
I placed this my Python Startup file:
This should mostly work except TerminalSize isn't a standard Python module (Python 3.4 includes similar functionality in a standard module, but I normally use 2.7).
Here's its contents:
I don't have any questions (although feel free to suggest improvements to the code). I just felt that this was too good to not be shared with anyone else who uses Python. I'd wrap it up and put it on PIP but it would seem a bit odd there given it's more a script that modifies Python than a module that adds-on to Python, if that makes any sense.
I wrote a method which modifies the behavior to prefer breaking on white space near the end of the line, although it'll wrap mid-non-writespace (blackspace? Is there a word for this?) if it has to.
I placed this my Python Startup file:
Code:
from string import whitespace
from TerminalSize import getTerminalSize
# Save original sys.stdout.write implementation - it'll be replaced in a moment.
orgStdOutWrite = sys.stdout.write
class NewStdOut(object):
def wrappedWrite(self, s, width):
if not s:
return
# If there's enough space, just write whatever it is.
if len(s) <= width:
orgStdOutWrite(s)
return
i = 0
# Scan forward to check for a linebreak before the end of the line.
for c in s[:width]:
if c == '\n':
orgStdOutWrite(s[:i + 1])
self.wrappedWrite(s[i + 1:], width)
return
i += 1
i = width
# Scan backwards for the whitespace nearest the end of the line.
for c in s[width - 1::-1]:
if c in whitespace:
orgStdOutWrite(s[:i - 1] + '\n')
self.wrappedWrite(s[i:], width)
return
i -= 1
# If this is an unbroken sequence, then just add a break in the middle.
orgStdOutWrite(s[:width] + '\n')
self.wrappedWrite(s[width:], width)
# Replace the standard write method:
def write(self, s):
self.wrappedWrite(s, getTerminalSize()[0])
# Replace sys.stdout with a new class which forwards from write to wrappedWrite
sys.stdout = NewStdOut()
This should mostly work except TerminalSize isn't a standard Python module (Python 3.4 includes similar functionality in a standard module, but I normally use 2.7).
Here's its contents:
Code:
"""
Taken from http://stackoverflow.com/a/6550596/901641
"""
def getTerminalSize():
import platform
current_os = platform.system()
tuple_xy=None
if current_os == 'Windows':
tuple_xy = _getTerminalSize_windows()
if tuple_xy is None:
tuple_xy = _getTerminalSize_tput()
# needed for window's python in cygwin's xterm!
if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'):
tuple_xy = _getTerminalSize_linux()
if tuple_xy is None:
print "default"
tuple_xy = (80, 25) # default value
return tuple_xy
def _getTerminalSize_windows():
res=None
try:
from ctypes import windll, create_string_buffer
# stdin handle is -10
# stdout handle is -11
# stderr handle is -12
h = windll.kernel32.GetStdHandle(-12)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
except:
return None
if res:
import struct
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
sizex = right - left + 1
sizey = bottom - top + 1
return sizex, sizey
else:
return None
def _getTerminalSize_tput():
# get terminal width
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
try:
import subprocess
proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
cols=int(output[0])
proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
rows=int(output[0])
return (cols,rows)
except:
return None
def _getTerminalSize_linux():
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
except:
return None
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
try:
cr = (env['LINES'], env['COLUMNS'])
except:
return None
return int(cr[1]), int(cr[0])
I don't have any questions (although feel free to suggest improvements to the code). I just felt that this was too good to not be shared with anyone else who uses Python. I'd wrap it up and put it on PIP but it would seem a bit odd there given it's more a script that modifies Python than a module that adds-on to Python, if that makes any sense.
Last edited: