diff cmd2.py @ 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
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"""