This commit is contained in:
Kovid Goyal 2014-03-28 16:05:23 +05:30
parent 5346868df7
commit a33b6098f7

View File

@ -16,9 +16,10 @@ from calibre.customize.ui import device_plugins
from calibre.devices.scanner import DeviceScanner
from calibre.utils.config import device_prefs
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
MINIMUM_COL_WIDTH = 12 # : Minimum width of columns in ls output
class FileFormatter(object):
def __init__(self, file):
self.is_dir = file.is_dir
self.is_readonly = file.is_readonly
@ -33,9 +34,12 @@ class FileFormatter(object):
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
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(doc=doc, fget=fget)
@ -49,18 +53,20 @@ class FileFormatter(object):
return name
return property(doc=doc, fget=fget)
@dynamic_property
def name_in_color(self):
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
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
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"):
cname = green + self.name + normal
return cname
return property(doc=doc, fget=fget)
@ -93,7 +99,7 @@ def info(dev):
print "Mime type: ", info[3]
def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
def col_split(l, cols): # split list l into columns
def col_split(l, cols): # split list l into columns
rows = len(l) / cols
if len(l) % cols:
rows += 1
@ -102,9 +108,9 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
m.append(l[i::rows])
return m
def row_widths(table): # Calculate widths for each column in the row-wise table
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) ]
rowwidths = [0 for i in range(tcols)]
for row in table:
c = 0
for item in row:
@ -113,20 +119,23 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
return rowwidths
output = StringIO.StringIO()
if path.endswith("/") and len(path) > 1: path = path[:-1]
if path.endswith("/") and len(path) > 1:
path = path[:-1]
dirs = dev.list(path, recurse)
for dir in dirs:
if recurse: print >>output, dir[0] + ":"
if recurse:
print >>output, dir[0] + ":"
lsoutput, lscoloutput = [], []
files = dir[1]
maxlen = 0
if ll: # Calculate column width for size column
if ll: # Calculate column width for size column
for file in files:
size = len(str(file.size))
if human_readable_size:
file = FileFormatter(file)
size = len(file.human_readable_size)
if size > maxlen: maxlen = size
if size > maxlen:
maxlen = size
for file in files:
file = FileFormatter(file)
name = file.name if ll else file.isdir_name
@ -134,7 +143,8 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
lscoloutput.append(name)
if ll:
size = str(file.size)
if human_readable_size: size = file.human_readable_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 = []
@ -148,8 +158,10 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
if len(item) > colwidth - 1:
works, row_break = False, True
break
if row_break: break
if works: 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)):
@ -176,11 +188,11 @@ def main():
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+
"is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"+
"For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
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
parser.disable_interspersed_args() # Allow unrecognized options
options, args = parser.parse_args()
if len(args) < 1:
@ -227,7 +239,6 @@ def main():
d.specialize_global_preferences(device_prefs)
break
try:
if command == "df":
total = dev.total_space(end_session=False)
@ -235,7 +246,7 @@ def main():
where = ("Memory", "Card A", "Card B")
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]),\
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 == 'eject':
dev.eject()
@ -244,9 +255,11 @@ def main():
for book in dev.books():
print book
print "\nBooks on storage carda:"
for book in dev.books(oncard='carda'): print book
for book in dev.books(oncard='carda'):
print book
print "\nBooks on storage cardb:"
for book in dev.books(oncard='cardb'): print book
for book in dev.books(oncard='cardb'):
print book
elif command == "mkdir":
parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/")
if len(args) != 1:
@ -255,8 +268,11 @@ def main():
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 / or card:/")
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.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.", # noqa
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)
@ -283,7 +299,8 @@ def main():
if args[0].startswith("dev:"):
outfile = args[1]
path = args[0][7:]
if path.endswith("/"): path = path[:-1]
if path.endswith("/"):
path = path[:-1]
if os.path.isdir(outfile):
outfile = os.path.join(outfile, path[path.rfind("/")+1:])
try:
@ -316,18 +333,21 @@ def main():
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:/")
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]
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 / or card:/\n\n"+\
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 / or card:/\n\n"+
"rm will DELETE the file. Be very CAREFUL")
options, args = parser.parse_args(args)
if len(args) != 1:
@ -335,8 +355,8 @@ def main():
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" )
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"+ # noqa
"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()
@ -358,7 +378,8 @@ def main():
dev.eject()
else:
parser.print_help()
if getattr(dev, 'handle', False): dev.close()
if getattr(dev, 'handle', False):
dev.close()
return 1
except DeviceLocked:
print >> sys.stderr, "The device is locked. Use the --unlock option"