changeset 36:f472921d6189

fixing split arg, AND cleaning up accidental merge mess
author catherine@localhost
date Mon, 19 May 2008 13:56:00 -0400
parents d72627da96de (diff) e72eb9137a87 (current diff)
children a974e2f44cbe
files cmd2.py
diffstat 3 files changed, 102 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgtags	Mon May 19 13:56:00 2008 -0400
@@ -0,0 +1,1 @@
+dd64c0e3dbe0b923081543946f0e1a64b57e5f61 v0.3.1
--- a/cmd2.py	Fri May 16 10:40:15 2008 -0400
+++ b/cmd2.py	Mon May 19 13:56:00 2008 -0400
@@ -18,7 +18,7 @@
 As of 0.3.0, options should be specified as `optparse` options.  See README.txt.
 flagReader.py options are still supported for backward compatibility
 """
-import cmd, re, os, sys, optparse
+import cmd, re, os, sys, optparse, subprocess, tempfile
 from optparse import make_option
 
 class OptionParser(optparse.OptionParser):
@@ -46,19 +46,83 @@
         def newFunc(instance, arg):
             try:
                 opts, arg = optionParser.parse_args(arg.split())
-                arg = ' '.join(arg)
             except (optparse.OptionValueError, optparse.BadOptionError,
                     optparse.OptionError, optparse.AmbiguousOptionError,
                     optparse.OptionConflictError), e:
                 print e
                 optionParser.print_help()
                 return 
-            result = func(instance, arg, opts)                            
+            result = func(instance, ' '.join(arg), opts)                            
             return result
         newFunc.__doc__ = '%s\n%s' % (func.__doc__, optionParser.format_help())
         return newFunc
     return option_setup
 
+class PasteBufferError(EnvironmentError):
+    if sys.platform[:3] == 'win':
+        errmsg = """Redirecting to or from paste buffer requires pywin32
+to be installed on operating system.
+Download from http://sourceforge.net/projects/pywin32/"""
+    else:
+        errmsg = """Redirecting to or from paste buffer requires xclip 
+to be installed on operating system.
+On Debian/Ubuntu, 'sudo apt-get install xclip' will install it."""        
+    def __init__(self):
+        Exception.__init__(self, self.errmsg)
+
+'''check here if functions exist; otherwise, stub out'''
+pastebufferr = """Redirecting to or from paste buffer requires %s
+to be installed on operating system.
+%s"""
+if subprocess.mswindows:
+    try:
+        import win32clipboard
+        def getPasteBuffer():
+            win32clipboard.OpenClipboard(0)
+            try:
+                result = win32clipboard.GetClipboardData()
+            except TypeError:
+                result = ''  #non-text
+            win32clipboard.CloseClipboard()
+            return result            
+        def writeToPasteBuffer(txt):
+            win32clipboard.OpenClipboard(0)
+            win32clipboard.EmptyClipboard()
+            win32clipboard.SetClipboardText(txt)
+            win32clipboard.CloseClipboard()        
+    except ImportError:
+        def getPasteBuffer():
+            raise OSError, pastebufferr % ('pywin32', 'Download from http://sourceforge.net/projects/pywin32/')
+        setPasteBuffer = getPasteBuffer
+else:
+    can_clip = False
+    try:
+        subprocess.check_call('xclip -o -sel clip', shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+        can_clip = True
+    except AttributeError:  # check_call not defined, Python < 2.5
+        teststring = 'Testing for presence of xclip.'
+        #import pdb; pdb.set_trace()
+        xclipproc = subprocess.Popen('xclip -sel clip', shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+        xclipproc.stdin.write(teststring)
+        xclipproc.stdin.close()
+        xclipproc = subprocess.Popen('xclip -o -sel clip', shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)        
+        if xclipproc.stdout.read() == teststring:
+            can_clip = True
+    except (subprocess.CalledProcessError, OSError):
+        pass
+    if can_clip:    
+        def getPasteBuffer():
+            xclipproc = subprocess.Popen('xclip -o -sel clip', shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+            return xclipproc.stdout.read()
+        def writeToPasteBuffer(txt):
+            xclipproc = subprocess.Popen('xclip -sel clip', shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+            xclipproc.stdin.write(txt)
+            xclipproc.stdin.close()
+    else:
+        def getPasteBuffer():
+            raise OSError, pastebufferr % ('xclip', 'On Debian/Ubuntu, install with "sudo apt-get install xclip"')
+        setPasteBuffer = getPasteBuffer
+                
 class Cmd(cmd.Cmd):
     caseInsensitive = True
     multilineCommands = []
@@ -72,12 +136,13 @@
         if sys.platform[:3] == 'win':
             editor = 'notepad'
         else:
-            for editor in ['gedit', 'kate', 'vim', 'emacs', 'nano', 'pico', 'vi']:
-                if not os.system('which %s' % (editor)):
+            for editor in ['gedit', 'kate', 'vim', 'emacs', 'nano', 'pico']:
+                if os.system('which %s' % (editor)):
                     break
             
     settable = ['prompt', 'continuationPrompt', 'defaultFileName', 'editor', 'caseInsensitive']
     terminators = ';\n'
+    _TO_PASTE_BUFFER = 1
     def do_cmdenvironment(self, args):
         self.stdout.write("""
         Commands are %(casesensitive)scase-sensitive.
@@ -115,8 +180,11 @@
         if mustBeTerminated and (parts[-2].strip()[-1] not in self.terminators):
             return statement, None
         (newStatement, redirect) = (symbol.join(parts[:-1]), parts[-1].strip())
-        if not self.legalFileName.search(redirect):
-            return statement, None
+        if redirect:
+            if not self.legalFileName.search(redirect):
+                return statement, None
+        else:
+            redirect = self._TO_PASTE_BUFFER
         return newStatement, redirect
     
     def extractCommand(self, statement):
@@ -131,7 +199,7 @@
     def parseRedirectors(self, statement):
         mustBeTerminated = self.extractCommand(statement)[0] in self.multilineCommands
         newStatement, redirect = self.parseRedirector(statement, '>>', mustBeTerminated)
-        if redirect:
+        if redirect:            
             return newStatement, redirect, 'a'        
         newStatement, redirect = self.parseRedirector(statement, '>', mustBeTerminated)
         if redirect:
@@ -140,7 +208,7 @@
         if redirect:
             return newStatement, redirect, 'r'
         return statement, '', ''
-        
+           
     def onecmd(self, line):
         """Interpret the argument as though it had been typed in response
         to the prompt.
@@ -156,15 +224,25 @@
         if command in self.multilineCommands:
             statement = self.finishStatement(statement)
         statekeeper = None
+        stop = 0
         statement, redirect, mode = self.parseRedirectors(statement)
-        if redirect:
+        if redirect == self._TO_PASTE_BUFFER:
+            try:
+                clipcontents = getPasteBuffer()
+                if mode in ('w', 'a'):
+                    statekeeper = Statekeeper(self, ('stdout',))
+                    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',))
-                try:
-                    self.stdout = open(redirect, mode)            
-                except IOError, e:
-                    print str(e)
-                    return 0
+                self.stdout = open(redirect, mode)            
             else:
                 statement = '%s %s' % (statement, self.fileimport(statement=statement, source=redirect))
         stop = cmd.Cmd.onecmd(self, statement)
@@ -173,6 +251,9 @@
                 self.history.append(statement)
         finally:
             if statekeeper:
+                if redirect == self._TO_PASTE_BUFFER:
+                    self.stdout.seek(0)
+                    writeToPasteBuffer(self.stdout.read())
                 self.stdout.close()
                 statekeeper.restore()
             return stop        
@@ -524,4 +605,4 @@
             setattr(self, attrib, getattr(self.obj, attrib))
     def restore(self):
         for attrib in self.attribs:
-            setattr(self.obj, attrib, getattr(self, attrib))        
\ No newline at end of file
+            setattr(self.obj, attrib, getattr(self, attrib))        
--- a/setup.py	Fri May 16 10:40:15 2008 -0400
+++ b/setup.py	Mon May 19 13:56:00 2008 -0400
@@ -3,7 +3,7 @@
 
 setup(
     name="cmd2",
-    version="0.3.0",
+    version="0.3.1",
     py_modules = ['cmd2','flagReader','bootstrap'],
     
     # metadata for upload to PyPI
@@ -26,7 +26,9 @@
     * Special-character shortcut commands (beyond cmd's "@" and "!")
     * Settable environment parameters
     * Parsing commands with flags
-    * Redirection to file with >, >>; input from file with <
+    * > (filename), >> (filename) redirect output to file
+    * < (filename) gets input from file
+    * bare >, >>, < redirect to/from paste buffer     
 
 Useable without modification anywhere cmd is used; simply import cmd2.Cmd in place of cmd.Cmd.