comparison cmd2.py @ 290:cd12e4e0fa17

show -l working
author catherine@bothari
date Fri, 06 Nov 2009 21:41:55 -0500
parents 327ace491fa9
children dfdbd93a2fae
comparison
equal deleted inserted replaced
289:327ace491fa9 290:cd12e4e0fa17
295 self.showtraceback() 295 self.showtraceback()
296 else: 296 else:
297 if softspace(sys.stdout, 0): 297 if softspace(sys.stdout, 0):
298 print 298 print
299 299
300 def ljust(x, width, fillchar=' '):
301 'analogous to str.ljust, but works for lists'
302 if hasattr(x, 'ljust'):
303 return x.ljust(width, fillchar)
304 else:
305 if len(x) < width:
306 x = (x + [fillchar] * width)[:width]
307 return x
308
300 class Cmd(cmd.Cmd): 309 class Cmd(cmd.Cmd):
301 echo = False 310 echo = False
302 case_insensitive = True # Commands recognized regardless of case 311 case_insensitive = True # Commands recognized regardless of case
303 continuation_prompt = '> ' 312 continuation_prompt = '> '
304 timing = False # Prints elapsed time for each command 313 timing = False # Prints elapsed time for each command
313 current_script_dir = None 322 current_script_dir = None
314 reserved_words = [] 323 reserved_words = []
315 feedback_to_output = False # Do include nonessentials in >, | output 324 feedback_to_output = False # Do include nonessentials in >, | output
316 quiet = False # Do not suppress nonessential output 325 quiet = False # Do not suppress nonessential output
317 debug = False 326 debug = False
318 settable = ['prompt', 'continuation_prompt', 'debug', 'default_file_name', 'editor', 327 settable = '''
319 'case_insensitive', 'feedback_to_output', 'quiet', 'echo', 'timing', 328 prompt
320 'abbrev'] 329 continuation_prompt
321 settable.sort() 330 debug
331 default_file_name for `save`, `load`, etc.
332 editor
333 case_insensitive upper- and lower-case both OK
334 feedback_to_output include nonessentials in `|`, `>` results
335 quiet
336 echo Echo command issued into output
337 timing Report execution times
338 abbrev Accept abbreviated commands
339 '''.splitlines()
322 340
323 def poutput(self, msg): 341 def poutput(self, msg):
324 if msg: 342 if msg:
325 self.stdout.write(msg) 343 self.stdout.write(msg)
326 if msg[-1] != '\n': 344 if msg[-1] != '\n':
376 self.history = History() 394 self.history = History()
377 self._init_parser() 395 self._init_parser()
378 self.pystate = {} 396 self.pystate = {}
379 self.shortcuts = sorted(self.shortcuts.items(), reverse=True) 397 self.shortcuts = sorted(self.shortcuts.items(), reverse=True)
380 self.keywords = self.reserved_words + [fname[3:] for fname in dir(self) 398 self.keywords = self.reserved_words + [fname[3:] for fname in dir(self)
381 if fname.startswith('do_')] 399 if fname.startswith('do_')]
400 self.settable = (l.strip() for l in self.settable if l.strip())
401 self.settable = dict(ljust(l.split(None,1), 2, '') for l in self.settable)
402
382 def do_shortcuts(self, args): 403 def do_shortcuts(self, args):
383 """Lists single-key shortcuts available.""" 404 """Lists single-key shortcuts available."""
384 result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.shortcuts)) 405 result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.shortcuts))
385 self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result)) 406 self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result))
386 407
799 return stop 820 return stop
800 821
801 def do_EOF(self, arg): 822 def do_EOF(self, arg):
802 return True 823 return True
803 do_eof = do_EOF 824 do_eof = do_EOF
804 825
805 def show_param(self, param):
806 any_shown = False
807 param = param.strip().lower()
808 for p in self.settable:
809 if p.startswith(param):
810 self.stdout.write('%s: %s\n' % (p, str(getattr(self, p))))
811 any_shown = True
812 if not any_shown:
813 self.perror("Parameter '%s' not supported (type 'show' for list of parameters)." % param)
814
815 def do_quit(self, arg): 826 def do_quit(self, arg):
816 return self._STOP_AND_EXIT 827 return self._STOP_AND_EXIT
817 do_exit = do_quit 828 do_exit = do_quit
818 do_q = do_quit 829 do_q = do_quit
819 830
820 def do_show(self, arg): 831 @options([make_option('-l', '--long', action="store_true",
832 help="describe function of parameter")])
833 def do_show(self, arg, opts):
821 '''Shows value of a parameter.''' 834 '''Shows value of a parameter.'''
822 if arg.strip(): 835 param = arg.strip().lower()
823 self.show_param(arg) 836 result = {}
824 else: 837 maxlen = 0
825 for param in self.settable: 838 for p in self.settable:
826 self.show_param(param) 839 if (not param) or p.startswith(param):
840 result[p] = '%s: %s' % (p, str(getattr(self, p)))
841 maxlen = max(maxlen, len(result[p]))
842 if result:
843 for p in sorted(result):
844 if opts.long:
845 self.poutput('%s # %s' % (result[p].ljust(maxlen), self.settable[p]))
846 else:
847 self.poutput(result[p])
848 else:
849 self.perror("Parameter '%s' not supported (type 'show' for list of parameters)." % param)
827 850
828 def do_set(self, arg): 851 def do_set(self, arg):
829 '''Sets a cmd2 parameter. Accepts abbreviated parameter names so long as there is no ambiguity. 852 '''
830 Call without arguments for a list of settable parameters with their values.''' 853 Sets a cmd2 parameter. Accepts abbreviated parameter names so long
854 as there is no ambiguity. Call without arguments for a list of
855 settable parameters with their values.'''
831 try: 856 try:
832 paramName, val = arg.split(None, 1) 857 paramName, val = arg.split(None, 1)
833 paramName = paramName.strip().lower() 858 paramName = paramName.strip().lower()
834 hits = [paramName in p for p in self.settable] 859 if paramName not in self.settable:
835 if hits.count(True) == 1: 860 hits = [p for p in self.settable if p.startswith(p)]
836 paramName = self.settable[hits.index(True)] 861 if len(hits) == 1:
837 currentVal = getattr(self, paramName) 862 paramName = hits[0]
838 if (val[0] == val[-1]) and val[0] in ("'", '"'): 863 else:
839 val = val[1:-1] 864 return self.do_show(paramName)
840 else: 865 currentVal = getattr(self, paramName)
841 val = cast(currentVal, val) 866 if (val[0] == val[-1]) and val[0] in ("'", '"'):
842 setattr(self, paramName, val) 867 val = val[1:-1]
843 self.stdout.write('%s - was: %s\nnow: %s\n' % (paramName, currentVal, val)) 868 else:
844 if currentVal != val: 869 val = cast(currentVal, val)
845 try: 870 setattr(self, paramName, val)
846 onchange_hook = getattr(self, '_onchange_%s' % paramName) 871 self.stdout.write('%s - was: %s\nnow: %s\n' % (paramName, currentVal, val))
847 onchange_hook(old=currentVal, new=val) 872 if currentVal != val:
848 except AttributeError: 873 try:
849 pass 874 onchange_hook = getattr(self, '_onchange_%s' % paramName)
850 else: 875 onchange_hook(old=currentVal, new=val)
851 self.do_show(paramName) 876 except AttributeError:
877 pass
852 except (ValueError, AttributeError, NotSettableError), e: 878 except (ValueError, AttributeError, NotSettableError), e:
853 self.do_show(arg) 879 self.do_show(arg)
854 880
855 def do_pause(self, arg): 881 def do_pause(self, arg):
856 'Displays the specified text then waits for the user to press RETURN.' 882 'Displays the specified text then waits for the user to press RETURN.'
1242 if self.CmdApp: 1268 if self.CmdApp:
1243 self.outputTrap.tearDown() 1269 self.outputTrap.tearDown()
1244 1270
1245 if __name__ == '__main__': 1271 if __name__ == '__main__':
1246 doctest.testmod(optionflags = doctest.NORMALIZE_WHITESPACE) 1272 doctest.testmod(optionflags = doctest.NORMALIZE_WHITESPACE)
1247
1248 1273
1249 ''' 1274 '''
1250 To make your application transcript-testable, add text like this to your .py file 1275 To make your application transcript-testable, add text like this to your .py file
1251 (replacing CmdLineApp with your own application class's name). Then, a cut-and-pasted 1276 (replacing CmdLineApp with your own application class's name). Then, a cut-and-pasted
1252 version of a successful session with your application, saved as a text file, can serve 1277 version of a successful session with your application, saved as a text file, can serve