cmd.py (9021B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\cmd.py 2 import string 3 __all__ = ['Cmd'] 4 PROMPT = '(Cmd) ' 5 IDENTCHARS = string.ascii_letters + string.digits + '_' 6 7 class Cmd: 8 prompt = PROMPT 9 identchars = IDENTCHARS 10 ruler = '=' 11 lastcmd = '' 12 intro = None 13 doc_leader = '' 14 doc_header = 'Documented commands (type help <topic>):' 15 misc_header = 'Miscellaneous help topics:' 16 undoc_header = 'Undocumented commands:' 17 nohelp = '*** No help on %s' 18 use_rawinput = 1 19 20 def __init__(self, completekey = 'tab', stdin = None, stdout = None): 21 import sys 22 if stdin is not None: 23 self.stdin = stdin 24 else: 25 self.stdin = sys.stdin 26 if stdout is not None: 27 self.stdout = stdout 28 else: 29 self.stdout = sys.stdout 30 self.cmdqueue = [] 31 self.completekey = completekey 32 33 def cmdloop(self, intro = None): 34 self.preloop() 35 if self.use_rawinput and self.completekey: 36 try: 37 import readline 38 self.old_completer = readline.get_completer() 39 readline.set_completer(self.complete) 40 readline.parse_and_bind(self.completekey + ': complete') 41 except ImportError: 42 pass 43 44 try: 45 if intro is not None: 46 self.intro = intro 47 if self.intro: 48 self.stdout.write(str(self.intro) + '\n') 49 stop = None 50 while not stop: 51 if self.cmdqueue: 52 line = self.cmdqueue.pop(0) 53 elif self.use_rawinput: 54 try: 55 line = raw_input(self.prompt) 56 except EOFError: 57 line = 'EOF' 58 59 else: 60 self.stdout.write(self.prompt) 61 self.stdout.flush() 62 line = self.stdin.readline() 63 if not len(line): 64 line = 'EOF' 65 else: 66 line = line.rstrip('\r\n') 67 line = self.precmd(line) 68 stop = self.onecmd(line) 69 stop = self.postcmd(stop, line) 70 71 self.postloop() 72 finally: 73 if self.use_rawinput and self.completekey: 74 try: 75 import readline 76 readline.set_completer(self.old_completer) 77 except ImportError: 78 pass 79 80 def precmd(self, line): 81 return line 82 83 def postcmd(self, stop, line): 84 return stop 85 86 def preloop(self): 87 pass 88 89 def postloop(self): 90 pass 91 92 def parseline(self, line): 93 line = line.strip() 94 if not line: 95 return (None, None, line) 96 if line[0] == '?': 97 line = 'help ' + line[1:] 98 elif line[0] == '!': 99 if hasattr(self, 'do_shell'): 100 line = 'shell ' + line[1:] 101 else: 102 return (None, None, line) 103 i, n = 0, len(line) 104 while i < n and line[i] in self.identchars: 105 i = i + 1 106 107 cmd, arg = line[:i], line[i:].strip() 108 return (cmd, arg, line) 109 110 def onecmd(self, line): 111 cmd, arg, line = self.parseline(line) 112 if not line: 113 return self.emptyline() 114 elif cmd is None: 115 return self.default(line) 116 else: 117 self.lastcmd = line 118 if cmd == '': 119 return self.default(line) 120 try: 121 func = getattr(self, 'do_' + cmd) 122 except AttributeError: 123 return self.default(line) 124 125 return func(arg) 126 127 def emptyline(self): 128 if self.lastcmd: 129 return self.onecmd(self.lastcmd) 130 131 def default(self, line): 132 self.stdout.write('*** Unknown syntax: %s\n' % line) 133 134 def completedefault(self, *ignored): 135 return [] 136 137 def completenames(self, text, *ignored): 138 dotext = 'do_' + text 139 return [ a[3:] for a in self.get_names() if a.startswith(dotext) ] 140 141 def complete(self, text, state): 142 if state == 0: 143 import readline 144 origline = readline.get_line_buffer() 145 line = origline.lstrip() 146 stripped = len(origline) - len(line) 147 begidx = readline.get_begidx() - stripped 148 endidx = readline.get_endidx() - stripped 149 if begidx > 0: 150 cmd, args, foo = self.parseline(line) 151 if cmd == '': 152 compfunc = self.completedefault 153 else: 154 try: 155 compfunc = getattr(self, 'complete_' + cmd) 156 except AttributeError: 157 compfunc = self.completedefault 158 159 else: 160 compfunc = self.completenames 161 self.completion_matches = compfunc(text, line, begidx, endidx) 162 try: 163 return self.completion_matches[state] 164 except IndexError: 165 return 166 167 def get_names(self): 168 return dir(self.__class__) 169 170 def complete_help(self, *args): 171 commands = set(self.completenames(*args)) 172 topics = set((a[5:] for a in self.get_names() if a.startswith('help_' + args[0]))) 173 return list(commands | topics) 174 175 def do_help(self, arg): 176 if arg: 177 try: 178 func = getattr(self, 'help_' + arg) 179 except AttributeError: 180 try: 181 doc = getattr(self, 'do_' + arg).__doc__ 182 if doc: 183 self.stdout.write('%s\n' % str(doc)) 184 return 185 except AttributeError: 186 pass 187 188 self.stdout.write('%s\n' % str(self.nohelp % (arg,))) 189 return 190 191 func() 192 else: 193 names = self.get_names() 194 cmds_doc = [] 195 cmds_undoc = [] 196 help = {} 197 for name in names: 198 if name[:5] == 'help_': 199 help[name[5:]] = 1 200 201 names.sort() 202 prevname = '' 203 for name in names: 204 if name[:3] == 'do_': 205 if name == prevname: 206 continue 207 prevname = name 208 cmd = name[3:] 209 if cmd in help: 210 cmds_doc.append(cmd) 211 del help[cmd] 212 elif getattr(self, name).__doc__: 213 cmds_doc.append(cmd) 214 else: 215 cmds_undoc.append(cmd) 216 217 self.stdout.write('%s\n' % str(self.doc_leader)) 218 self.print_topics(self.doc_header, cmds_doc, 15, 80) 219 self.print_topics(self.misc_header, help.keys(), 15, 80) 220 self.print_topics(self.undoc_header, cmds_undoc, 15, 80) 221 222 def print_topics(self, header, cmds, cmdlen, maxcol): 223 if cmds: 224 self.stdout.write('%s\n' % str(header)) 225 if self.ruler: 226 self.stdout.write('%s\n' % str(self.ruler * len(header))) 227 self.columnize(cmds, maxcol - 1) 228 self.stdout.write('\n') 229 230 def columnize(self, list, displaywidth = 80): 231 if not list: 232 self.stdout.write('<empty>\n') 233 return 234 nonstrings = [ i for i in range(len(list)) if not isinstance(list[i], str) ] 235 if nonstrings: 236 raise TypeError, 'list[i] not a string for i in %s' % ', '.join(map(str, nonstrings)) 237 size = len(list) 238 if size == 1: 239 self.stdout.write('%s\n' % str(list[0])) 240 return 241 for nrows in range(1, len(list)): 242 ncols = (size + nrows - 1) // nrows 243 colwidths = [] 244 totwidth = -2 245 for col in range(ncols): 246 colwidth = 0 247 for row in range(nrows): 248 i = row + nrows * col 249 if i >= size: 250 break 251 x = list[i] 252 colwidth = max(colwidth, len(x)) 253 254 colwidths.append(colwidth) 255 totwidth += colwidth + 2 256 if totwidth > displaywidth: 257 break 258 259 if totwidth <= displaywidth: 260 break 261 else: 262 nrows = len(list) 263 ncols = 1 264 colwidths = [0] 265 266 for row in range(nrows): 267 texts = [] 268 for col in range(ncols): 269 i = row + nrows * col 270 if i >= size: 271 x = '' 272 else: 273 x = list[i] 274 texts.append(x) 275 276 while texts and not texts[-1]: 277 del texts[-1] 278 279 for col in range(len(texts)): 280 texts[col] = texts[col].ljust(colwidths[col]) 281 282 self.stdout.write('%s\n' % str(' '.join(texts)))