1 """Shell is an interactive text control in which a user types in 
   2 commands to be sent to the interpreter.  This particular shell is 
   3 based on wxPython's wxStyledTextCtrl. 
   5 Sponsored by Orbtech - Your source for Python programming expertise.""" 
   7 __author__ 
= "Patrick K. O'Brien <pobrien@orbtech.com>" 
   9 __revision__ 
= "$Revision$"[11:-2] 
  19 from buffer import Buffer
 
  23 from pseudo 
import PseudoFileIn
 
  24 from pseudo 
import PseudoFileOut
 
  25 from pseudo 
import PseudoFileErr
 
  26 from version 
import VERSION
 
  28 sys
.ps3 
= '<-- '  # Input prompt. 
  30 NAVKEYS 
= (wx
.WXK_END
, wx
.WXK_LEFT
, wx
.WXK_RIGHT
, 
  31            wx
.WXK_UP
, wx
.WXK_DOWN
, wx
.WXK_PRIOR
, wx
.WXK_NEXT
) 
  34 class ShellFrame(frame
.Frame
, frame
.ShellFrameMixin
): 
  35     """Frame containing the shell component.""" 
  38     revision 
= __revision__
 
  40     def __init__(self
, parent
=None, id=-1, title
='PyShell', 
  41                  pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
, 
  42                  style
=wx
.DEFAULT_FRAME_STYLE
, locals=None, 
  44                  config
=None, dataDir
=None, 
  46         """Create ShellFrame instance.""" 
  47         frame
.Frame
.__init
__(self
, parent
, id, title
, pos
, size
, style
) 
  48         frame
.ShellFrameMixin
.__init
__(self
, config
, dataDir
) 
  50         if size 
== wx
.DefaultSize
: 
  51             self
.SetSize((750, 525)) 
  53         intro 
= 'PyShell %s - The Flakiest Python Shell' % VERSION
 
  54         self
.SetStatusText(intro
.replace('\n', ', ')) 
  55         self
.shell 
= Shell(parent
=self
, id=-1, introText
=intro
, 
  56                            locals=locals, InterpClass
=InterpClass
, 
  57                            startupScript
=self
.startupScript
, 
  58                            execStartupScript
=self
.execStartupScript
, 
  61         # Override the shell so that status messages go to the status bar. 
  62         self
.shell
.setStatusText 
= self
.SetStatusText
 
  68     def OnClose(self
, event
): 
  69         """Event handler for closing.""" 
  70         # This isn't working the way I want, but I'll leave it for now. 
  71         if self
.shell
.waiting
: 
  79     def OnAbout(self
, event
): 
  80         """Display an About window.""" 
  81         title 
= 'About PyShell' 
  82         text 
= 'PyShell %s\n\n' % VERSION 
+ \
 
  83                'Yet another Python shell, only flakier.\n\n' + \
 
  84                'Half-baked by Patrick K. O\'Brien,\n' + \
 
  85                'the other half is still in the oven.\n\n' + \
 
  86                'Shell Revision: %s\n' % self
.shell
.revision 
+ \
 
  87                'Interpreter Revision: %s\n\n' % self
.shell
.interp
.revision 
+ \
 
  88                'Platform: %s\n' % sys
.platform 
+ \
 
  89                'Python Version: %s\n' % sys
.version
.split()[0] + \
 
  90                'wxPython Version: %s\n' % wx
.VERSION_STRING 
+ \
 
  91                ('\t(%s)\n' % ", ".join(wx
.PlatformInfo
[1:]))  
  92         dialog 
= wx
.MessageDialog(self
, text
, title
, 
  93                                   wx
.OK | wx
.ICON_INFORMATION
) 
  98     def OnHelp(self
, event
): 
  99         """Show a help dialog.""" 
 100         frame
.ShellFrameMixin
.OnHelp(self
, event
) 
 103     def LoadSettings(self
): 
 104         if self
.config 
is not None: 
 105             frame
.ShellFrameMixin
.LoadSettings(self
) 
 106             frame
.Frame
.LoadSettings(self
, self
.config
) 
 107             self
.shell
.LoadSettings(self
.config
) 
 109     def SaveSettings(self
, force
=False): 
 110         if self
.config 
is not None: 
 111             frame
.ShellFrameMixin
.SaveSettings(self
) 
 112             if self
.autoSaveSettings 
or force
: 
 113                 frame
.Frame
.SaveSettings(self
, self
.config
) 
 114                 self
.shell
.SaveSettings(self
.config
) 
 116     def DoSaveSettings(self
): 
 117         if self
.config 
is not None: 
 118             self
.SaveSettings(force
=True) 
 126 Home              Go to the beginning of the command or line. 
 127 Shift+Home        Select to the beginning of the command or line. 
 128 Shift+End         Select to the end of the line. 
 129 End               Go to the end of the line. 
 130 Ctrl+C            Copy selected text, removing prompts. 
 131 Ctrl+Shift+C      Copy selected text, retaining prompts. 
 132 Alt+C             Copy to the clipboard, including prefixed prompts. 
 133 Ctrl+X            Cut selected text. 
 134 Ctrl+V            Paste from clipboard. 
 135 Ctrl+Shift+V      Paste and run multiple commands from clipboard. 
 136 Ctrl+Up Arrow     Retrieve Previous History item. 
 137 Alt+P             Retrieve Previous History item. 
 138 Ctrl+Down Arrow   Retrieve Next History item. 
 139 Alt+N             Retrieve Next History item. 
 140 Shift+Up Arrow    Insert Previous History item. 
 141 Shift+Down Arrow  Insert Next History item. 
 142 F8                Command-completion of History item. 
 143                   (Type a few characters of a previous command and press F8.) 
 144 Ctrl+Enter        Insert new line into multiline command. 
 145 Ctrl+]            Increase font size. 
 146 Ctrl+[            Decrease font size. 
 147 Ctrl+=            Default font size. 
 148 Ctrl-Space        Show Auto Completion. 
 149 Ctrl-Alt-Space    Show Call Tip. 
 150 Shift+Enter       Complete Text from History. 
 153 Ctrl+H            "hide" lines containing selection / "unhide" 
 154 F12               on/off "free-edit" mode 
 158     """Simplified interface to all shell-related functionality. 
 160     This is a semi-transparent facade, in that all attributes of other 
 161     are accessible, even though only some are visible to the user.""" 
 163     name 
= 'Shell Interface' 
 164     revision 
= __revision__
 
 166     def __init__(self
, other
): 
 167         """Create a ShellFacade instance.""" 
 170         d
['helpText'] = HELP_TEXT
 
 171         d
['this'] = other
.this
 
 174         """Display some useful information about how to use the shell.""" 
 175         self
.write(self
.helpText
) 
 177     def __getattr__(self
, name
): 
 178         if hasattr(self
.other
, name
): 
 179             return getattr(self
.other
, name
) 
 181             raise AttributeError, name
 
 183     def __setattr__(self
, name
, value
): 
 184         if self
.__dict
__.has_key(name
): 
 185             self
.__dict
__[name
] = value
 
 186         elif hasattr(self
.other
, name
): 
 187             setattr(self
.other
, name
, value
) 
 189             raise AttributeError, name
 
 191     def _getAttributeNames(self
): 
 192         """Return list of magic attributes to extend introspection.""" 
 198             'autoCompleteAutoHide', 
 199             'autoCompleteCaseInsensitive', 
 200             'autoCompleteIncludeDouble', 
 201             'autoCompleteIncludeMagic', 
 202             'autoCompleteIncludeSingle', 
 221 class Shell(editwindow
.EditWindow
): 
 222     """Shell based on StyledTextCtrl.""" 
 225     revision 
= __revision__
 
 227     def __init__(self
, parent
, id=-1, pos
=wx
.DefaultPosition
, 
 228                  size
=wx
.DefaultSize
, style
=wx
.CLIP_CHILDREN
, 
 229                  introText
='', locals=None, InterpClass
=None, 
 230                  startupScript
=None, execStartupScript
=True, 
 232         """Create Shell instance.""" 
 233         editwindow
.EditWindow
.__init
__(self
, parent
, id, pos
, size
, style
) 
 237             locals = __main__
.__dict
__ 
 239         # Grab these so they can be restored by self.redirect* methods. 
 240         self
.stdin 
= sys
.stdin
 
 241         self
.stdout 
= sys
.stdout
 
 242         self
.stderr 
= sys
.stderr
 
 244         # Import a default interpreter class if one isn't provided. 
 245         if InterpClass 
== None: 
 246             from interpreter 
import Interpreter
 
 248             Interpreter 
= InterpClass
 
 250         # Create a replacement for stdin. 
 251         self
.reader 
= PseudoFileIn(self
.readline
, self
.readlines
) 
 252         self
.reader
.input = '' 
 253         self
.reader
.isreading 
= False 
 255         # Set up the interpreter. 
 256         self
.interp 
= Interpreter(locals=locals, 
 257                                   rawin
=self
.raw_input, 
 259                                   stdout
=PseudoFileOut(self
.writeOut
), 
 260                                   stderr
=PseudoFileErr(self
.writeErr
), 
 264         self
.buffer = Buffer() 
 266         # Find out for which keycodes the interpreter will autocomplete. 
 267         self
.autoCompleteKeys 
= self
.interp
.getAutoCompleteKeys() 
 269         # Keep track of the last non-continuation prompt positions. 
 270         self
.promptPosStart 
= 0 
 271         self
.promptPosEnd 
= 0 
 273         # Keep track of multi-line commands. 
 276         # Create the command history.  Commands are added into the 
 277         # front of the list (ie. at index 0) as they are entered. 
 278         # self.historyIndex is the current position in the history; it 
 279         # gets incremented as you retrieve the previous command, 
 280         # decremented as you retrieve the next, and reset when you hit 
 281         # Enter.  self.historyIndex == -1 means you're on the current 
 282         # command, not in the history. 
 284         self
.historyIndex 
= -1 
 286         #seb add mode for "free edit" 
 288         self
.MarkerDefine(0,stc
.STC_MARK_ROUNDRECT
)  # marker for hidden 
 291         # Assign handlers for keyboard events. 
 292         self
.Bind(wx
.EVT_CHAR
, self
.OnChar
) 
 293         self
.Bind(wx
.EVT_KEY_DOWN
, self
.OnKeyDown
) 
 295         # Assign handler for idle time. 
 297         self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
) 
 299         # Display the introductory banner information. 
 300         self
.showIntro(introText
) 
 302         # Assign some pseudo keywords to the interpreter's namespace. 
 303         self
.setBuiltinKeywords() 
 305         # Add 'shell' to the interpreter's local namespace. 
 308         ## NOTE:  See note at bottom of this file... 
 309         ## #seb: File drag and drop 
 310         ## self.SetDropTarget( FileDropTarget(self) ) 
 312         # Do this last so the user has complete control over their 
 313         # environment.  They can override anything they want. 
 314         if execStartupScript
: 
 315             if startupScript 
is None: 
 316                 startupScript 
= os
.environ
.get('PYTHONSTARTUP') 
 317             self
.execStartupScript(startupScript
) 
 321         wx
.CallAfter(self
.ScrollToLine
, 0) 
 324     def clearHistory(self
): 
 326         self
.historyIndex 
= -1 
 327         dispatcher
.send(signal
="Shell.clearHistory") 
 334         """Set focus to the shell.""" 
 337     def OnIdle(self
, event
): 
 338         """Free the CPU to do other things.""" 
 343     def showIntro(self
, text
=''): 
 344         """Display introductory text in the shell.""" 
 346             if not text
.endswith(os
.linesep
): 
 350             self
.write(self
.interp
.introText
) 
 351         except AttributeError: 
 354     def setBuiltinKeywords(self
): 
 355         """Create pseudo keywords as part of builtins. 
 357         This sets "close", "exit" and "quit" to a helpful string. 
 360         __builtin__
.close 
= __builtin__
.exit 
= __builtin__
.quit 
= \
 
 361             'Click on the close button to leave the application.' 
 365         """Quit the application.""" 
 366         # XXX Good enough for now but later we want to send a close event. 
 367         # In the close event handler we can make sure they want to 
 368         # quit.  Other applications, like PythonCard, may choose to 
 369         # hide rather than quit so we should just post the event and 
 370         # let the surrounding app decide what it wants to do. 
 371         self
.write('Click on the close button to leave the application.') 
 374     def setLocalShell(self
): 
 375         """Add 'shell' to locals as reference to ShellFacade instance.""" 
 376         self
.interp
.locals['shell'] = ShellFacade(other
=self
) 
 379     def execStartupScript(self
, startupScript
): 
 380         """Execute the user's PYTHONSTARTUP script if they have one.""" 
 381         if startupScript 
and os
.path
.isfile(startupScript
): 
 382             text 
= 'Startup script executed: ' + startupScript
 
 383             self
.push('print %r; execfile(%r)' % (text
, startupScript
)) 
 384             self
.interp
.startupScript 
= startupScript
 
 390         """Display information about Py.""" 
 394 Py Shell Revision: %s 
 395 Py Interpreter Revision: %s 
 398 wxPython PlatformInfo: %s 
 400         (__author__
, VERSION
, self
.revision
, self
.interp
.revision
, 
 401          sys
.version
.split()[0], wx
.VERSION_STRING
, str(wx
.PlatformInfo
), 
 403         self
.write(text
.strip()) 
 406     def OnChar(self
, event
): 
 407         """Keypress event handler. 
 409         Only receives an event if OnKeyDown calls event.Skip() for the 
 410         corresponding event.""" 
 416         # Prevent modification of previously submitted 
 417         # commands/responses. 
 418         if not self
.CanEdit(): 
 420         key 
= event
.GetKeyCode() 
 421         currpos 
= self
.GetCurrentPos() 
 422         stoppos 
= self
.promptPosEnd
 
 423         # Return (Enter) needs to be ignored in this handler. 
 424         if key 
in [wx
.WXK_RETURN
, wx
.WXK_NUMPAD_ENTER
]: 
 426         elif key 
in self
.autoCompleteKeys
: 
 427             # Usually the dot (period) key activates auto completion. 
 428             # Get the command between the prompt and the cursor.  Add 
 429             # the autocomplete character to the end of the command. 
 430             if self
.AutoCompActive(): 
 431                 self
.AutoCompCancel() 
 432             command 
= self
.GetTextRange(stoppos
, currpos
) + chr(key
) 
 434             if self
.autoComplete
: 
 435                 self
.autoCompleteShow(command
) 
 436         elif key 
== ord('('): 
 437             # The left paren activates a call tip and cancels an 
 438             # active auto completion. 
 439             if self
.AutoCompActive(): 
 440                 self
.AutoCompCancel() 
 441             # Get the command between the prompt and the cursor.  Add 
 442             # the '(' to the end of the command. 
 443             self
.ReplaceSelection('') 
 444             command 
= self
.GetTextRange(stoppos
, currpos
) + '(' 
 446             self
.autoCallTipShow(command
, self
.GetCurrentPos() == self
.GetTextLength()) 
 448             # Allow the normal event handling to take place. 
 452     def OnKeyDown(self
, event
): 
 453         """Key down event handler.""" 
 455         key 
= event
.GetKeyCode() 
 456         # If the auto-complete window is up let it do its thing. 
 457         if self
.AutoCompActive(): 
 461         # Prevent modification of previously submitted 
 462         # commands/responses. 
 463         controlDown 
= event
.ControlDown() 
 464         altDown 
= event
.AltDown() 
 465         shiftDown 
= event
.ShiftDown() 
 466         currpos 
= self
.GetCurrentPos() 
 467         endpos 
= self
.GetTextLength() 
 468         selecting 
= self
.GetSelectionStart() != self
.GetSelectionEnd() 
 470         if controlDown 
and shiftDown 
and key 
in (ord('F'), ord('f')):  
 471             li 
= self
.GetCurrentLine() 
 472             m 
= self
.MarkerGet(li
) 
 474                 startP 
= self
.PositionFromLine(li
) 
 475                 self
.MarkerDelete(li
, 0) 
 476                 maxli 
= self
.GetLineCount() 
 477                 li 
+= 1 # li stayed visible as header-line 
 479                 while li
<maxli 
and self
.GetLineVisible(li
) == 0: 
 481                 endP 
= self
.GetLineEndPosition(li
-1) 
 482                 self
.ShowLines(li0
, li
-1) 
 483                 self
.SetSelection( startP
, endP 
) # select reappearing text to allow "hide again" 
 485             startP
,endP 
= self
.GetSelection() 
 487             startL
,endL 
= self
.LineFromPosition(startP
), self
.LineFromPosition(endP
) 
 489             if endL 
== self
.LineFromPosition(self
.promptPosEnd
): # never hide last prompt 
 492             m 
= self
.MarkerGet(startL
) 
 493             self
.MarkerAdd(startL
, 0) 
 494             self
.HideLines(startL
+1,endL
) 
 495             self
.SetCurrentPos( startP 
) # to ensure caret stays visible ! 
 497         if key 
== wx
.WXK_F12
: #seb 
 499                 # self.promptPosStart not used anyway - or ?  
 500                 self
.promptPosEnd 
= self
.PositionFromLine( self
.GetLineCount()-1 ) + len(str(sys
.ps1
)) 
 501                 self
.GotoLine(self
.GetLineCount()) 
 502                 self
.GotoPos(self
.promptPosEnd
) 
 503                 self
.prompt()  #make sure we have a prompt 
 504                 self
.SetCaretForeground("black") 
 505                 self
.SetCaretWidth(1)    #default 
 506                 self
.SetCaretPeriod(500) #default 
 508                 self
.SetCaretForeground("red") 
 509                 self
.SetCaretWidth(4) 
 510                 self
.SetCaretPeriod(0) #steady 
 512             self
.noteMode 
= not self
.noteMode
 
 518         # Return (Enter) is used to submit a command to the 
 520         if (not controlDown 
and not shiftDown 
and not altDown
) and key 
in [wx
.WXK_RETURN
, wx
.WXK_NUMPAD_ENTER
]: 
 521             if self
.CallTipActive(): 
 525         # Complete Text (from already typed words)     
 526         elif shiftDown 
and key 
in [wx
.WXK_RETURN
, wx
.WXK_NUMPAD_ENTER
]: 
 527             self
.OnShowCompHistory() 
 529         # Ctrl+Return (Ctrl+Enter) is used to insert a line break. 
 530         elif controlDown 
and key 
in [wx
.WXK_RETURN
, wx
.WXK_NUMPAD_ENTER
]: 
 531             if self
.CallTipActive(): 
 533             if currpos 
== endpos
: 
 536                 self
.insertLineBreak() 
 538         # Let Ctrl-Alt-* get handled normally. 
 539         elif controlDown 
and altDown
: 
 542         # Clear the current, unexecuted command. 
 543         elif key 
== wx
.WXK_ESCAPE
: 
 544             if self
.CallTipActive(): 
 549         # Clear the current command 
 550         elif key 
== wx
.WXK_BACK 
and controlDown 
and shiftDown
: 
 553         # Increase font size. 
 554         elif controlDown 
and key 
in (ord(']'), wx
.WXK_NUMPAD_ADD
): 
 555             dispatcher
.send(signal
='FontIncrease') 
 557         # Decrease font size. 
 558         elif controlDown 
and key 
in (ord('['), wx
.WXK_NUMPAD_SUBTRACT
): 
 559             dispatcher
.send(signal
='FontDecrease') 
 562         elif controlDown 
and key 
in (ord('='), wx
.WXK_NUMPAD_DIVIDE
): 
 563             dispatcher
.send(signal
='FontDefault') 
 565         # Cut to the clipboard. 
 566         elif (controlDown 
and key 
in (ord('X'), ord('x'))) \
 
 567                  or (shiftDown 
and key 
== wx
.WXK_DELETE
): 
 570         # Copy to the clipboard. 
 571         elif controlDown 
and not shiftDown \
 
 572                  and key 
in (ord('C'), ord('c'), wx
.WXK_INSERT
): 
 575         # Copy to the clipboard, including prompts. 
 576         elif controlDown 
and shiftDown \
 
 577                  and key 
in (ord('C'), ord('c'), wx
.WXK_INSERT
): 
 578             self
.CopyWithPrompts() 
 580         # Copy to the clipboard, including prefixed prompts. 
 581         elif altDown 
and not controlDown \
 
 582                  and key 
in (ord('C'), ord('c'), wx
.WXK_INSERT
): 
 583             self
.CopyWithPromptsPrefixed() 
 585         # Home needs to be aware of the prompt. 
 586         elif key 
== wx
.WXK_HOME
: 
 587             home 
= self
.promptPosEnd
 
 589                 self
.SetCurrentPos(home
) 
 590                 if not selecting 
and not shiftDown
: 
 592                     self
.EnsureCaretVisible() 
 597         # The following handlers modify text, so we need to see if 
 598         # there is a selection that includes text prior to the prompt. 
 600         # Don't modify a selection with text prior to the prompt. 
 601         elif selecting 
and key 
not in NAVKEYS 
and not self
.CanEdit(): 
 604         # Paste from the clipboard. 
 605         elif (controlDown 
and not shiftDown 
and key 
in (ord('V'), ord('v'))) \
 
 606                  or (shiftDown 
and not controlDown 
and key 
== wx
.WXK_INSERT
): 
 609         # manually invoke AutoComplete and Calltips 
 610         elif controlDown 
and key 
== wx
.WXK_SPACE
: 
 611             self
.OnCallTipAutoCompleteManually(shiftDown
) 
 613         # Paste from the clipboard, run commands. 
 614         elif controlDown 
and shiftDown 
and key 
in (ord('V'), ord('v')): 
 617         # Replace with the previous command from the history buffer. 
 618         elif (controlDown 
and key 
== wx
.WXK_UP
) \
 
 619                  or (altDown 
and key 
in (ord('P'), ord('p'))): 
 620             self
.OnHistoryReplace(step
=+1) 
 622         # Replace with the next command from the history buffer. 
 623         elif (controlDown 
and key 
== wx
.WXK_DOWN
) \
 
 624                  or (altDown 
and key 
in (ord('N'), ord('n'))): 
 625             self
.OnHistoryReplace(step
=-1) 
 627         # Insert the previous command from the history buffer. 
 628         elif (shiftDown 
and key 
== wx
.WXK_UP
) and self
.CanEdit(): 
 629             self
.OnHistoryInsert(step
=+1) 
 631         # Insert the next command from the history buffer. 
 632         elif (shiftDown 
and key 
== wx
.WXK_DOWN
) and self
.CanEdit(): 
 633             self
.OnHistoryInsert(step
=-1) 
 635         # Search up the history for the text in front of the cursor. 
 636         elif key 
== wx
.WXK_F8
: 
 637             self
.OnHistorySearch() 
 639         # Don't backspace over the latest non-continuation prompt. 
 640         elif key 
== wx
.WXK_BACK
: 
 641             if selecting 
and self
.CanEdit(): 
 643             elif currpos 
> self
.promptPosEnd
: 
 646         # Only allow these keys after the latest prompt. 
 647         elif key 
in (wx
.WXK_TAB
, wx
.WXK_DELETE
): 
 651         # Don't toggle between insert mode and overwrite mode. 
 652         elif key 
== wx
.WXK_INSERT
: 
 655         # Don't allow line deletion. 
 656         elif controlDown 
and key 
in (ord('L'), ord('l')): 
 659         # Don't allow line transposition. 
 660         elif controlDown 
and key 
in (ord('T'), ord('t')): 
 663         # Basic navigation keys should work anywhere. 
 667         # Protect the readonly portion of the shell. 
 668         elif not self
.CanEdit(): 
 675     def OnShowCompHistory(self
): 
 676         """Show possible autocompletion Words from already typed words.""" 
 679         his 
= self
.history
[:] 
 681         #put together in one string 
 682         joined 
= " ".join (his
) 
 685         #sort out only "good" words 
 686         newlist 
= re
.split("[ \.\[\]=}(\)\,0-9\"]", joined
) 
 688         #length > 1 (mix out "trash") 
 694         #unique (no duplicate words 
 695         #oneliner from german python forum => unique list 
 696         unlist 
= [thlist
[i
] for i 
in xrange(len(thlist
)) if thlist
[i
] not in thlist
[:i
]] 
 699         unlist
.sort(lambda a
, b
: cmp(a
.lower(), b
.lower())) 
 701         #this is more convenient, isn't it? 
 702         self
.AutoCompSetIgnoreCase(True) 
 704         #join again together in a string 
 705         stringlist 
= " ".join(unlist
) 
 707         #pos von 0 noch ausrechnen 
 709         #how big is the offset? 
 710         cpos 
= self
.GetCurrentPos() - 1 
 711         while chr (self
.GetCharAt (cpos
)).isalnum(): 
 714         #the most important part 
 715         self
.AutoCompShow(self
.GetCurrentPos() - cpos 
-1, stringlist
) 
 718     def clearCommand(self
): 
 719         """Delete the current, unexecuted command.""" 
 720         startpos 
= self
.promptPosEnd
 
 721         endpos 
= self
.GetTextLength() 
 722         self
.SetSelection(startpos
, endpos
) 
 723         self
.ReplaceSelection('') 
 726     def OnHistoryReplace(self
, step
): 
 727         """Replace with the previous/next command from the history buffer.""" 
 729         self
.replaceFromHistory(step
) 
 731     def replaceFromHistory(self
, step
): 
 732         """Replace selection with command from the history buffer.""" 
 734         self
.ReplaceSelection('') 
 735         newindex 
= self
.historyIndex 
+ step
 
 736         if -1 <= newindex 
<= len(self
.history
): 
 737             self
.historyIndex 
= newindex
 
 738         if 0 <= newindex 
<= len(self
.history
)-1: 
 739             command 
= self
.history
[self
.historyIndex
] 
 740             command 
= command
.replace('\n', os
.linesep 
+ ps2
) 
 741             self
.ReplaceSelection(command
) 
 743     def OnHistoryInsert(self
, step
): 
 744         """Insert the previous/next command from the history buffer.""" 
 745         if not self
.CanEdit(): 
 747         startpos 
= self
.GetCurrentPos() 
 748         self
.replaceFromHistory(step
) 
 749         endpos 
= self
.GetCurrentPos() 
 750         self
.SetSelection(endpos
, startpos
) 
 752     def OnHistorySearch(self
): 
 753         """Search up the history buffer for the text in front of the cursor.""" 
 754         if not self
.CanEdit(): 
 756         startpos 
= self
.GetCurrentPos() 
 757         # The text up to the cursor is what we search for. 
 758         numCharsAfterCursor 
= self
.GetTextLength() - startpos
 
 759         searchText 
= self
.getCommand(rstrip
=False) 
 760         if numCharsAfterCursor 
> 0: 
 761             searchText 
= searchText
[:-numCharsAfterCursor
] 
 764         # Search upwards from the current history position and loop 
 765         # back to the beginning if we don't find anything. 
 766         if (self
.historyIndex 
<= -1) \
 
 767         or (self
.historyIndex 
>= len(self
.history
)-2): 
 768             searchOrder 
= range(len(self
.history
)) 
 770             searchOrder 
= range(self
.historyIndex
+1, len(self
.history
)) + \
 
 771                           range(self
.historyIndex
) 
 772         for i 
in searchOrder
: 
 773             command 
= self
.history
[i
] 
 774             if command
[:len(searchText
)] == searchText
: 
 775                 # Replace the current selection with the one we found. 
 776                 self
.ReplaceSelection(command
[len(searchText
):]) 
 777                 endpos 
= self
.GetCurrentPos() 
 778                 self
.SetSelection(endpos
, startpos
) 
 779                 # We've now warped into middle of the history. 
 780                 self
.historyIndex 
= i
 
 783     def setStatusText(self
, text
): 
 784         """Display status information.""" 
 786         # This method will likely be replaced by the enclosing app to 
 787         # do something more interesting, like write to a status bar. 
 790     def insertLineBreak(self
): 
 791         """Insert a new line break.""" 
 793             self
.write(os
.linesep
) 
 797     def processLine(self
): 
 798         """Process the line of text at which the user hit Enter.""" 
 800         # The user hit ENTER and we need to decide what to do. They 
 801         # could be sitting on any line in the shell. 
 803         thepos 
= self
.GetCurrentPos() 
 804         startpos 
= self
.promptPosEnd
 
 805         endpos 
= self
.GetTextLength() 
 807         # If they hit RETURN inside the current command, execute the 
 810             self
.SetCurrentPos(endpos
) 
 811             self
.interp
.more 
= False 
 812             command 
= self
.GetTextRange(startpos
, endpos
) 
 813             lines 
= command
.split(os
.linesep 
+ ps2
) 
 814             lines 
= [line
.rstrip() for line 
in lines
] 
 815             command 
= '\n'.join(lines
) 
 816             if self
.reader
.isreading
: 
 818                     # Match the behavior of the standard Python shell 
 819                     # when the user hits return without entering a 
 822                 self
.reader
.input = command
 
 823                 self
.write(os
.linesep
) 
 826                 wx
.FutureCall(1, self
.EnsureCaretVisible
) 
 827         # Or replace the current command with the other command. 
 829             # If the line contains a command (even an invalid one). 
 830             if self
.getCommand(rstrip
=False): 
 831                 command 
= self
.getMultilineCommand() 
 834             # Otherwise, put the cursor back where we started. 
 836                 self
.SetCurrentPos(thepos
) 
 837                 self
.SetAnchor(thepos
) 
 839     def getMultilineCommand(self
, rstrip
=True): 
 840         """Extract a multi-line command from the editor. 
 842         The command may not necessarily be valid Python syntax.""" 
 843         # XXX Need to extract real prompts here. Need to keep track of 
 844         # the prompt every time a command is issued. 
 849         # This is a total hack job, but it works. 
 850         text 
= self
.GetCurLine()[0] 
 851         line 
= self
.GetCurrentLine() 
 852         while text
[:ps2size
] == ps2 
and line 
> 0: 
 855             text 
= self
.GetCurLine()[0] 
 856         if text
[:ps1size
] == ps1
: 
 857             line 
= self
.GetCurrentLine() 
 859             startpos 
= self
.GetCurrentPos() + ps1size
 
 862             while self
.GetCurLine()[0][:ps2size
] == ps2
: 
 865             stoppos 
= self
.GetCurrentPos() 
 866             command 
= self
.GetTextRange(startpos
, stoppos
) 
 867             command 
= command
.replace(os
.linesep 
+ ps2
, '\n') 
 868             command 
= command
.rstrip() 
 869             command 
= command
.replace('\n', os
.linesep 
+ ps2
) 
 873             command 
= command
.rstrip() 
 876     def getCommand(self
, text
=None, rstrip
=True): 
 877         """Extract a command from text which may include a shell prompt. 
 879         The command may not necessarily be valid Python syntax.""" 
 881             text 
= self
.GetCurLine()[0] 
 882         # Strip the prompt off the front leaving just the command. 
 883         command 
= self
.lstripPrompt(text
) 
 885             command 
= ''  # Real commands have prompts. 
 887             command 
= command
.rstrip() 
 890     def lstripPrompt(self
, text
): 
 891         """Return text without a leading prompt.""" 
 896         # Strip the prompt off the front of text. 
 897         if text
[:ps1size
] == ps1
: 
 898             text 
= text
[ps1size
:] 
 899         elif text
[:ps2size
] == ps2
: 
 900             text 
= text
[ps2size
:] 
 903     def push(self
, command
, silent 
= False): 
 904         """Send command to the interpreter for execution.""" 
 906             self
.write(os
.linesep
) 
 907         busy 
= wx
.BusyCursor() 
 909         self
.more 
= self
.interp
.push(command
) 
 913             self
.addHistory(command
.rstrip()) 
 917     def addHistory(self
, command
): 
 918         """Add command to the command history.""" 
 919         # Reset the history position. 
 920         self
.historyIndex 
= -1 
 921         # Insert this command into the history, unless it's a blank 
 922         # line or the same as the last command. 
 924         and (len(self
.history
) == 0 or command 
!= self
.history
[0]): 
 925             self
.history
.insert(0, command
) 
 926             dispatcher
.send(signal
="Shell.addHistory", command
=command
) 
 928     def write(self
, text
): 
 929         """Display text in the shell. 
 931         Replace line endings with OS-specific endings.""" 
 932         text 
= self
.fixLineEndings(text
) 
 934         self
.EnsureCaretVisible() 
 936     def fixLineEndings(self
, text
): 
 937         """Return text with line endings replaced by OS-specific endings.""" 
 938         lines 
= text
.split('\r\n') 
 939         for l 
in range(len(lines
)): 
 940             chunks 
= lines
[l
].split('\r') 
 941             for c 
in range(len(chunks
)): 
 942                 chunks
[c
] = os
.linesep
.join(chunks
[c
].split('\n')) 
 943             lines
[l
] = os
.linesep
.join(chunks
) 
 944         text 
= os
.linesep
.join(lines
) 
 948         """Display proper prompt for the context: ps1, ps2 or ps3. 
 950         If this is a continuation line, autoindent as necessary.""" 
 951         isreading 
= self
.reader
.isreading
 
 954             prompt 
= str(sys
.ps3
) 
 956             prompt 
= str(sys
.ps2
) 
 958             prompt 
= str(sys
.ps1
) 
 959         pos 
= self
.GetCurLine()[1] 
 964                 self
.write(os
.linesep
) 
 966             self
.promptPosStart 
= self
.GetCurrentPos() 
 970             self
.promptPosEnd 
= self
.GetCurrentPos() 
 971             # Keep the undo feature from undoing previous responses. 
 972             self
.EmptyUndoBuffer() 
 973         # XXX Add some autoindent magic here if more. 
 975             self
.write(' '*4)  # Temporary hack indentation. 
 976         self
.EnsureCaretVisible() 
 977         self
.ScrollToColumn(0) 
 980         """Replacement for stdin.readline().""" 
 983         reader
.isreading 
= True 
 986             while not reader
.input: 
 991             reader
.isreading 
= False 
 992         input = str(input)  # In case of Unicode. 
 996         """Replacement for stdin.readlines().""" 
 998         while lines
[-1:] != ['\n']: 
 999             lines
.append(self
.readline()) 
1002     def raw_input(self
, prompt
=''): 
1003         """Return string based on user input.""" 
1006         return self
.readline() 
1008     def ask(self
, prompt
='Please enter your response:'): 
1009         """Get response from the user using a dialog box.""" 
1010         dialog 
= wx
.TextEntryDialog(None, prompt
, 
1011                                     'Input Dialog (Raw)', '') 
1013             if dialog
.ShowModal() == wx
.ID_OK
: 
1014                 text 
= dialog
.GetValue() 
1021         """Halt execution pending a response from the user.""" 
1022         self
.ask('Press enter to continue:') 
1025         """Delete all text from the shell.""" 
1028     def run(self
, command
, prompt
=True, verbose
=True): 
1029         """Execute command as if it was typed in directly. 
1030         >>> shell.run('print "this"') 
1035         # Go to the very bottom of the text. 
1036         endpos 
= self
.GetTextLength() 
1037         self
.SetCurrentPos(endpos
) 
1038         command 
= command
.rstrip() 
1039         if prompt
: self
.prompt() 
1040         if verbose
: self
.write(command
) 
1043     def runfile(self
, filename
): 
1044         """Execute all commands in file as if they were typed into the 
1046         file = open(filename
) 
1049             for command 
in file.readlines(): 
1050                 if command
[:6] == 'shell.': 
1051                     # Run shell methods silently. 
1052                     self
.run(command
, prompt
=False, verbose
=False) 
1054                     self
.run(command
, prompt
=False, verbose
=True) 
1058     def autoCompleteShow(self
, command
, offset 
= 0): 
1059         """Display auto-completion popup list.""" 
1060         self
.AutoCompSetAutoHide(self
.autoCompleteAutoHide
) 
1061         self
.AutoCompSetIgnoreCase(self
.autoCompleteCaseInsensitive
) 
1062         list = self
.interp
.getAutoCompleteList(command
, 
1063                     includeMagic
=self
.autoCompleteIncludeMagic
, 
1064                     includeSingle
=self
.autoCompleteIncludeSingle
, 
1065                     includeDouble
=self
.autoCompleteIncludeDouble
) 
1067             options 
= ' '.join(list) 
1069             self
.AutoCompShow(offset
, options
) 
1071     def autoCallTipShow(self
, command
, insertcalltip 
= True, forceCallTip 
= False): 
1072         """Display argument spec and docstring in a popup window.""" 
1073         if self
.CallTipActive(): 
1074             self
.CallTipCancel() 
1075         (name
, argspec
, tip
) = self
.interp
.getCallTip(command
) 
1077             dispatcher
.send(signal
='Shell.calltip', sender
=self
, calltip
=tip
) 
1078         if not self
.autoCallTip 
and not forceCallTip
: 
1080         if argspec 
and insertcalltip 
and self
.callTipInsert
: 
1081             startpos 
= self
.GetCurrentPos() 
1082             self
.write(argspec 
+ ')') 
1083             endpos 
= self
.GetCurrentPos() 
1084             self
.SetSelection(endpos
, startpos
) 
1086             curpos 
= self
.GetCurrentPos() 
1087             tippos 
= curpos 
- (len(name
) + 1) 
1088             fallback 
= curpos 
- self
.GetColumn(curpos
) 
1089             # In case there isn't enough room, only go back to the 
1091             tippos 
= max(tippos
, fallback
) 
1092             self
.CallTipShow(tippos
, tip
) 
1094     def OnCallTipAutoCompleteManually (self
, shiftDown
): 
1095         """AutoComplete and Calltips manually.""" 
1096         if self
.AutoCompActive(): 
1097             self
.AutoCompCancel() 
1098         currpos 
= self
.GetCurrentPos() 
1099         stoppos 
= self
.promptPosEnd
 
1102         #go back until '.' is found 
1104         while cpos 
>= stoppos
: 
1105             if self
.GetCharAt(cpos
) == ord ('.'): 
1106                 pointavailpos 
= cpos
 
1110         #word from non whitespace until '.' 
1111         if pointavailpos 
!= -1: 
1112             #look backward for first whitespace char 
1113             textbehind 
= self
.GetTextRange (pointavailpos 
+ 1, currpos
) 
1118                 stoppos 
= self
.promptPosEnd
 
1119                 textbefore 
= self
.GetTextRange(stoppos
, pointavailpos
) 
1120                 self
.autoCompleteShow(textbefore
, len (textbehind
)) 
1123                 cpos 
= pointavailpos
 
1125                 while cpos 
> stoppos
: 
1126                     if chr(self
.GetCharAt(cpos
)).isspace(): 
1132                 ctips 
= self
.GetTextRange (begpos
, currpos
) 
1133                 ctindex 
= ctips
.find ('(') 
1134                 if ctindex 
!= -1 and not self
.CallTipActive(): 
1135                     #insert calltip, if current pos is '(', otherwise show it only 
1136                     self
.autoCallTipShow(ctips
[:ctindex 
+ 1],  
1137                         self
.GetCharAt(currpos 
- 1) == ord('(') and self
.GetCurrentPos() == self
.GetTextLength(), 
1141     def writeOut(self
, text
): 
1142         """Replacement for stdout.""" 
1145     def writeErr(self
, text
): 
1146         """Replacement for stderr.""" 
1149     def redirectStdin(self
, redirect
=True): 
1150         """If redirect is true then sys.stdin will come from the shell.""" 
1152             sys
.stdin 
= self
.reader
 
1154             sys
.stdin 
= self
.stdin
 
1156     def redirectStdout(self
, redirect
=True): 
1157         """If redirect is true then sys.stdout will go to the shell.""" 
1159             sys
.stdout 
= PseudoFileOut(self
.writeOut
) 
1161             sys
.stdout 
= self
.stdout
 
1163     def redirectStderr(self
, redirect
=True): 
1164         """If redirect is true then sys.stderr will go to the shell.""" 
1166             sys
.stderr 
= PseudoFileErr(self
.writeErr
) 
1168             sys
.stderr 
= self
.stderr
 
1171         """Return true if text is selected and can be cut.""" 
1172         if self
.GetSelectionStart() != self
.GetSelectionEnd() \
 
1173                and self
.GetSelectionStart() >= self
.promptPosEnd \
 
1174                and self
.GetSelectionEnd() >= self
.promptPosEnd
: 
1180         """Return true if a paste should succeed.""" 
1181         if self
.CanEdit() and editwindow
.EditWindow
.CanPaste(self
): 
1187         """Return true if editing should succeed.""" 
1188         if self
.GetSelectionStart() != self
.GetSelectionEnd(): 
1189             if self
.GetSelectionStart() >= self
.promptPosEnd \
 
1190                    and self
.GetSelectionEnd() >= self
.promptPosEnd
: 
1195             return self
.GetCurrentPos() >= self
.promptPosEnd
 
1198         """Remove selection and place it on the clipboard.""" 
1199         if self
.CanCut() and self
.CanCopy(): 
1200             if self
.AutoCompActive(): 
1201                 self
.AutoCompCancel() 
1202             if self
.CallTipActive(): 
1203                 self
.CallTipCancel() 
1205             self
.ReplaceSelection('') 
1208         """Copy selection and place it on the clipboard.""" 
1212             command 
= self
.GetSelectedText() 
1213             command 
= command
.replace(os
.linesep 
+ ps2
, os
.linesep
) 
1214             command 
= command
.replace(os
.linesep 
+ ps1
, os
.linesep
) 
1215             command 
= self
.lstripPrompt(text
=command
) 
1216             data 
= wx
.TextDataObject(command
) 
1219     def CopyWithPrompts(self
): 
1220         """Copy selection, including prompts, and place it on the clipboard.""" 
1222             command 
= self
.GetSelectedText() 
1223             data 
= wx
.TextDataObject(command
) 
1226     def CopyWithPromptsPrefixed(self
): 
1227         """Copy selection, including prompts prefixed with four 
1228         spaces, and place it on the clipboard.""" 
1230             command 
= self
.GetSelectedText() 
1232             command 
= spaces 
+ command
.replace(os
.linesep
, 
1233                                                os
.linesep 
+ spaces
) 
1234             data 
= wx
.TextDataObject(command
) 
1237     def _clip(self
, data
): 
1238         if wx
.TheClipboard
.Open(): 
1239             wx
.TheClipboard
.UsePrimarySelection(False) 
1240             wx
.TheClipboard
.SetData(data
) 
1241             wx
.TheClipboard
.Flush() 
1242             wx
.TheClipboard
.Close() 
1245         """Replace selection with clipboard contents.""" 
1246         if self
.CanPaste() and wx
.TheClipboard
.Open(): 
1248             if wx
.TheClipboard
.IsSupported(wx
.DataFormat(wx
.DF_TEXT
)): 
1249                 data 
= wx
.TextDataObject() 
1250                 if wx
.TheClipboard
.GetData(data
): 
1251                     self
.ReplaceSelection('') 
1252                     command 
= data
.GetText() 
1253                     command 
= command
.rstrip() 
1254                     command 
= self
.fixLineEndings(command
) 
1255                     command 
= self
.lstripPrompt(text
=command
) 
1256                     command 
= command
.replace(os
.linesep 
+ ps2
, '\n') 
1257                     command 
= command
.replace(os
.linesep
, '\n') 
1258                     command 
= command
.replace('\n', os
.linesep 
+ ps2
) 
1260             wx
.TheClipboard
.Close() 
1263     def PasteAndRun(self
): 
1264         """Replace selection with clipboard contents, run commands.""" 
1266         if wx
.TheClipboard
.Open(): 
1267             if wx
.TheClipboard
.IsSupported(wx
.DataFormat(wx
.DF_TEXT
)): 
1268                 data 
= wx
.TextDataObject() 
1269                 if wx
.TheClipboard
.GetData(data
): 
1270                     text 
= data
.GetText() 
1271             wx
.TheClipboard
.Close() 
1276     def Execute(self
, text
): 
1277         """Replace selection with text and run commands.""" 
1280         endpos 
= self
.GetTextLength() 
1281         self
.SetCurrentPos(endpos
) 
1282         startpos 
= self
.promptPosEnd
 
1283         self
.SetSelection(startpos
, endpos
) 
1284         self
.ReplaceSelection('') 
1285         text 
= text
.lstrip() 
1286         text 
= self
.fixLineEndings(text
) 
1287         text 
= self
.lstripPrompt(text
) 
1288         text 
= text
.replace(os
.linesep 
+ ps1
, '\n') 
1289         text 
= text
.replace(os
.linesep 
+ ps2
, '\n') 
1290         text 
= text
.replace(os
.linesep
, '\n') 
1291         lines 
= text
.split('\n') 
1295             if line
.strip() == ps2
.strip(): 
1296                 # If we are pasting from something like a 
1297                 # web page that drops the trailing space 
1298                 # from the ps2 prompt of a blank line. 
1300             lstrip 
= line
.lstrip() 
1301             if line
.strip() != '' and lstrip 
== line 
and \
 
1302                     lstrip
[:4] not in ['else','elif'] and \
 
1303                     lstrip
[:6] != 'except': 
1306                     # Add the previous command to the list. 
1307                     commands
.append(command
) 
1308                 # Start a new command, which may be multiline. 
1311                 # Multiline command. Add to the command. 
1314         commands
.append(command
) 
1315         for command 
in commands
: 
1316             command 
= command
.replace('\n', os
.linesep 
+ ps2
) 
1321     def wrap(self
, wrap
=True): 
1322         """Sets whether text is word wrapped.""" 
1324             self
.SetWrapMode(wrap
) 
1325         except AttributeError: 
1326             return 'Wrapping is not available in this version.' 
1328     def zoom(self
, points
=0): 
1329         """Set the zoom level. 
1331         This number of points is added to the size of all fonts.  It 
1332         may be positive to magnify or negative to reduce.""" 
1333         self
.SetZoom(points
) 
1337     def LoadSettings(self
, config
): 
1338         self
.autoComplete              
= config
.ReadBool('Options/AutoComplete', True) 
1339         self
.autoCompleteIncludeMagic  
= config
.ReadBool('Options/AutoCompleteIncludeMagic', True) 
1340         self
.autoCompleteIncludeSingle 
= config
.ReadBool('Options/AutoCompleteIncludeSingle', True) 
1341         self
.autoCompleteIncludeDouble 
= config
.ReadBool('Options/AutoCompleteIncludeDouble', True) 
1343         self
.autoCallTip 
= config
.ReadBool('Options/AutoCallTip', True) 
1344         self
.callTipInsert 
= config
.ReadBool('Options/CallTipInsert', True) 
1345         self
.SetWrapMode(config
.ReadBool('View/WrapMode', True)) 
1347         useAA 
= config
.ReadBool('Options/UseAntiAliasing', self
.GetUseAntiAliasing()) 
1348         self
.SetUseAntiAliasing(useAA
) 
1349         self
.lineNumbers 
= config
.ReadBool('View/ShowLineNumbers', True) 
1350         self
.setDisplayLineNumbers (self
.lineNumbers
) 
1351         zoom 
= config
.ReadInt('View/Zoom/Shell', -99) 
1357     def SaveSettings(self
, config
): 
1358         config
.WriteBool('Options/AutoComplete', self
.autoComplete
) 
1359         config
.WriteBool('Options/AutoCompleteIncludeMagic', self
.autoCompleteIncludeMagic
) 
1360         config
.WriteBool('Options/AutoCompleteIncludeSingle', self
.autoCompleteIncludeSingle
) 
1361         config
.WriteBool('Options/AutoCompleteIncludeDouble', self
.autoCompleteIncludeDouble
) 
1362         config
.WriteBool('Options/AutoCallTip', self
.autoCallTip
) 
1363         config
.WriteBool('Options/CallTipInsert', self
.callTipInsert
) 
1364         config
.WriteBool('Options/UseAntiAliasing', self
.GetUseAntiAliasing()) 
1365         config
.WriteBool('View/WrapMode', self
.GetWrapMode()) 
1366         config
.WriteBool('View/ShowLineNumbers', self
.lineNumbers
) 
1367         config
.WriteInt('View/Zoom/Shell', self
.GetZoom()) 
1371 ## NOTE: The DnD of file names is disabled until I can figure out how 
1372 ## best to still allow DnD of text. 
1375 ## #seb : File drag and drop 
1376 ## class FileDropTarget(wx.FileDropTarget): 
1377 ##     def __init__(self, obj): 
1378 ##         wx.FileDropTarget.__init__(self) 
1380 ##     def OnDropFiles(self, x, y, filenames): 
1381 ##         if len(filenames) == 1: 
1382 ##             txt = 'r\"%s\"' % filenames[0] 
1385 ##             for f in filenames: 
1386 ##                 txt += 'r\"%s\" , ' % f 
1388 ##         self.obj.AppendText(txt) 
1389 ##         pos = self.obj.GetCurrentPos() 
1390 ##         self.obj.SetCurrentPos( pos ) 
1391 ##         self.obj.SetSelection( pos, pos ) 
1395 ## class TextAndFileDropTarget(wx.DropTarget): 
1396 ##     def __init__(self, shell): 
1397 ##         wx.DropTarget.__init__(self) 
1398 ##         self.shell = shell 
1399 ##         self.compdo = wx.DataObjectComposite() 
1400 ##         self.textdo = wx.TextDataObject() 
1401 ##         self.filedo = wx.FileDataObject() 
1402 ##         self.compdo.Add(self.textdo) 
1403 ##         self.compdo.Add(self.filedo, True) 
1405 ##         self.SetDataObject(self.compdo) 
1407 ##     def OnDrop(self, x, y): 
1410 ##     def OnData(self, x, y, result): 
1412 ##         if self.textdo.GetTextLength() > 1: 
1413 ##             text = self.textdo.GetText() 
1414 ##             # *** Do somethign with the dragged text here... 
1415 ##             self.textdo.SetText('') 
1417 ##             filenames = str(self.filename.GetFilenames()) 
1418 ##             if len(filenames) == 1: 
1419 ##                 txt = 'r\"%s\"' % filenames[0] 
1422 ##                 for f in filenames: 
1423 ##                     txt += 'r\"%s\" , ' % f 
1425 ##             self.shell.AppendText(txt) 
1426 ##             pos = self.shell.GetCurrentPos() 
1427 ##             self.shell.SetCurrentPos( pos ) 
1428 ##             self.shell.SetSelection( pos, pos )