Mercurial > python-cmd2
changeset 66:f373aaa2390c
ready for first trial
author | catherine@Elli.myhome.westell.com |
---|---|
date | Mon, 23 Jun 2008 15:15:11 -0400 |
parents | 4e028e9ec4c2 |
children | a78dff1e7bca |
files | cmd2.py |
diffstat | 1 files changed, 43 insertions(+), 102 deletions(-) [+] |
line wrap: on
line diff
--- a/cmd2.py Mon Jun 23 12:51:37 2008 -0400 +++ b/cmd2.py Mon Jun 23 15:15:11 2008 -0400 @@ -209,37 +209,9 @@ self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result)) commmand_terminator_finder = punctuationParser(terminators) - outputTo_finder = punctuationParser(['>']) - inputFrom_finder = punctuationParser(['<']) - pipe_finder = punctuationParser(['|']) - - notAPipe = pyparsing.SkipTo('|') - notAPipe.ignore(pyparsing.sglQuotedString) - notAPipe.ignore(pyparsing.dblQuotedString) - pipeFinder = notAPipe + '|' + pyparsing.SkipTo(pyparsing.StringEnd()) - def parsePipe(self, statement, mustBeTerminated): - try: - statement, pipe, destination = self.pipeFinder.parseString(statement) - redirect = subprocess.Popen(destination, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) - return statement, redirect - except pyparsing.ParseException: - return statement, None - - legalFileName = re.compile(r'''^[^"'\s]+$''') - def parseRedirector(self, statement, symbol, mustBeTerminated=False): - # pipeFinder.scanString(statement) - parts = statement.split(symbol) - if (len(parts) < 2): - return statement, None - if mustBeTerminated and (not self.statementEndPattern.search(parts[-2])): - return statement, None - (newStatement, redirect) = (symbol.join(parts[:-1]), parts[-1].strip()) - if redirect: - if not self.legalFileName.search(redirect): - return statement, None - else: - redirect = self._TO_PASTE_BUFFER - return newStatement, redirect + output_destination_finder = punctuationParser(['>>', '>']) + input_source_finder = punctuationParser(['<']) + pipe_destination_finder = punctuationParser(['|']) def extractCommand(self, statement): try: @@ -250,22 +222,16 @@ command = command.lower() return command, args - def parseRedirectors(self, statement): - mustBeTerminated = self.extractCommand(statement)[0] in self.multilineCommands - newStatement, redirect = self.parsePipe(statement, mustBeTerminated) - if redirect: - return newStatement, redirect, 'pipe' - newStatement, redirect = self.parseRedirector(statement, '>>', mustBeTerminated) - if redirect: - return newStatement, redirect, 'a' - newStatement, redirect = self.parseRedirector(statement, '>', mustBeTerminated) - if redirect: - return newStatement, redirect, 'w' - newStatement, redirect = self.parseRedirector(statement, '<', mustBeTerminated) - if redirect: - return newStatement, redirect, 'r' - return statement, '', '' - + def completedStatement(self, firstline): + statement = firstline + while not self.commmand_terminator_finder(statement): + inp = self.pseudo_raw_input(self.continuationPrompt) + statement = '%s\n%s' % (statement, inp) + return statement + # assembling a list of lines and joining them at the end would be faster, + # but statementHasEnded needs a string arg; anyway, we're getting + # user input and users are slow. + def onecmd(self, line, assumeComplete=False): """Interpret the argument as though it had been typed in response to the prompt. @@ -279,79 +245,54 @@ command, args = self.extractCommand(line) statement = originalStatement = ' '.join([command, args]) if (not assumeComplete) and (command in self.multilineCommands): - statement = self.finishStatement(statement) + statement = self.completedStatement(statement) statekeeper = None stop = 0 - statement, redirect, mode = self.parseRedirectors(statement) - if isinstance(redirect, subprocess.Popen): - statekeeper = Statekeeper(self, ('stdout',)) + + inputFrom = self.input_source_finder(statement) + if inputFrom: + statement, source = inputFrom[0], inputFrom[-1] + if source: + statement = '%s %s' % (statement, self.fileimport(statement=statement, source=source)) + else: + statement = getPasteBuffer() + + pipeTo = self.pipe_destination_finder(statement) + if pipeTo: + statement, pipeTo = pipeTo[0], [-1] + statekeeper = Statekeeper(self, ('stdout',)) + pipeTo = subprocess.Popen(PipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) self.stdout = redirect.stdin - elif redirect == self._TO_PASTE_BUFFER: - try: - clipcontents = getPasteBuffer() - if mode in ('w', 'a'): - statekeeper = Statekeeper(self, ('stdout',)) + else: # can't pipe output AND send it to a file + outputTo = self.outputTo_finder(statement) + if outputTo: + statement, destination = outputTo[0], outputTo[-1] + statekeeper = Statekeeper(self, ('stdout',)) + mode = ((output[1] == '>>') and 'a') or 'w' + if destination: + self.stdout = open(destination, mode) + else: self.stdout = tempfile.TemporaryFile() if mode == 'a': - self.stdout.write(clipcontents) - else: - statement = '%s %s' % (statement, clipcontents) - except OSError, e: - print e - return 0 - elif redirect: - if mode in ('w','a'): - statekeeper = Statekeeper(self, ('stdout',)) - self.stdout = open(redirect, mode) - else: - statement = '%s %s' % (statement, self.fileimport(statement=statement, source=redirect)) - if isinstance(redirect, subprocess.Popen): - stop = self.onecmd(statement) - else: - stop = cmd.Cmd.onecmd(self, statement) + self.stdout.write(getPasteBuffer()) + + stop = cmd.Cmd.onecmd(self, statement) try: if command not in self.excludeFromHistory: self.history.append(originalStatement) finally: if statekeeper: - if redirect == self._TO_PASTE_BUFFER: + if outputTo and not destination: self.stdout.seek(0) writeToPasteBuffer(self.stdout.read()) - elif isinstance(redirect, subprocess.Popen): + elif pipeTo: # uh-oh. HUH? for result in redirect.communicate(): statekeeper.stdout.write(result or '') self.stdout.close() statekeeper.restore() return stop - - #TODO: This should be replaced by pyparsing. What if terminators come - #inside a string? What about statements that end in different ways? - # + searching for EOF string is sloppy! - statementEndPattern = re.compile(r'[%s]\s*$' % terminators) - lineEndFinder = pyparsing.Optional(pyparsing.CharsNotIn(';')) + ';' - def statementHasEnded(self, lines): - #import pdb; pdb.set_trace() - try: - self.lineEndFinder.parseString(lines) - return True - except pyparsing.ParseException: - return False - ''' - return bool(self.statementEndPattern.search(lines)) \ - or lines[-3:] == 'EOF' \ - or self.parseRedirectors(lines)[1]''' - - def finishStatement(self, firstline): - statement = firstline - while not self.statementHasEnded(statement): - inp = self.pseudo_raw_input(self.continuationPrompt) - statement = '%s\n%s' % (statement, inp) - return statement - # assembling a list of lines and joining them at the end would be faster, - # but statementHasEnded needs a string arg; anyway, we're getting - # user input and users are slow. - + def pseudo_raw_input(self, prompt): """copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout"""