1
2 """
3 Provides a command-line interface to the SONY Reader PRS-500.
4
5 For usage information run the script.
6 """
7
8 import StringIO, sys, time, os
9 from optparse import OptionParser
10
11 from libprs500 import VERSION
12 from libprs500.communicate import PRS500Device
13 from libprs500.terminfo import TerminalController
14 from libprs500.errors import ArgumentError
15
16
17 MINIMUM_COL_WIDTH = 12
18
40
41 @apply
53 return property(**locals())
54
55 @apply
66 return property(**locals())
67
68 @apply
73 return property(**locals())
74
75 @apply
80 return property(**locals())
81
88
89 -def ls(dev, path, term, recurse=False, color=False, human_readable_size=False, ll=False, cols=0):
90 def col_split(l, cols):
91 rows = len(l) / cols
92 if len(l) % cols:
93 rows += 1
94 m = []
95 for i in range(rows):
96 m.append(l[i::rows])
97 return m
98
99 def row_widths(table):
100 tcols = len(table[0])
101 rowwidths = [ 0 for i in range(tcols) ]
102 for row in table:
103 c = 0
104 for item in row:
105 rowwidths[c] = len(item) if len(item) > rowwidths[c] else rowwidths[c]
106 c += 1
107 return rowwidths
108
109 output = StringIO.StringIO()
110 if path.endswith("/"): path = path[:-1]
111 dirs = dev.list(path, recurse)
112 for dir in dirs:
113 if recurse: print >>output, dir[0] + ":"
114 lsoutput, lscoloutput = [], []
115 files = dir[1]
116 maxlen = 0
117 if ll:
118 for file in files:
119 size = len(str(file.size))
120 if human_readable_size:
121 file = FileFormatter(file, term)
122 size = len(file.human_readable_size)
123 if size > maxlen: maxlen = size
124 for file in files:
125 file = FileFormatter(file, term)
126 name = file.name
127 lsoutput.append(name)
128 if color: name = file.name_in_color
129 lscoloutput.append(name)
130 if ll:
131 size = str(file.size)
132 if human_readable_size: size = file.human_readable_size
133 print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name
134 if not ll and len(lsoutput) > 0:
135 trytable = []
136 for colwidth in range(MINIMUM_COL_WIDTH, cols):
137 trycols = int(cols/colwidth)
138 trytable = col_split(lsoutput, trycols)
139 works = True
140 for row in trytable:
141 row_break = False
142 for item in row:
143 if len(item) > colwidth - 1:
144 works, row_break = False, True
145 break
146 if row_break: break
147 if works: break
148 rowwidths = row_widths(trytable)
149 trytablecol = col_split(lscoloutput, len(trytable[0]))
150 for r in range(len(trytable)):
151 for c in range(len(trytable[r])):
152 padding = rowwidths[c] - len(trytable[r][c])
153 print >>output, trytablecol[r][c], "".ljust(padding),
154 print >>output
155 print >>output
156 listing = output.getvalue().rstrip()+ "\n"
157 output.close()
158 return listing
159
161 term = TerminalController()
162 cols = term.COLS
163
164 parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, ls, cp, cat or rm\n\n"+
165 "For help on a particular command: %prog command", version="libprs500 version: " + VERSION)
166 parser.add_option("--log-packets", help="print out packet stream to stdout", dest="log_packets", action="store_true", default=False)
167 parser.remove_option("-h")
168 parser.disable_interspersed_args()
169 options, args = parser.parse_args()
170
171 if len(args) < 1:
172 parser.print_help()
173 sys.exit(1)
174 command = args[0]
175 args = args[1:]
176 dev = PRS500Device(log_packets=options.log_packets)
177 if command == "ls":
178 parser = OptionParser(usage="usage: %prog ls [options] path\n\npath must begin with /,a:/ or b:/")
179 parser.add_option("--color", help="show ls output in color", dest="color", action="store_true", default=False)
180 parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time unless other times are selected)", dest="ll", action="store_true", default=False)
181 parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False)
182 parser.remove_option("-h")
183 parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False)
184 options, args = parser.parse_args(args)
185 if len(args) < 1:
186 parser.print_help()
187 sys.exit(1)
188 dev.open()
189 try:
190 print ls(dev, args[0], term, color=options.color, recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),
191 except ArgumentError, e:
192 print >> sys.stderr, e
193 sys.exit(1)
194 finally:
195 dev.close()
196 elif command == "info":
197 dev.open()
198 try:
199 info(dev)
200 finally: dev.close()
201 elif command == "cp":
202 parser = OptionParser(usage="usage: %prog cp [options] source destination\n\nsource is a path on the device and must begin with /,a:/ or b:/"+
203 "\n\ndestination is a path on your computer and can point to either a file or a directory")
204 options, args = parser.parse_args(args)
205 if len(args) < 2:
206 parser.print_help()
207 sys.exit(1)
208 if args[0].endswith("/"): path = args[0][:-1]
209 else: path = args[0]
210 outfile = args[1]
211 if os.path.isdir(outfile):
212 outfile = os.path.join(outfile, path[path.rfind("/")+1:])
213 outfile = open(outfile, "w")
214 dev.open()
215 try:
216 dev.get_file(path, outfile)
217 except ArgumentError, e:
218 print >>sys.stderr, e
219 finally:
220 dev.close()
221 outfile.close()
222 elif command == "cat":
223 outfile = sys.stdout
224 parser = OptionParser(usage="usage: %prog cat path\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
225 options, args = parser.parse_args(args)
226 if len(args) < 1:
227 parser.print_help()
228 sys.exit(1)
229 if args[0].endswith("/"): path = args[0][:-1]
230 else: path = args[0]
231 outfile = sys.stdout
232 dev.open()
233 try:
234 dev.get_file(path, outfile)
235 except ArgumentError, e:
236 print >>sys.stderr, e
237 finally:
238 dev.close()
239 else:
240 parser.print_help()
241 sys.exit(1)
242
243 if __name__ == "__main__":
244 main()
245