1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""A generic class to build line-oriented command interpreters. 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehInterpreters constructed with this class obey the following conventions: 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh1. End of file on input is processed as the command 'EOF'. 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh2. A command is parsed out of each line by collecting the prefix composed 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh of characters in the identchars member. 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh is passed a single argument consisting of the remainder of the line. 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh4. Typing an empty line repeats the last command. (Actually, it calls the 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh method `emptyline', which may be overridden in a subclass.) 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh5. There is a predefined `help' method. Given an argument `topic', it 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh calls the command `help_topic'. With no arguments, it lists all topics 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with defined help_ functions, broken into up to three topics; documented 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh commands, miscellaneous help topics, and undocumented commands. 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh6. The command '?' is a synonym for `help'. The command '!' is a synonym 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for `shell', if a do_shell method exists. 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh7. If completion is enabled, completing commands will be done automatically, 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh and completing of commands args is done by calling complete_foo() with 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh arguments text, line, begidx, endidx. text is string we are matching 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh against, all returned matches must begin with it. line is the current 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input line (lstripped), begidx and endidx are the beginning and end 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh indexes of the text being matched, which could be used to provide 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh different completion depending upon which position the argument is in. 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThe `default' method may be overridden to intercept commands for which there 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehis no do_ method. 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThe `completedefault' method may be overridden to intercept completions for 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehcommands that have no complete_ method. 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThe data member `self.ruler' sets the character used to draw separator lines 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehin the help messages. If empty, no ruler line is drawn. It defaults to "=". 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehIf the value of `self.intro' is nonempty when the cmdloop method is called, 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehit is printed out on interpreter startup. This value may be overridden 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehvia an optional argument to the cmdloop() method. 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThe data members `self.doc_header', `self.misc_header', and 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh`self.undoc_header' set the headers used for the help function's 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehlistings of documented functions, miscellaneous topics, and undocumented 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfunctions respectively. 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThese interpreters use raw_input; thus, if the readline module is loaded, 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehthey automatically support Emacs-like command history and editing features. 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport string 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh__all__ = ["Cmd"] 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehPROMPT = '(Cmd) ' 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehIDENTCHARS = string.ascii_letters + string.digits + '_' 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass Cmd: 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """A simple framework for writing line-oriented command interpreters. 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh These are often useful for test harnesses, administrative tools, and 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh prototypes that will later be wrapped in a more sophisticated interface. 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh A Cmd instance or subclass instance is a line-oriented interpreter 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh framework. There is no good reason to instantiate Cmd itself; rather, 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh it's useful as a superclass of an interpreter class you define yourself 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh in order to inherit Cmd's methods and encapsulate action methods. 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh prompt = PROMPT 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh identchars = IDENTCHARS 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ruler = '=' 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lastcmd = '' 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh intro = None 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh doc_leader = "" 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh doc_header = "Documented commands (type help <topic>):" 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh misc_header = "Miscellaneous help topics:" 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh undoc_header = "Undocumented commands:" 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nohelp = "*** No help on %s" 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh use_rawinput = 1 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, completekey='tab', stdin=None, stdout=None): 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Instantiate a line-oriented interpreter framework. 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh The optional argument 'completekey' is the readline name of a 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh completion key; it defaults to the Tab key. If completekey is 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh not None and the readline module is available, command completion 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh is done automatically. The optional arguments stdin and stdout 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh specify alternate input and output file objects; if not specified, 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.stdin and sys.stdout are used. 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import sys 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if stdin is not None: 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdin = stdin 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdin = sys.stdin 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if stdout is not None: 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout = stdout 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout = sys.stdout 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.cmdqueue = [] 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.completekey = completekey 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def cmdloop(self, intro=None): 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Repeatedly issue a prompt, accept input, parse an initial prefix 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh off the received input, and dispatch to action methods, passing them 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh the remainder of the line as argument. 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.preloop() 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.use_rawinput and self.completekey: 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import readline 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.old_completer = readline.get_completer() 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh readline.set_completer(self.complete) 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh readline.parse_and_bind(self.completekey+": complete") 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if intro is not None: 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.intro = intro 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.intro: 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write(str(self.intro)+"\n") 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh stop = None 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while not stop: 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.cmdqueue: 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = self.cmdqueue.pop(0) 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.use_rawinput: 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = raw_input(self.prompt) 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except EOFError: 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = 'EOF' 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write(self.prompt) 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.flush() 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = self.stdin.readline() 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not len(line): 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = 'EOF' 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = line.rstrip('\r\n') 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = self.precmd(line) 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh stop = self.onecmd(line) 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh stop = self.postcmd(stop, line) 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.postloop() 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.use_rawinput and self.completekey: 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import readline 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh readline.set_completer(self.old_completer) 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def precmd(self, line): 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Hook method executed just before the command line is 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh interpreted, but after the input prompt is generated and issued. 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return line 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def postcmd(self, stop, line): 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Hook method executed just after a command dispatch is finished.""" 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return stop 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def preloop(self): 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Hook method executed once when the cmdloop() method is called.""" 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def postloop(self): 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Hook method executed once when the cmdloop() method is about to 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return. 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def parseline(self, line): 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Parse the line into a command name and a string containing 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh the arguments. Returns a tuple containing (command, args, line). 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'command' and 'args' may be None if the line couldn't be parsed. 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = line.strip() 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not line: 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None, None, line 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif line[0] == '?': 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = 'help ' + line[1:] 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif line[0] == '!': 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(self, 'do_shell'): 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = 'shell ' + line[1:] 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None, None, line 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i, n = 0, len(line) 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while i < n and line[i] in self.identchars: i = i+1 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd, arg = line[:i], line[i:].strip() 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return cmd, arg, line 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def onecmd(self, line): 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Interpret the argument as though it had been typed in response 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh to the prompt. 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh This may be overridden, but should not normally need to be; 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh see the precmd() and postcmd() methods for useful execution hooks. 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh The return value is a flag indicating whether interpretation of 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh commands by the interpreter should stop. 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd, arg, line = self.parseline(line) 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not line: 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.emptyline() 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cmd is None: 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.default(line) 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.lastcmd = line 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if line == 'EOF' : 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.lastcmd = '' 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cmd == '': 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.default(line) 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh func = getattr(self, 'do_' + cmd) 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.default(line) 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return func(arg) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def emptyline(self): 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Called when an empty line is entered in response to the prompt. 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh If this method is not overridden, it repeats the last nonempty 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command entered. 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.lastcmd: 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.onecmd(self.lastcmd) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def default(self, line): 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Called on an input line when the command prefix is not recognized. 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh If this method is not overridden, it prints an error message and 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh returns. 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write('*** Unknown syntax: %s\n'%line) 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def completedefault(self, *ignored): 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Method called to complete an input line when no command-specific 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh complete_*() method is available. 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh By default, it returns an empty list. 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return [] 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def completenames(self, text, *ignored): 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dotext = 'do_'+text 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return [a[3:] for a in self.get_names() if a.startswith(dotext)] 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def complete(self, text, state): 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Return the next possible completion for 'text'. 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh If a command has not been entered, then complete against command list. 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Otherwise try to call complete_<command> to get list of completions. 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if state == 0: 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import readline 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh origline = readline.get_line_buffer() 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh line = origline.lstrip() 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh stripped = len(origline) - len(line) 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh begidx = readline.get_begidx() - stripped 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh endidx = readline.get_endidx() - stripped 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if begidx>0: 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd, args, foo = self.parseline(line) 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cmd == '': 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh compfunc = self.completedefault 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh compfunc = getattr(self, 'complete_' + cmd) 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh compfunc = self.completedefault 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh compfunc = self.completenames 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.completion_matches = compfunc(text, line, begidx, endidx) 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.completion_matches[state] 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IndexError: 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_names(self): 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This method used to pull in base class attributes 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # at a time dir() didn't do it yet. 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return dir(self.__class__) 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def complete_help(self, *args): 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh commands = set(self.completenames(*args)) 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh topics = set(a[5:] for a in self.get_names() 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if a.startswith('help_' + args[0])) 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return list(commands | topics) 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def do_help(self, arg): 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'List available commands with "help" or detailed help with "help cmd".' 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if arg: 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXX check arg syntax 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh func = getattr(self, 'help_' + arg) 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh doc=getattr(self, 'do_' + arg).__doc__ 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if doc: 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(doc)) 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(self.nohelp % (arg,))) 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh func() 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh names = self.get_names() 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmds_doc = [] 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmds_undoc = [] 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help = {} 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name in names: 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name[:5] == 'help_': 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help[name[5:]]=1 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh names.sort() 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # There can be duplicates if routines overridden 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh prevname = '' 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name in names: 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name[:3] == 'do_': 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name == prevname: 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh prevname = name 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd=name[3:] 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cmd in help: 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmds_doc.append(cmd) 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh del help[cmd] 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif getattr(self, name).__doc__: 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmds_doc.append(cmd) 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmds_undoc.append(cmd) 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(self.doc_leader)) 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.print_topics(self.doc_header, cmds_doc, 15,80) 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.print_topics(self.misc_header, help.keys(),15,80) 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.print_topics(self.undoc_header, cmds_undoc, 15,80) 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def print_topics(self, header, cmds, cmdlen, maxcol): 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cmds: 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(header)) 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.ruler: 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(self.ruler * len(header))) 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.columnize(cmds, maxcol-1) 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("\n") 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def columnize(self, list, displaywidth=80): 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Display a list of strings as a compact set of columns. 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Each column is only as wide as necessary. 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Columns are separated by two spaces (one was not legible enough). 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not list: 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("<empty>\n") 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nonstrings = [i for i in range(len(list)) 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not isinstance(list[i], str)] 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if nonstrings: 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise TypeError, ("list[i] not a string for i in %s" % 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ", ".join(map(str, nonstrings))) 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh size = len(list) 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if size == 1: 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write('%s\n'%str(list[0])) 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try every row count from 1 upwards 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for nrows in range(1, len(list)): 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncols = (size+nrows-1) // nrows 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh colwidths = [] 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh totwidth = -2 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for col in range(ncols): 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh colwidth = 0 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for row in range(nrows): 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = row + nrows*col 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if i >= size: 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x = list[i] 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh colwidth = max(colwidth, len(x)) 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh colwidths.append(colwidth) 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh totwidth += colwidth + 2 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if totwidth > displaywidth: 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if totwidth <= displaywidth: 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nrows = len(list) 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncols = 1 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh colwidths = [0] 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for row in range(nrows): 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh texts = [] 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for col in range(ncols): 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = row + nrows*col 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if i >= size: 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x = "" 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x = list[i] 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh texts.append(x) 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while texts and not texts[-1]: 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh del texts[-1] 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for col in range(len(texts)): 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh texts[col] = texts[col].ljust(colwidths[col]) 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdout.write("%s\n"%str(" ".join(texts))) 405