Improved terminal functions.
This commit is contained in:
parent
4dec964cb7
commit
c9082aee42
4 changed files with 67 additions and 30 deletions
|
@ -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
16
dosage
|
@ -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
22
dosagelib/fileutil.py
Normal 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())
|
|
@ -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')
|
||||
|
||||
|
|
Loading…
Reference in a new issue