mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-11 09:13:57 -04:00
Re-indent libprs500.cli to 4 spaces as per PEP8
This commit is contained in:
parent
567017f238
commit
4b2afac719
@ -30,275 +30,275 @@ from libprs500.errors import ArgumentError, DeviceError
|
||||
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
|
||||
|
||||
def human_readable(size):
|
||||
""" Convert a size in bytes into a human readle form """
|
||||
if size < 1024: divisor, suffix = 1, ""
|
||||
elif size < 1024*1024: divisor, suffix = 1024., "K"
|
||||
elif size < 1024*1024*1024: divisor, suffix = 1024*1024, "M"
|
||||
elif size < 1024*1024*1024*1024: divisor, suffix = 1024*1024, "G"
|
||||
size = str(size/divisor)
|
||||
if size.find(".") > -1: size = size[:size.find(".")+2]
|
||||
return size + suffix
|
||||
""" Convert a size in bytes into a human readle form """
|
||||
if size < 1024: divisor, suffix = 1, ""
|
||||
elif size < 1024*1024: divisor, suffix = 1024., "K"
|
||||
elif size < 1024*1024*1024: divisor, suffix = 1024*1024, "M"
|
||||
elif size < 1024*1024*1024*1024: divisor, suffix = 1024*1024, "G"
|
||||
size = str(size/divisor)
|
||||
if size.find(".") > -1: size = size[:size.find(".")+2]
|
||||
return size + suffix
|
||||
|
||||
class FileFormatter(object):
|
||||
def __init__(self, file, term):
|
||||
self.term = term
|
||||
self.is_dir = file.is_dir
|
||||
self.is_readonly = file.is_readonly
|
||||
self.size = file.size
|
||||
self.ctime = file.ctime
|
||||
self.wtime = file.wtime
|
||||
self.name = file.name
|
||||
self.path = file.path
|
||||
def __init__(self, file, term):
|
||||
self.term = term
|
||||
self.is_dir = file.is_dir
|
||||
self.is_readonly = file.is_readonly
|
||||
self.size = file.size
|
||||
self.ctime = file.ctime
|
||||
self.wtime = file.wtime
|
||||
self.name = file.name
|
||||
self.path = file.path
|
||||
|
||||
@apply
|
||||
def mode_string():
|
||||
doc=""" The mode string for this file. There are only two modes read-only and read-write """
|
||||
def fget(self):
|
||||
mode, x = "-", "-"
|
||||
if self.is_dir: mode, x = "d", "x"
|
||||
if self.is_readonly: mode += "r-"+x+"r-"+x+"r-"+x
|
||||
else: mode += "rw"+x+"rw"+x+"rw"+x
|
||||
return mode
|
||||
return property(**locals())
|
||||
@apply
|
||||
def mode_string():
|
||||
doc=""" The mode string for this file. There are only two modes read-only and read-write """
|
||||
def fget(self):
|
||||
mode, x = "-", "-"
|
||||
if self.is_dir: mode, x = "d", "x"
|
||||
if self.is_readonly: mode += "r-"+x+"r-"+x+"r-"+x
|
||||
else: mode += "rw"+x+"rw"+x+"rw"+x
|
||||
return mode
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def name_in_color():
|
||||
doc=""" The name in ANSI text. Directories are blue, ebooks are green """
|
||||
def fget(self):
|
||||
cname = self.name
|
||||
blue, green, normal = "", "", ""
|
||||
if self.term: blue, green, normal = self.term.BLUE, self.term.GREEN, self.term.NORMAL
|
||||
if self.is_dir: cname = blue + self.name + normal
|
||||
else:
|
||||
ext = self.name[self.name.rfind("."):]
|
||||
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): cname = green + self.name + normal
|
||||
return cname
|
||||
return property(**locals())
|
||||
@apply
|
||||
def name_in_color():
|
||||
doc=""" The name in ANSI text. Directories are blue, ebooks are green """
|
||||
def fget(self):
|
||||
cname = self.name
|
||||
blue, green, normal = "", "", ""
|
||||
if self.term: blue, green, normal = self.term.BLUE, self.term.GREEN, self.term.NORMAL
|
||||
if self.is_dir: cname = blue + self.name + normal
|
||||
else:
|
||||
ext = self.name[self.name.rfind("."):]
|
||||
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): cname = green + self.name + normal
|
||||
return cname
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def human_readable_size():
|
||||
doc=""" File size in human readable form """
|
||||
def fget(self):
|
||||
human_readable(self.size)
|
||||
return property(**locals())
|
||||
@apply
|
||||
def human_readable_size():
|
||||
doc=""" File size in human readable form """
|
||||
def fget(self):
|
||||
human_readable(self.size)
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def modification_time():
|
||||
doc=""" Last modified time in the Linux ls -l format """
|
||||
def fget(self):
|
||||
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime))
|
||||
return property(**locals())
|
||||
@apply
|
||||
def modification_time():
|
||||
doc=""" Last modified time in the Linux ls -l format """
|
||||
def fget(self):
|
||||
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime))
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def creation_time():
|
||||
doc=""" Last modified time in the Linux ls -l format """
|
||||
def fget(self):
|
||||
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime))
|
||||
return property(**locals())
|
||||
@apply
|
||||
def creation_time():
|
||||
doc=""" Last modified time in the Linux ls -l format """
|
||||
def fget(self):
|
||||
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime))
|
||||
return property(**locals())
|
||||
|
||||
def info(dev):
|
||||
info = dev.get_device_information()
|
||||
print "Device name: ", info[0]
|
||||
print "Device version: ", info[1]
|
||||
print "Software version:", info[2]
|
||||
print "Mime type: ", info[3]
|
||||
info = dev.get_device_information()
|
||||
print "Device name: ", info[0]
|
||||
print "Device version: ", info[1]
|
||||
print "Software version:", info[2]
|
||||
print "Mime type: ", info[3]
|
||||
|
||||
def ls(dev, path, term, recurse=False, color=False, human_readable_size=False, ll=False, cols=0):
|
||||
def col_split(l, cols): # split list l into columns
|
||||
rows = len(l) / cols
|
||||
if len(l) % cols:
|
||||
rows += 1
|
||||
m = []
|
||||
for i in range(rows):
|
||||
m.append(l[i::rows])
|
||||
return m
|
||||
|
||||
def row_widths(table): # Calculate widths for each column in the row-wise table
|
||||
tcols = len(table[0])
|
||||
rowwidths = [ 0 for i in range(tcols) ]
|
||||
for row in table:
|
||||
c = 0
|
||||
for item in row:
|
||||
rowwidths[c] = len(item) if len(item) > rowwidths[c] else rowwidths[c]
|
||||
c += 1
|
||||
return rowwidths
|
||||
|
||||
output = StringIO.StringIO()
|
||||
if path.endswith("/"): path = path[:-1]
|
||||
dirs = dev.list(path, recurse)
|
||||
for dir in dirs:
|
||||
if recurse: print >>output, dir[0] + ":"
|
||||
lsoutput, lscoloutput = [], []
|
||||
files = dir[1]
|
||||
maxlen = 0
|
||||
if ll: # Calculate column width for size column
|
||||
for file in files:
|
||||
size = len(str(file.size))
|
||||
if human_readable_size:
|
||||
file = FileFormatter(file, term)
|
||||
size = len(file.human_readable_size)
|
||||
if size > maxlen: maxlen = size
|
||||
for file in files:
|
||||
file = FileFormatter(file, term)
|
||||
name = file.name
|
||||
lsoutput.append(name)
|
||||
if color: name = file.name_in_color
|
||||
lscoloutput.append(name)
|
||||
if ll:
|
||||
size = str(file.size)
|
||||
if human_readable_size: size = file.human_readable_size
|
||||
print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name
|
||||
if not ll and len(lsoutput) > 0:
|
||||
trytable = []
|
||||
for colwidth in range(MINIMUM_COL_WIDTH, cols):
|
||||
trycols = int(cols/colwidth)
|
||||
trytable = col_split(lsoutput, trycols)
|
||||
works = True
|
||||
for row in trytable:
|
||||
row_break = False
|
||||
for item in row:
|
||||
if len(item) > colwidth - 1:
|
||||
works, row_break = False, True
|
||||
break
|
||||
if row_break: break
|
||||
if works: break
|
||||
rowwidths = row_widths(trytable)
|
||||
trytablecol = col_split(lscoloutput, len(trytable[0]))
|
||||
for r in range(len(trytable)):
|
||||
for c in range(len(trytable[r])):
|
||||
padding = rowwidths[c] - len(trytable[r][c])
|
||||
print >>output, trytablecol[r][c], "".ljust(padding),
|
||||
print >>output
|
||||
print >>output
|
||||
listing = output.getvalue().rstrip()+ "\n"
|
||||
output.close()
|
||||
return listing
|
||||
def col_split(l, cols): # split list l into columns
|
||||
rows = len(l) / cols
|
||||
if len(l) % cols:
|
||||
rows += 1
|
||||
m = []
|
||||
for i in range(rows):
|
||||
m.append(l[i::rows])
|
||||
return m
|
||||
|
||||
def row_widths(table): # Calculate widths for each column in the row-wise table
|
||||
tcols = len(table[0])
|
||||
rowwidths = [ 0 for i in range(tcols) ]
|
||||
for row in table:
|
||||
c = 0
|
||||
for item in row:
|
||||
rowwidths[c] = len(item) if len(item) > rowwidths[c] else rowwidths[c]
|
||||
c += 1
|
||||
return rowwidths
|
||||
|
||||
output = StringIO.StringIO()
|
||||
if path.endswith("/"): path = path[:-1]
|
||||
dirs = dev.list(path, recurse)
|
||||
for dir in dirs:
|
||||
if recurse: print >>output, dir[0] + ":"
|
||||
lsoutput, lscoloutput = [], []
|
||||
files = dir[1]
|
||||
maxlen = 0
|
||||
if ll: # Calculate column width for size column
|
||||
for file in files:
|
||||
size = len(str(file.size))
|
||||
if human_readable_size:
|
||||
file = FileFormatter(file, term)
|
||||
size = len(file.human_readable_size)
|
||||
if size > maxlen: maxlen = size
|
||||
for file in files:
|
||||
file = FileFormatter(file, term)
|
||||
name = file.name
|
||||
lsoutput.append(name)
|
||||
if color: name = file.name_in_color
|
||||
lscoloutput.append(name)
|
||||
if ll:
|
||||
size = str(file.size)
|
||||
if human_readable_size: size = file.human_readable_size
|
||||
print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name
|
||||
if not ll and len(lsoutput) > 0:
|
||||
trytable = []
|
||||
for colwidth in range(MINIMUM_COL_WIDTH, cols):
|
||||
trycols = int(cols/colwidth)
|
||||
trytable = col_split(lsoutput, trycols)
|
||||
works = True
|
||||
for row in trytable:
|
||||
row_break = False
|
||||
for item in row:
|
||||
if len(item) > colwidth - 1:
|
||||
works, row_break = False, True
|
||||
break
|
||||
if row_break: break
|
||||
if works: break
|
||||
rowwidths = row_widths(trytable)
|
||||
trytablecol = col_split(lscoloutput, len(trytable[0]))
|
||||
for r in range(len(trytable)):
|
||||
for c in range(len(trytable[r])):
|
||||
padding = rowwidths[c] - len(trytable[r][c])
|
||||
print >>output, trytablecol[r][c], "".ljust(padding),
|
||||
print >>output
|
||||
print >>output
|
||||
listing = output.getvalue().rstrip()+ "\n"
|
||||
output.close()
|
||||
return listing
|
||||
|
||||
def main():
|
||||
term = TerminalController()
|
||||
cols = term.COLS
|
||||
|
||||
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, books, df, ls, cp, mkdir, touch, cat, rm\n\n"+
|
||||
"For help on a particular command: %prog command", version="libprs500 version: " + VERSION)
|
||||
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
|
||||
term = TerminalController()
|
||||
cols = term.COLS
|
||||
|
||||
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, books, df, ls, cp, mkdir, touch, cat, rm\n\n"+
|
||||
"For help on a particular command: %prog command", version="libprs500 version: " + VERSION)
|
||||
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
|
||||
"The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
|
||||
dest="log_packets", action="store_true", default=False)
|
||||
parser.remove_option("-h")
|
||||
parser.disable_interspersed_args() # Allow unrecognized options
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if len(args) < 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
command = args[0]
|
||||
args = args[1:]
|
||||
dev = PRS500Device(log_packets=options.log_packets)
|
||||
try:
|
||||
if command == "df":
|
||||
total = dev.total_space(end_session=False)
|
||||
free = dev.free_space()
|
||||
where = ("Memory", "Stick", "Card")
|
||||
print "Filesystem\tSize \tUsed \tAvail \tUse%"
|
||||
for i in range(3):
|
||||
print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
|
||||
str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
|
||||
elif command == "books":
|
||||
print "Books in main memory:"
|
||||
for book in dev.books(): print book
|
||||
print "\nBooks on storage card:"
|
||||
for book in dev.books(oncard=True): print book
|
||||
elif command == "mkdir":
|
||||
parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with /,a:/ or b:/")
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
dev.mkdir(args[0])
|
||||
elif command == "ls":
|
||||
parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with /,a:/ or b:/")
|
||||
parser.add_option("--color", help="show ls output in color", dest="color", action="store_true", default=False)
|
||||
parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", dest="ll", action="store_true", default=False)
|
||||
parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False)
|
||||
parser.remove_option("-h")
|
||||
parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False)
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
dest="log_packets", action="store_true", default=False)
|
||||
parser.remove_option("-h")
|
||||
parser.disable_interspersed_args() # Allow unrecognized options
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if len(args) < 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
print ls(dev, args[0], term, color=options.color, recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),
|
||||
elif command == "info":
|
||||
info(dev)
|
||||
elif command == "cp":
|
||||
usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\
|
||||
|
||||
command = args[0]
|
||||
args = args[1:]
|
||||
dev = PRS500Device(log_packets=options.log_packets)
|
||||
try:
|
||||
if command == "df":
|
||||
total = dev.total_space(end_session=False)
|
||||
free = dev.free_space()
|
||||
where = ("Memory", "Stick", "Card")
|
||||
print "Filesystem\tSize \tUsed \tAvail \tUse%"
|
||||
for i in range(3):
|
||||
print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
|
||||
str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
|
||||
elif command == "books":
|
||||
print "Books in main memory:"
|
||||
for book in dev.books(): print book
|
||||
print "\nBooks on storage card:"
|
||||
for book in dev.books(oncard=True): print book
|
||||
elif command == "mkdir":
|
||||
parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with /,a:/ or b:/")
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
dev.mkdir(args[0])
|
||||
elif command == "ls":
|
||||
parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with /,a:/ or b:/")
|
||||
parser.add_option("--color", help="show ls output in color", dest="color", action="store_true", default=False)
|
||||
parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", dest="ll", action="store_true", default=False)
|
||||
parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False)
|
||||
parser.remove_option("-h")
|
||||
parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False)
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
print ls(dev, args[0], term, color=options.color, recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),
|
||||
elif command == "info":
|
||||
info(dev)
|
||||
elif command == "cp":
|
||||
usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\
|
||||
"One of source or destination must be a path on the device. \n\nDevice paths have the form\n"+\
|
||||
"prs500:mountpoint/my/path\n"+\
|
||||
"where mountpoint is one of /, a: or b:\n\n"+\
|
||||
"source must point to a file for which you have read permissions\n"+\
|
||||
"destination must point to a file or directory for which you have write permissions"
|
||||
parser = OptionParser(usage=usage)
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 2:
|
||||
parser.print_help()
|
||||
return 1
|
||||
if args[0].startswith("prs500:"):
|
||||
outfile = args[1]
|
||||
path = args[0][7:]
|
||||
if path.endswith("/"): path = path[:-1]
|
||||
if os.path.isdir(outfile):
|
||||
outfile = os.path.join(outfile, path[path.rfind("/")+1:])
|
||||
try:
|
||||
outfile = open(outfile, "w")
|
||||
except IOError, e:
|
||||
print >> sys.stderr, e
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.get_file(path, outfile)
|
||||
outfile.close()
|
||||
elif args[1].startswith("prs500:"):
|
||||
try:
|
||||
infile = open(args[0], "r")
|
||||
except IOError, e:
|
||||
print >> sys.stderr, e
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.put_file(infile, args[1][7:])
|
||||
infile.close()
|
||||
else:
|
||||
parser.print_help()
|
||||
return 1
|
||||
elif command == "cat":
|
||||
outfile = sys.stdout
|
||||
parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
if args[0].endswith("/"): path = args[0][:-1]
|
||||
else: path = args[0]
|
||||
outfile = sys.stdout
|
||||
dev.get_file(path, outfile)
|
||||
elif command == "rm":
|
||||
parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+\
|
||||
parser = OptionParser(usage=usage)
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 2:
|
||||
parser.print_help()
|
||||
return 1
|
||||
if args[0].startswith("prs500:"):
|
||||
outfile = args[1]
|
||||
path = args[0][7:]
|
||||
if path.endswith("/"): path = path[:-1]
|
||||
if os.path.isdir(outfile):
|
||||
outfile = os.path.join(outfile, path[path.rfind("/")+1:])
|
||||
try:
|
||||
outfile = open(outfile, "w")
|
||||
except IOError, e:
|
||||
print >> sys.stderr, e
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.get_file(path, outfile)
|
||||
outfile.close()
|
||||
elif args[1].startswith("prs500:"):
|
||||
try:
|
||||
infile = open(args[0], "r")
|
||||
except IOError, e:
|
||||
print >> sys.stderr, e
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.put_file(infile, args[1][7:])
|
||||
infile.close()
|
||||
else:
|
||||
parser.print_help()
|
||||
return 1
|
||||
elif command == "cat":
|
||||
outfile = sys.stdout
|
||||
parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
if args[0].endswith("/"): path = args[0][:-1]
|
||||
else: path = args[0]
|
||||
outfile = sys.stdout
|
||||
dev.get_file(path, outfile)
|
||||
elif command == "rm":
|
||||
parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+\
|
||||
"and must begin with /,a:/ or b:/\n\n"+\
|
||||
"rm will DELETE the file. Be very CAREFUL")
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.rm(args[0])
|
||||
elif command == "touch":
|
||||
parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+
|
||||
"Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" )
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.touch(args[0])
|
||||
else:
|
||||
parser.print_help()
|
||||
if dev.handle: dev.close()
|
||||
return 1
|
||||
except (ArgumentError, DeviceError), e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
||||
dev.rm(args[0])
|
||||
elif command == "touch":
|
||||
parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+
|
||||
"Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" )
|
||||
options, args = parser.parse_args(args)
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
return 1
|
||||
dev.touch(args[0])
|
||||
else:
|
||||
parser.print_help()
|
||||
if dev.handle: dev.close()
|
||||
return 1
|
||||
except (ArgumentError, DeviceError), e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
||||
return 0
|
||||
return 0
|
||||
|
@ -25,16 +25,16 @@ class TerminalController:
|
||||
values are initialized to the control sequence necessary to
|
||||
perform a given action. These can be simply included in normal
|
||||
output to the terminal:
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> print 'This is '+term.GREEN+'green'+term.NORMAL
|
||||
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> print 'This is '+term.GREEN+'green'+term.NORMAL
|
||||
|
||||
Alternatively, the `render()` method can used, which replaces
|
||||
'${action}' with the string required to perform 'action':
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> print term.render('This is ${GREEN}green${NORMAL}')
|
||||
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> print term.render('This is ${GREEN}green${NORMAL}')
|
||||
|
||||
If the terminal doesn't support a given action, then the value of
|
||||
the corresponding instance variable will be set to ''. As a
|
||||
result, the above code will still work on terminals that do not
|
||||
@ -42,11 +42,11 @@ class TerminalController:
|
||||
Also, this means that you can test whether the terminal supports a
|
||||
given action by simply testing the truth value of the
|
||||
corresponding instance variable:
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> if term.CLEAR_SCREEN:
|
||||
... print 'This terminal supports clearning the screen.'
|
||||
|
||||
|
||||
>>> term = TerminalController()
|
||||
>>> if term.CLEAR_SCREEN:
|
||||
... print 'This terminal supports clearning the screen.'
|
||||
|
||||
Finally, if the width and height of the terminal are known, then
|
||||
they will be stored in the `COLS` and `LINES` attributes.
|
||||
"""
|
||||
@ -56,28 +56,28 @@ class TerminalController:
|
||||
DOWN = '' #: Move the cursor down one line
|
||||
LEFT = '' #: Move the cursor left one char
|
||||
RIGHT = '' #: Move the cursor right one char
|
||||
|
||||
|
||||
# Deletion:
|
||||
CLEAR_SCREEN = '' #: Clear the screen and move to home position
|
||||
CLEAR_EOL = '' #: Clear to the end of the line.
|
||||
CLEAR_BOL = '' #: Clear to the beginning of the line.
|
||||
CLEAR_EOS = '' #: Clear to the end of the screen
|
||||
|
||||
|
||||
# Output modes:
|
||||
BOLD = '' #: Turn on bold mode
|
||||
BLINK = '' #: Turn on blink mode
|
||||
DIM = '' #: Turn on half-bright mode
|
||||
REVERSE = '' #: Turn on reverse-video mode
|
||||
NORMAL = '' #: Turn off all modes
|
||||
|
||||
|
||||
# Cursor display:
|
||||
HIDE_CURSOR = '' #: Make the cursor invisible
|
||||
SHOW_CURSOR = '' #: Make the cursor visible
|
||||
|
||||
|
||||
# Terminal size:
|
||||
COLS = None #: Width of the terminal (None for unknown)
|
||||
LINES = None #: Height of the terminal (None for unknown)
|
||||
|
||||
|
||||
# Foreground colors:
|
||||
BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
|
||||
|
||||
@ -92,7 +92,7 @@ class TerminalController:
|
||||
HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
|
||||
_COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
|
||||
_ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
|
||||
|
||||
|
||||
def __init__(self, term_stream=sys.stdout):
|
||||
"""
|
||||
Create a `TerminalController` and initialize its attributes
|
||||
@ -104,15 +104,15 @@ class TerminalController:
|
||||
# Curses isn't available on all platforms
|
||||
try: import curses
|
||||
except: return
|
||||
|
||||
|
||||
# If the stream isn't a tty, then assume it has no capabilities.
|
||||
if not term_stream.isatty(): return
|
||||
|
||||
|
||||
# Check the terminal type. If we fail, then assume that the
|
||||
# terminal has no capabilities.
|
||||
try: curses.setupterm()
|
||||
except: return
|
||||
|
||||
|
||||
# Look up numeric capabilities.
|
||||
self.COLS = curses.tigetnum('cols')
|
||||
self.LINES = curses.tigetnum('lines')
|
||||
@ -121,7 +121,7 @@ class TerminalController:
|
||||
for capability in self._STRING_CAPABILITIES:
|
||||
(attrib, cap_name) = capability.split('=')
|
||||
setattr(self, attrib, self._tigetstr(cap_name) or '')
|
||||
|
||||
|
||||
# Colors
|
||||
set_fg = self._tigetstr('setf')
|
||||
if set_fg:
|
||||
@ -139,7 +139,7 @@ class TerminalController:
|
||||
if set_bg_ansi:
|
||||
for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
|
||||
setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
|
||||
|
||||
|
||||
def _tigetstr(self, cap_name):
|
||||
# String capabilities can include "delays" of the form "$<2>".
|
||||
# For any modern terminal, we should be able to just ignore
|
||||
@ -147,7 +147,7 @@ class TerminalController:
|
||||
import curses
|
||||
cap = curses.tigetstr(cap_name) or ''
|
||||
return re.sub(r'\$<\d+>[/*]?', '', cap)
|
||||
|
||||
|
||||
def render(self, template):
|
||||
"""
|
||||
Replace each $-substitutions in the given template string with
|
||||
@ -155,7 +155,7 @@ class TerminalController:
|
||||
'' (if it's not).
|
||||
"""
|
||||
return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
|
||||
|
||||
|
||||
def _render_sub(self, match):
|
||||
s = match.group()
|
||||
if s == '$$': return s
|
||||
@ -169,40 +169,40 @@ class ProgressBar:
|
||||
"""
|
||||
A 3-line progress bar, which looks like::
|
||||
|
||||
Header
|
||||
20% [===========----------------------------------]
|
||||
progress message
|
||||
|
||||
Header
|
||||
20% [===========----------------------------------]
|
||||
progress message
|
||||
|
||||
The progress bar is colored, if the terminal supports color
|
||||
output; and adjusts to the width of the terminal.
|
||||
"""
|
||||
BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
|
||||
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
|
||||
|
||||
|
||||
def __init__(self, term, header):
|
||||
self.term = term
|
||||
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
|
||||
raise ValueError("Terminal isn't capable enough -- you "
|
||||
"should use a simpler progress dispaly.")
|
||||
"should use a simpler progress dispaly.")
|
||||
self.width = self.term.COLS or 75
|
||||
self.bar = term.render(self.BAR)
|
||||
self.header = self.term.render(self.HEADER % header.center(self.width))
|
||||
self.cleared = 1 #: true if we haven't drawn the bar yet.
|
||||
self.update(0, '')
|
||||
|
||||
|
||||
def update(self, percent, message):
|
||||
if self.cleared:
|
||||
sys.stdout.write(self.header)
|
||||
self.cleared = 0
|
||||
n = int((self.width-10)*percent)
|
||||
sys.stdout.write(
|
||||
self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
|
||||
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
|
||||
self.term.CLEAR_EOL + message.center(self.width))
|
||||
|
||||
self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
|
||||
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
|
||||
self.term.CLEAR_EOL + message.center(self.width))
|
||||
|
||||
def clear(self):
|
||||
if not self.cleared:
|
||||
sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
|
||||
self.term.UP + self.term.CLEAR_EOL +
|
||||
self.term.UP + self.term.CLEAR_EOL)
|
||||
self.term.UP + self.term.CLEAR_EOL +
|
||||
self.term.UP + self.term.CLEAR_EOL)
|
||||
self.cleared = 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user