def redirect_streams(self, statement): self.kept_state = Statekeeper(self, ('stdout','stdin','stderr',)) self.kept_sys = Statekeeper(sys, ('stdout','stdin','stderr',)) if statement.parsed.pipeTo: self.redirect = subprocess.Popen(statement.parsed.pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) sys.stdout = self.stdout = self.redirect.stdin elif statement.parsed.output: if (not statement.parsed.outputTo) and (not can_clip): raise EnvironmentError('Cannot redirect to paste buffer; install ``xclip`` and re-run to enable') if statement.parsed.outputTo: mode = 'w' if statement.parsed.output == 2 * self.redirector: mode = 'a' sys.stdout = self.stdout = open(os.path.expanduser(statement.parsed.outputTo), mode) else: sys.stdout = self.stdout = tempfile.TemporaryFile(mode="w+") if statement.parsed.output == '>>': self.stdout.write(get_paste_buffer()) if statement.parsed.input: if (not statement.parsed.inputFrom) and (not can_clip): raise EnvironmentError('Cannot redirect from paste buffer; install ``xclip`` and re-run to enable') if statement.parsed.inputFrom: mode = 'r' sys.stdin = self.stdin = open(os.path.expanduser(statement.parsed.inputFrom), mode) else: self.stdin.write(get_paste_buffer())
def help_(self): kept_state = Statekeeper(obj, ('stdout', 'stdin', 'stderr')) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr return obj.onecmd('help') finally: kept_state.restore()
def sumHelp(arg, column): keepstate = Statekeeper(self, ( 'stdout', 'stderr', )) keepsys = Statekeeper(sys, ( 'stdout', 'stderr', )) try: data = None stdout = StringIO.StringIO() # Replace stderr and stdout sys.stdout = self.stdout = stdout self.stderr = sys.stderr = StringIO.StringIO() callHelp(arg, False, stdout=stdout) data = stdout.getvalue() #if not data or len(data) == 0: # data = str(self.nohelp % (arg,)) data = data.split('\n\n', 1)[0].replace("\n", " ") return splitHelp(data, column) finally: # Restore keepstate.restore() keepsys.restore()
def do_(self, args): kept_state = Statekeeper(obj, ('stdout', 'stdin', 'stderr',)) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr if not args: self.printError('*** No command\n') return obj.do_help("", stdout = self.stderr) else: if isinstance(args, ParsedString): args = args.parsed.args return obj.onecmd_plus_hooks(args) finally: kept_state.restore()
def do_py(self, line): ''' py <command>: Executes a Python command. py: Enters interactive Python mode. End with ``Ctrl-D`` (Unix) / ``Ctrl-Z`` (Windows), ``quit()``, '`exit()``. Non-python commands can be issued with ``cmd("your command")``. Run python code from external files with ``run("filename.py")`` ''' self.pystate['self'] = self line = self.rebuildline(line) arg = line.strip() localvars = (self.locals_in_py and self.pystate) or {} from code import InteractiveConsole, InteractiveInterpreter interp = InteractiveConsole(locals=localvars) interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())') if arg.strip(): interp.runcode(arg) else: def quit(): raise EmbeddedConsoleExit def onecmd_plus_hooks(arg): return self.onecmd_plus_hooks(arg + '\n') def run(arg): try: file = open(arg) interp.runcode(file.read()) file.close() except IOError as e: self.perror(e) self.pystate['quit'] = quit self.pystate['exit'] = quit self.pystate['cmd'] = onecmd_plus_hooks self.pystate['run'] = run try: cprt = 'Type "help", "copyright", "credits" or "license" for more information.' keepstate = Statekeeper(sys, ('stdin', 'stdout')) sys.stdout = self.stdout sys.stdin = self.stdin interp.interact(banner="Python %s on %s\n%s\n(%s)\n%s" % (sys.version, sys.platform, cprt, self.__class__.__name__, self.do_py.__doc__)) except EmbeddedConsoleExit: pass keepstate.restore()
def sumHelp(arg, column): keepstate = Statekeeper(self, ('stdout', 'stderr',)) keepsys = Statekeeper(sys, ('stdout', 'stderr',)) try: data = None stdout = StringIO.StringIO() # Replace stderr and stdout sys.stdout = self.stdout = stdout self.stderr = sys.stderr = StringIO.StringIO() callHelp(arg, False, stdout=stdout) data = stdout.getvalue() #if not data or len(data) == 0: # data = str(self.nohelp % (arg,)) data = data.split('\n', 1)[0] return (data[:(column-3)] + '...') if len(data) > column else data finally: # Restore keepstate.restore() keepsys.restore()
class Cmd(Cmd2, object): case_insensitive = False debug = True def colored(self, val, a=None, b=None, attrs=None): if self.stdout == self.initial_stdout: return colored(val, a, b, attrs) return val def __init__(self): Cmd2.__init__(self) self.stderr = sys.stderr self.initial_stdin = sys.stdin self.initial_stderr = sys.stderr self.doc_leader = colored( self.__class__.__name__, 'white', attrs=['bold']) + ' help' self.doc_header = "Commands (type help <topic>):" self.maxcol = 120 # Init functions for a subCmd def subCmd(class_, obj, command): if inspect.isclass(obj): obj = obj() def object_(self): return obj def do_(self, args): kept_state = Statekeeper(obj, ( 'stdout', 'stdin', 'stderr', )) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr if not args: self.printError('*** No command\n') return obj.do_help("", stdout=self.stderr) else: if isinstance(args, ParsedString): args = args.parsed.args return obj.onecmd_plus_hooks(args) finally: kept_state.restore() def complete_(self, text, line, start_index, end_index): if hasattr(obj, 'subCmds'): inCmdList = line.split() for cmd in obj.subCmds: if inCmdList[len(inCmdList) - 1] == cmd: return obj.subCmds[cmd].completenames(text) return obj.completenames(text) else: return obj.completenames(text) def help_(self): kept_state = Statekeeper(obj, ('stdout', 'stdin', 'stderr')) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr return obj.onecmd('help') finally: kept_state.restore() setattr(class_, 'do_' + command, do_) setattr(class_, 'complete_' + command, complete_) setattr(class_, 'help_' + command, help_) setattr(class_, 'object_' + command, object_) return obj if hasattr(self, 'subCmds'): for cmd in self.subCmds: subCmd(self.__class__, self.subCmds[cmd], cmd) def printError(self, errmsg): self.stderr.write(self.colored(str(errmsg), 'red')) def default(self, line): """Called on an input line when the command prefix is not recognized. If this method is not overridden, it prints an error message and returns. """ self.printError('*** Command not found: %s\n' % line) def do_help(self, arg, stdout=None): 'List available commands with "help" or detailed help with "help cmd".' if stdout == None: stdout = self.stdout # Call help for command def callHelp(arg, depth=True, stdout=None, stderr=None): if stdout == None: stdout = self.stdout if stderr == None: stderr = self.stderr if not depth: try: func = getattr(self, 'object_' + arg) doc = func().__doc__ if doc: stdout.write("%s\n" % str(doc)) return except AttributeError: pass try: func = getattr(self, 'help_' + arg) func() except AttributeError: try: doc = getattr(self, 'do_' + arg).__doc__ if doc: stdout.write("%s\n" % str(doc)) return except AttributeError: pass stderr.write( self.colored("%s\n" % str(self.nohelp % (arg, )), 'red')) # Create a help sum def sumHelp(arg, column): keepstate = Statekeeper(self, ( 'stdout', 'stderr', )) keepsys = Statekeeper(sys, ( 'stdout', 'stderr', )) try: data = None stdout = StringIO.StringIO() # Replace stderr and stdout sys.stdout = self.stdout = stdout self.stderr = sys.stderr = StringIO.StringIO() callHelp(arg, False, stdout=stdout) data = stdout.getvalue() #if not data or len(data) == 0: # data = str(self.nohelp % (arg,)) data = data.split('\n\n', 1)[0].replace("\n", " ") return splitHelp(data, column) finally: # Restore keepstate.restore() keepsys.restore() def splitHelp(data, columnSize): rows = [] for n in range(0, len(data), columnSize): rows.append(data[n:n + columnSize]) return rows # Forward help args = re.split('\s+', arg, 1) if len(args) > 1: if hasattr(self, 'object_' + args[0]): funct = getattr(self, 'object_' + args[0]) obj = funct() return obj.onecmd('help ' + args[1]) else: arg = args[0] if arg: return callHelp(arg, stdout=stdout) else: names = self.get_names() cmds_doc = [] cmds_undoc = [] help = {} for name in names: if name[:5] == 'help_': help[name[5:]] = 1 names.sort() # There can be duplicates if routines overridden prevname = '' for name in names: if name[:3] == 'do_': if name == prevname: continue prevname = name cmd = name[3:] if cmd in help: cmds_doc.append(cmd) del help[cmd] elif getattr(self, name).__doc__: cmds_doc.append(cmd) else: cmds_undoc.append(cmd) # Print if self.ruler: stdout.write("%s\n" % str(self.ruler * self.maxcol)) stdout.write("%s\n" % str(self.doc_leader)) if self.ruler: stdout.write("%s\n" % str(self.ruler * self.maxcol)) cmdMaxCol = 30 helpMaxCol = self.maxcol - cmdMaxCol - 3 for cmd in cmds_doc: rows = sumHelp(cmd, helpMaxCol) stdout.write( str('{0:<' + str(cmdMaxCol) + '}| {1:<' + str(helpMaxCol) + '}\n').format(cmd, rows[0])) for n in range(1, len(rows)): stdout.write( str('{0:<' + str(cmdMaxCol) + '}| {1:<' + str(helpMaxCol) + '}\n').format("", rows[n])) def parsed(self, raw, **kwargs): if isinstance(raw, ParsedString): p = raw else: # preparse is an overridable hook; default makes no changes s = self.preparse(raw, **kwargs) s = self.inputParser.transformString(s.lstrip()) s = self.commentGrammars.transformString(s) for (shortcut, expansion) in self.shortcuts: if s.lower().startswith(shortcut): s = s.replace(shortcut, expansion + ' ', 1) break result = self.parser.parseString(s) if isinstance(result.command, pyparsing.ParseResults): result.command = result.command[0] if isinstance(result.multilineCommand, pyparsing.ParseResults): result.multilineCommand = result.multilineCommand[0] result['raw'] = raw result['command'] = result.multilineCommand or result.command result = self.postparse(result) p = ParsedString(result.args) p.parsed = result p.parser = self.parsed for (key, val) in kwargs.items(): p.parsed[key] = val return p def _init_parser(self): #outputParser = (pyparsing.Literal('>>') | (pyparsing.WordStart() + '>') | pyparsing.Regex('[^=]>'))('output') outputParser = (pyparsing.Literal(self.redirector *2) | \ (pyparsing.WordStart() + self.redirector) | \ pyparsing.Regex('[^=]' + self.redirector))('output') inputMark = pyparsing.Literal('<')('input') terminatorParser = pyparsing.Or([ (hasattr(t, 'parseString') and t) or pyparsing.Literal(t) for t in self.terminators ])('terminator') stringEnd = pyparsing.stringEnd ^ '\nEOF' self.multilineCommand = pyparsing.Or([ pyparsing.Keyword(c, caseless=self.case_insensitive) for c in self.multilineCommands ])('multilineCommand') oneLineCommand = (~self.multilineCommand + pyparsing.Word(self.legalChars))('command') pipe = pyparsing.Keyword('|', identChars='|') self.commentGrammars.ignore( pyparsing.quotedString).setParseAction(lambda x: '') doNotParse = self.commentGrammars | self.commentInProgress | pyparsing.quotedString afterElements = \ pyparsing.Optional(inputMark + pyparsing.SkipTo(outputParser ^ pipe ^ stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('inputFrom')) + \ pyparsing.Optional(pipe + pyparsing.SkipTo(outputParser ^ stringEnd, ignore=doNotParse)('pipeTo')) + \ pyparsing.Optional(outputParser + pyparsing.SkipTo(stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('outputTo')) if self.case_insensitive: self.multilineCommand.setParseAction(lambda x: x[0].lower()) oneLineCommand.setParseAction(lambda x: x[0].lower()) if self.blankLinesAllowed: self.blankLineTerminationParser = pyparsing.NoMatch else: self.blankLineTerminator = (pyparsing.lineEnd + pyparsing.lineEnd)('terminator') self.blankLineTerminator.setResultsName('terminator') self.blankLineTerminationParser = ( (self.multilineCommand ^ oneLineCommand) + pyparsing.SkipTo(self.blankLineTerminator, ignore=doNotParse). setParseAction(lambda x: x[0].strip())('args') + self.blankLineTerminator)('statement') self.multilineParser = ( ((self.multilineCommand ^ oneLineCommand) + pyparsing.SkipTo( terminatorParser, ignore=doNotParse).setParseAction(lambda x: x[0].strip()) ('args') + terminatorParser)('statement') + pyparsing.SkipTo( outputParser ^ inputMark ^ pipe ^ stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip()) ('suffix') + afterElements) self.multilineParser.ignore(self.commentInProgress) self.singleLineParser = ((oneLineCommand + pyparsing.SkipTo( terminatorParser ^ stringEnd ^ pipe ^ outputParser ^ inputMark, ignore=doNotParse).setParseAction(lambda x: x[0].strip()) ('args'))('statement') + pyparsing.Optional(terminatorParser) + afterElements) #self.multilineParser = self.multilineParser.setResultsName('multilineParser') #self.singleLineParser = self.singleLineParser.setResultsName('singleLineParser') self.blankLineTerminationParser = self.blankLineTerminationParser.setResultsName( 'statement') self.parser = self.prefixParser + ( stringEnd | self.multilineParser | self.singleLineParser | self.blankLineTerminationParser | self.multilineCommand + pyparsing.SkipTo(stringEnd, ignore=doNotParse)) self.parser.ignore(self.commentGrammars) fileName = pyparsing.Word(self.legalChars + '/\\') inputFrom = fileName('inputFrom') # a not-entirely-satisfactory way of distinguishing < as in "import from" from < # as in "lesser than" self.inputParser = inputMark + pyparsing.Optional(inputFrom) + pyparsing.Optional('>') + \ pyparsing.Optional(fileName) + (pyparsing.stringEnd | '|') self.inputParser.ignore(self.commentInProgress) def redirect_streams(self, statement): self.kept_state = Statekeeper(self, ( 'stdout', 'stdin', 'stderr', )) self.kept_sys = Statekeeper(sys, ( 'stdout', 'stdin', 'stderr', )) if statement.parsed.pipeTo: self.redirect = subprocess.Popen(statement.parsed.pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) sys.stdout = self.stdout = self.redirect.stdin elif statement.parsed.output: if (not statement.parsed.outputTo) and (not can_clip): raise EnvironmentError( 'Cannot redirect to paste buffer; install ``xclip`` and re-run to enable' ) if statement.parsed.outputTo: mode = 'w' if statement.parsed.output == 2 * self.redirector: mode = 'a' sys.stdout = self.stdout = open( os.path.expanduser(statement.parsed.outputTo), mode) else: sys.stdout = self.stdout = tempfile.TemporaryFile(mode="w+") if statement.parsed.output == '>>': self.stdout.write(get_paste_buffer()) if statement.parsed.input: if (not statement.parsed.inputFrom) and (not can_clip): raise EnvironmentError( 'Cannot redirect from paste buffer; install ``xclip`` and re-run to enable' ) if statement.parsed.inputFrom: mode = 'r' sys.stdin = self.stdin = open( os.path.expanduser(statement.parsed.inputFrom), mode) else: self.stdin.write(get_paste_buffer()) def restore_streams(self, statement): if self.kept_state: if statement.parsed.output: if not statement.parsed.outputTo: self.stdout.seek(0) write_to_paste_buffer(self.stdout.read()) self.stdout.close() elif statement.parsed.pipeTo: for result in self.redirect.communicate(): self.kept_state.stdout.write(result or '') self.stdout.close() if statement.parsed.input: self.stdin.close() self.kept_state.restore() self.kept_sys.restore() self.kept_state = None def pseudo_raw_input(self, prompt): """copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout""" if self.use_rawinput: line = raw_input(prompt) else: sys.stderr.write(prompt) sys.stderr.flush() line = self.stdin.readline() if not len(line): raise EOFError() else: if line[-1] == '\n': # this was always true in Cmd line = line[:-1] return line def _cmdloop(self, intro=None): """Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument. """ # An almost perfect copy from Cmd; however, the pseudo_raw_input portion # has been split out so that it can be called separately self.preloop() if self.use_rawinput and self.completekey: try: import readline self.old_completer = readline.get_completer() readline.set_completer(self.complete) readline.parse_and_bind(self.completekey + ": complete") except ImportError: pass try: if intro is not None: self.intro = intro if self.intro: self.stdout.write(str(self.intro) + "\n") stop = None while (stop != 1 or stop != True): try: if self.cmdqueue: line = self.cmdqueue.pop(0) else: line = self.pseudo_raw_input(self.prompt) if (self.echo) and (isinstance(self.stdin, file)): self.stdout.write(line + '\n') stop = self.onecmd_plus_hooks(line) except EOFError: pass self.postloop() finally: if self.use_rawinput and self.completekey: try: import readline readline.set_completer(self.old_completer) except ImportError: pass return stop def run_commands_at_invocation(self, callargs): for initial_command in callargs: code = self.onecmd_plus_hooks(initial_command + '\n') if code: return code def join_args(self, args): ret = "" for arg in args: if " " in arg: ret += "'%s' " % arg else: ret += "%s " % arg return ret.strip() def onecmd_plus_hooks(self, line): # The outermost level of try/finally nesting can be condensed once # Python 2.4 support can be dropped. stop = 0 try: try: statement = None statement = self.complete_statement(line) (stop, statement) = self.postparsing_precmd(statement) if stop: return self.postparsing_postcmd(stop) if statement.parsed.command not in self.excludeFromHistory: self.history.append(statement.parsed.raw) try: self.redirect_streams(statement) timestart = datetime.datetime.now() statement = self.precmd(statement) stop = self.onecmd(statement) stop = self.postcmd(stop, statement) if self.timing: self.pfeedback( 'Elapsed: %s' % str(datetime.datetime.now() - timestart)) except KeyboardInterrupt: print "\nExiting command..." except BaseException as e: self.perror(str(e), statement) finally: self.restore_streams(statement) except pyparsing.ParseException as e: print "File parsing error with line: " + line.rstrip() except EmptyStatement: return 0 except Exception as e: self.perror(str(e), statement) except Exception as e: self.perror(str(e)) finally: return self.postparsing_postcmd(stop)
class Cmd(Cmd2, object): case_insensitive = False debug = True def colored(self, val, a=None, b=None, attrs=None): if self.stdout == self.initial_stdout: return colored(val, a, b , attrs) return val def __init__(self): Cmd2.__init__(self) self.stderr = sys.stderr self.initial_stdin = sys.stdin self.initial_stderr = sys.stderr self.doc_leader = colored(self.__class__.__name__, 'white', attrs=['bold']) + ' help' self.doc_header = "Commands (type help <topic>):" self.maxcol = 120 # Init functions for a subCmd def subCmd(class_, obj, command): if inspect.isclass(obj): obj = obj() def object_(self): return obj def do_(self, args): kept_state = Statekeeper(obj, ('stdout', 'stdin', 'stderr',)) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr if not args: self.printError('*** No command\n') return obj.do_help("", stdout = self.stderr) else: if isinstance(args, ParsedString): args = args.parsed.args return obj.onecmd_plus_hooks(args) finally: kept_state.restore() def complete_(self, text, line, start_index, end_index): if hasattr(obj, 'subCmds'): inCmdList=line.split() for cmd in obj.subCmds: if inCmdList[len(inCmdList)-1]==cmd: return obj.subCmds[cmd].completenames(text) return obj.completenames(text) else: return obj.completenames(text) def help_(self): kept_state = Statekeeper(obj, ('stdout', 'stdin', 'stderr')) try: obj.stdout = self.stdout obj.stdin = self.stdin obj.stderr = self.stderr return obj.onecmd('help') finally: kept_state.restore() setattr(class_, 'do_' + command, do_) setattr(class_, 'complete_' + command, complete_) setattr(class_, 'help_' + command, help_) setattr(class_, 'object_' + command, object_) return obj if hasattr(self, 'subCmds'): for cmd in self.subCmds: subCmd(self.__class__, self.subCmds[cmd], cmd) def printError(self, errmsg): self.stderr.write(self.colored(str(errmsg), 'red')) def default(self, line): """Called on an input line when the command prefix is not recognized. If this method is not overridden, it prints an error message and returns. """ self.printError('*** Command not found: %s\n'%line) def do_help(self, arg, stdout = None): 'List available commands with "help" or detailed help with "help cmd".' if stdout == None: stdout = self.stdout # Call help for command def callHelp(arg, depth = True, stdout = None, stderr = None): if stdout == None: stdout = self.stdout if stderr == None: stderr = self.stderr if not depth: try: func = getattr(self, 'object_' + arg) doc = func().__doc__ if doc: stdout.write("%s\n"%str(doc)) return except AttributeError: pass try: func = getattr(self, 'help_' + arg) func() except AttributeError: try: doc = getattr(self, 'do_' + arg).__doc__ if doc: stdout.write("%s\n"%str(doc)) return except AttributeError: pass stderr.write(self.colored("%s\n"%str(self.nohelp % (arg,)), 'red')) # Create a help sum def sumHelp(arg, column): keepstate = Statekeeper(self, ('stdout', 'stderr',)) keepsys = Statekeeper(sys, ('stdout', 'stderr',)) try: data = None stdout = StringIO.StringIO() # Replace stderr and stdout sys.stdout = self.stdout = stdout self.stderr = sys.stderr = StringIO.StringIO() callHelp(arg, False, stdout=stdout) data = stdout.getvalue() #if not data or len(data) == 0: # data = str(self.nohelp % (arg,)) data = data.split('\n', 1)[0] return (data[:(column-3)] + '...') if len(data) > column else data finally: # Restore keepstate.restore() keepsys.restore() # Forward help args = re.split('\s+', arg, 1) if len(args) > 1: if hasattr(self, 'object_' + args[0]): funct = getattr(self, 'object_' + args[0]) obj = funct() return obj.onecmd('help ' + args[1]) else: arg = args[0] if arg: return callHelp(arg, stdout=stdout) else: names = self.get_names() cmds_doc = [] cmds_undoc = [] help = {} for name in names: if name[:5] == 'help_': help[name[5:]]=1 names.sort() # There can be duplicates if routines overridden prevname = '' for name in names: if name[:3] == 'do_': if name == prevname: continue prevname = name cmd=name[3:] if cmd in help: cmds_doc.append(cmd) del help[cmd] elif getattr(self, name).__doc__: cmds_doc.append(cmd) else: cmds_undoc.append(cmd) # Print if self.ruler: stdout.write("%s\n"%str(self.ruler * self.maxcol)) stdout.write("%s\n"%str(self.doc_leader)) if self.ruler: stdout.write("%s\n"%str(self.ruler * self.maxcol)) cmdMaxCol = 30 helpMaxCol = self.maxcol - cmdMaxCol - 3 for cmd in cmds_doc: stdout.write(str('{0:<'+str(cmdMaxCol)+'}| {1:<' + str(helpMaxCol) + '}\n').format(cmd, sumHelp(cmd, helpMaxCol))) def parsed(self, raw, **kwargs): if isinstance(raw, ParsedString): p = raw else: # preparse is an overridable hook; default makes no changes s = self.preparse(raw, **kwargs) s = self.inputParser.transformString(s.lstrip()) s = self.commentGrammars.transformString(s) for (shortcut, expansion) in self.shortcuts: if s.lower().startswith(shortcut): s = s.replace(shortcut, expansion + ' ', 1) break result = self.parser.parseString(s) if isinstance(result.command, pyparsing.ParseResults): result.command = result.command[0] if isinstance(result.multilineCommand, pyparsing.ParseResults): result.multilineCommand = result.multilineCommand[0] result['raw'] = raw result['command'] = result.multilineCommand or result.command result = self.postparse(result) p = ParsedString(result.args) p.parsed = result p.parser = self.parsed for (key, val) in kwargs.items(): p.parsed[key] = val return p def _init_parser(self): #outputParser = (pyparsing.Literal('>>') | (pyparsing.WordStart() + '>') | pyparsing.Regex('[^=]>'))('output') outputParser = (pyparsing.Literal(self.redirector *2) | \ (pyparsing.WordStart() + self.redirector) | \ pyparsing.Regex('[^=]' + self.redirector))('output') inputMark = pyparsing.Literal('<')('input') terminatorParser = pyparsing.Or([(hasattr(t, 'parseString') and t) or pyparsing.Literal(t) for t in self.terminators])('terminator') stringEnd = pyparsing.stringEnd ^ '\nEOF' self.multilineCommand = pyparsing.Or([pyparsing.Keyword(c, caseless=self.case_insensitive) for c in self.multilineCommands])('multilineCommand') oneLineCommand = (~self.multilineCommand + pyparsing.Word(self.legalChars))('command') pipe = pyparsing.Keyword('|', identChars='|') self.commentGrammars.ignore(pyparsing.quotedString).setParseAction(lambda x: '') doNotParse = self.commentGrammars | self.commentInProgress | pyparsing.quotedString afterElements = \ pyparsing.Optional(inputMark + pyparsing.SkipTo(outputParser ^ pipe ^ stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('inputFrom')) + \ pyparsing.Optional(pipe + pyparsing.SkipTo(outputParser ^ stringEnd, ignore=doNotParse)('pipeTo')) + \ pyparsing.Optional(outputParser + pyparsing.SkipTo(stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('outputTo')) if self.case_insensitive: self.multilineCommand.setParseAction(lambda x: x[0].lower()) oneLineCommand.setParseAction(lambda x: x[0].lower()) if self.blankLinesAllowed: self.blankLineTerminationParser = pyparsing.NoMatch else: self.blankLineTerminator = (pyparsing.lineEnd + pyparsing.lineEnd)('terminator') self.blankLineTerminator.setResultsName('terminator') self.blankLineTerminationParser = ((self.multilineCommand ^ oneLineCommand) + pyparsing.SkipTo(self.blankLineTerminator, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('args') + self.blankLineTerminator)('statement') self.multilineParser = (((self.multilineCommand ^ oneLineCommand) + pyparsing.SkipTo(terminatorParser, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('args') + terminatorParser)('statement') + pyparsing.SkipTo(outputParser ^ inputMark ^ pipe ^ stringEnd, ignore=doNotParse).setParseAction(lambda x: x[0].strip())('suffix') + afterElements) self.multilineParser.ignore(self.commentInProgress) self.singleLineParser = ((oneLineCommand + pyparsing.SkipTo(terminatorParser ^ stringEnd ^ pipe ^ outputParser ^ inputMark, ignore=doNotParse).setParseAction(lambda x:x[0].strip())('args'))('statement') + pyparsing.Optional(terminatorParser) + afterElements) #self.multilineParser = self.multilineParser.setResultsName('multilineParser') #self.singleLineParser = self.singleLineParser.setResultsName('singleLineParser') self.blankLineTerminationParser = self.blankLineTerminationParser.setResultsName('statement') self.parser = self.prefixParser + ( stringEnd | self.multilineParser | self.singleLineParser | self.blankLineTerminationParser | self.multilineCommand + pyparsing.SkipTo(stringEnd, ignore=doNotParse) ) self.parser.ignore(self.commentGrammars) fileName = pyparsing.Word(self.legalChars + '/\\') inputFrom = fileName('inputFrom') # a not-entirely-satisfactory way of distinguishing < as in "import from" from < # as in "lesser than" self.inputParser = inputMark + pyparsing.Optional(inputFrom) + pyparsing.Optional('>') + \ pyparsing.Optional(fileName) + (pyparsing.stringEnd | '|') self.inputParser.ignore(self.commentInProgress) def redirect_streams(self, statement): self.kept_state = Statekeeper(self, ('stdout','stdin','stderr',)) self.kept_sys = Statekeeper(sys, ('stdout','stdin','stderr',)) if statement.parsed.pipeTo: self.redirect = subprocess.Popen(statement.parsed.pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) sys.stdout = self.stdout = self.redirect.stdin elif statement.parsed.output: if (not statement.parsed.outputTo) and (not can_clip): raise EnvironmentError('Cannot redirect to paste buffer; install ``xclip`` and re-run to enable') if statement.parsed.outputTo: mode = 'w' if statement.parsed.output == 2 * self.redirector: mode = 'a' sys.stdout = self.stdout = open(os.path.expanduser(statement.parsed.outputTo), mode) else: sys.stdout = self.stdout = tempfile.TemporaryFile(mode="w+") if statement.parsed.output == '>>': self.stdout.write(get_paste_buffer()) if statement.parsed.input: if (not statement.parsed.inputFrom) and (not can_clip): raise EnvironmentError('Cannot redirect from paste buffer; install ``xclip`` and re-run to enable') if statement.parsed.inputFrom: mode = 'r' sys.stdin = self.stdin = open(os.path.expanduser(statement.parsed.inputFrom), mode) else: self.stdin.write(get_paste_buffer()) def restore_streams(self, statement): if self.kept_state: if statement.parsed.output: if not statement.parsed.outputTo: self.stdout.seek(0) write_to_paste_buffer(self.stdout.read()) self.stdout.close() elif statement.parsed.pipeTo: for result in self.redirect.communicate(): self.kept_state.stdout.write(result or '') self.stdout.close() if statement.parsed.input: self.stdin.close() self.kept_state.restore() self.kept_sys.restore() self.kept_state = None def pseudo_raw_input(self, prompt): """copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout""" if self.use_rawinput: line = raw_input(prompt) else: sys.stderr.write(prompt) sys.stderr.flush() line = self.stdin.readline() if not len(line): raise EOFError() else: if line[-1] == '\n': # this was always true in Cmd line = line[:-1] return line def _cmdloop(self, intro=None): """Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument. """ # An almost perfect copy from Cmd; however, the pseudo_raw_input portion # has been split out so that it can be called separately self.preloop() if self.use_rawinput and self.completekey: try: import readline self.old_completer = readline.get_completer() readline.set_completer(self.complete) readline.parse_and_bind(self.completekey+": complete") except ImportError: pass try: if intro is not None: self.intro = intro if self.intro: self.stdout.write(str(self.intro)+"\n") stop = None while (stop!=1 or stop!=True): try: if self.cmdqueue: line = self.cmdqueue.pop(0) else: line = self.pseudo_raw_input(self.prompt) if (self.echo) and (isinstance(self.stdin, file)): self.stdout.write(line + '\n') stop = self.onecmd_plus_hooks(line) except EOFError: pass self.postloop() finally: if self.use_rawinput and self.completekey: try: import readline readline.set_completer(self.old_completer) except ImportError: pass return stop def run_commands_at_invocation(self, callargs): for initial_command in callargs: code= self.onecmd_plus_hooks(initial_command + '\n') if code: return code def onecmd_plus_hooks(self, line): # The outermost level of try/finally nesting can be condensed once # Python 2.4 support can be dropped. stop = 0 try: try: statement = None statement = self.complete_statement(line) (stop, statement) = self.postparsing_precmd(statement) if stop: return self.postparsing_postcmd(stop) if statement.parsed.command not in self.excludeFromHistory: self.history.append(statement.parsed.raw) try: self.redirect_streams(statement) timestart = datetime.datetime.now() statement = self.precmd(statement) stop = self.onecmd(statement) stop = self.postcmd(stop, statement) if self.timing: self.pfeedback('Elapsed: %s' % str(datetime.datetime.now() - timestart)) except KeyboardInterrupt: print "\nExiting command..." except BaseException as e: self.perror(str(e), statement) finally: self.restore_streams(statement) except pyparsing.ParseException as e: print "File parsing error with line: "+line.rstrip() except EmptyStatement: return 0 except Exception as e: self.perror(str(e), statement) except Exception as e: self.perror(str(e)) finally: return self.postparsing_postcmd(stop)