Improved terminal functions.

This commit is contained in:
Bastian Kleineidam 2012-06-20 22:33:26 +02:00
parent 4dec964cb7
commit c9082aee42
4 changed files with 67 additions and 30 deletions

View file

@ -10,6 +10,7 @@ Changes:
- comics: Removed the twisted and zope dependencies by adding
an internal plugin search mechanism.
- testing: Refactored the test comic routine in proper unit tests.
- cmdline: Improved terminal feature detection.
Fixes:
- comics: Adjusted Xkcd href values.

16
dosage
View file

@ -22,7 +22,7 @@ import traceback
from dosagelib import events, scraper
from dosagelib.output import out
from dosagelib.util import getWindowSize, internal_error
from dosagelib.util import is_tty, get_columns, internal_error
from dosagelib.configuration import App, Freeware, Copyright
def setupOptions():
@ -38,14 +38,7 @@ def setupOptions():
parser.add_option('-m', '--module-help', action='store_true', dest='modhelp', help='display help for comic modules')
parser.add_option('-t', '--timestamps', action='store_true', dest='timestamps', default=False, help='print timestamps for all output at any info level')
parser.add_option('-o', '--output', action='store', dest='output', choices=events.getHandlers(), help='output formatting for downloaded comics')
try:
getWindowSize()
except NotImplementedError:
progress = False
else:
progress = True
if progress:
if is_tty(sys.stdout):
parser.add_option('-p', '--progress', action='store_true', dest='progress', default=False, help='display progress bar while downloading comics')
return parser
@ -131,10 +124,7 @@ class Dosage(object):
print '\n'.join(scraper.get_name() for scraper in scrapers)
def doColumnList(self, scrapers):
try:
screenWidth = getWindowSize()
except NotImplementedError:
screenWidth = 80
screenWidth = get_columns()
names = [scraper.get_name() for scraper in scrapers]
maxlen = max([len(name) for name in names])
namesPerLine = int(screenWidth / (maxlen + 1))

22
dosagelib/fileutil.py Normal file
View file

@ -0,0 +1,22 @@
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2012 Bastian Kleineidam
"""
File and path utilities.
"""
def has_module (name):
"""Test if given module can be imported.
@return: flag if import is successful
@rtype: bool
"""
try:
exec "import %s as _bla" % name
return True
except (OSError, ImportError):
# some modules (for example HTMLtidy) raise OSError
return False
def is_tty (fp):
"""Check if a file object is a TTY."""
return (hasattr(fp, "isatty") and fp.isatty())

View file

@ -2,8 +2,6 @@ from __future__ import division
import urllib2, urlparse
import sys
import struct
import array
import os
import cgi
import re
@ -14,6 +12,12 @@ from math import log, floor
from .output import out
from .configuration import UserAgent, AppName, App, SupportUrl
from .fileutil import has_module, is_tty
has_wconio = has_module("WConio")
has_curses = has_module("curses")
has_fcntl = has_module('fcntl')
has_termios = has_module('termios')
class NoMatchError(Exception): pass
@ -148,21 +152,41 @@ def urlopen(url, referrer=None, retries=5):
return urlobj
def getWindowSize():
try:
from fcntl import ioctl
from termios import TIOCGWINSZ
except ImportError:
raise NotImplementedError
st = 'HHHH'
names = 'ws_row', 'ws_col', 'ws_xpixel', 'ws_ypixel'
buf = array.array('b', ' ' * struct.calcsize(st))
try:
ioctl(sys.stderr, TIOCGWINSZ, buf, True)
except IOError:
raise NotImplementedError
winsize = dict(zip(names, struct.unpack(st, buf.tostring())))
return winsize['ws_col']
def get_columns (fp):
"""Return number of columns for given file."""
if not is_tty(fp):
return 80
if has_wconio:
import WConio
# gettextinfo() returns a tuple
# - left, top, right, bottom: window coordinates
# - textattr, normattr: current attributes
# - videomode: current video mode
# - height, width: screen size
# - curx, cury: current cursor position
# return the width:
return WConio.gettextinfo()[8]
if has_curses:
import curses
try:
curses.setupterm()
return curses.tigetnum("cols")
except curses.error:
pass
if has_fcntl and has_termios:
import fcntl, termios, array, struct
st = 'HHHH'
names = 'ws_row', 'ws_col', 'ws_xpixel', 'ws_ypixel'
buf = array.array('b', ' ' * struct.calcsize(st))
try:
fcntl.ioctl(fp, termios.TIOCGWINSZ, buf, True)
winsize = dict(zip(names, struct.unpack(st, buf.tostring())))
return winsize['ws_col']
except IOError:
pass
return 80
suffixes = ('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')