Updated PyCrust from Patrick O'Brien
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14343 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -52,7 +52,7 @@ class CrustFrame(wxFrame, ShellMenu):
|
|||||||
"""Create a PyCrust CrustFrame instance."""
|
"""Create a PyCrust CrustFrame instance."""
|
||||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||||
intro += '\nSponsored by Orbtech.com - Your Source For Python Development Services'
|
intro += '\nSponsored by Orbtech - Your Source For Python Development Services'
|
||||||
self.CreateStatusBar()
|
self.CreateStatusBar()
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
self.SetStatusText(intro.replace('\n', ', '))
|
||||||
if wxPlatform == '__WXMSW__':
|
if wxPlatform == '__WXMSW__':
|
||||||
|
@@ -50,11 +50,13 @@ class FillingTree(wxTreeCtrl):
|
|||||||
"""Return a dictionary with the attributes or contents of object."""
|
"""Return a dictionary with the attributes or contents of object."""
|
||||||
dict = {}
|
dict = {}
|
||||||
objtype = type(object)
|
objtype = type(object)
|
||||||
if objtype is types.DictType:
|
if (objtype is types.DictType) \
|
||||||
|
or str(objtype)[17:23] == 'BTrees' and hasattr(object, 'keys'):
|
||||||
dict = object
|
dict = object
|
||||||
elif (objtype in (types.ClassType, \
|
elif (objtype in (types.ClassType, \
|
||||||
types.InstanceType, \
|
types.InstanceType, \
|
||||||
types.ModuleType)):
|
types.ModuleType)) \
|
||||||
|
or str(objtype)[1:10] == 'extension':
|
||||||
for key in introspect.getAttributeNames(object):
|
for key in introspect.getAttributeNames(object):
|
||||||
# Believe it or not, some attributes can disappear, such as
|
# Believe it or not, some attributes can disappear, such as
|
||||||
# the exc_traceback attribute of the sys module. So this is
|
# the exc_traceback attribute of the sys module. So this is
|
||||||
@@ -74,7 +76,10 @@ class FillingTree(wxTreeCtrl):
|
|||||||
if not children:
|
if not children:
|
||||||
return
|
return
|
||||||
list = children.keys()
|
list = children.keys()
|
||||||
|
try:
|
||||||
list.sort(lambda x, y: cmp(x.lower(), y.lower()))
|
list.sort(lambda x, y: cmp(x.lower(), y.lower()))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
for item in list:
|
for item in list:
|
||||||
itemtext = str(item)
|
itemtext = str(item)
|
||||||
# Show string dictionary items with single quotes, except for
|
# Show string dictionary items with single quotes, except for
|
||||||
@@ -101,7 +106,7 @@ class FillingTree(wxTreeCtrl):
|
|||||||
object = self.GetPyData(item)
|
object = self.GetPyData(item)
|
||||||
text = ''
|
text = ''
|
||||||
text += self.getFullName(item)
|
text += self.getFullName(item)
|
||||||
text += '\n\nType: ' + str(type(object))[7:-2]
|
text += '\n\nType: ' + str(type(object))
|
||||||
value = str(object)
|
value = str(object)
|
||||||
if type(object) is types.StringType:
|
if type(object) is types.StringType:
|
||||||
value = repr(value)
|
value = repr(value)
|
||||||
@@ -133,7 +138,9 @@ class FillingTree(wxTreeCtrl):
|
|||||||
name = self.GetItemText(item)
|
name = self.GetItemText(item)
|
||||||
# Apply dictionary syntax to dictionary items, except the root
|
# Apply dictionary syntax to dictionary items, except the root
|
||||||
# and first level children of a namepace.
|
# and first level children of a namepace.
|
||||||
if type(parentobject) is types.DictType \
|
if (type(parentobject) is types.DictType \
|
||||||
|
or str(type(parentobject))[17:23] == 'BTrees' \
|
||||||
|
and hasattr(parentobject, 'keys')) \
|
||||||
and ((item != self.root and parent != self.root) \
|
and ((item != self.root and parent != self.root) \
|
||||||
or (parent == self.root and not self.rootIsNamespace)):
|
or (parent == self.root and not self.rootIsNamespace)):
|
||||||
name = '[' + name + ']'
|
name = '[' + name + ']'
|
||||||
|
@@ -93,28 +93,40 @@ def getCallTip(command='', locals=None):
|
|||||||
|
|
||||||
The call tip information will be based on the locals namespace."""
|
The call tip information will be based on the locals namespace."""
|
||||||
|
|
||||||
|
calltip = ('', '', '')
|
||||||
# Get the proper chunk of code from the command.
|
# Get the proper chunk of code from the command.
|
||||||
root = getRoot(command, terminator='(')
|
root = getRoot(command, terminator='(')
|
||||||
try:
|
try:
|
||||||
object = eval(root, locals)
|
object = eval(root, locals)
|
||||||
except:
|
except:
|
||||||
return ''
|
return calltip
|
||||||
dropSelf = 0
|
name = ''
|
||||||
if hasattr(object, '__name__'): # Make sure this is a useable object.
|
dropSelf = 1
|
||||||
# Switch to the object that has the information we need.
|
# Switch to the object that has the information we need.
|
||||||
if inspect.ismethod(object) or hasattr(object, 'im_func'):
|
if inspect.isbuiltin(object):
|
||||||
|
# Builtin functions don't have an argspec that we can get.
|
||||||
|
pass
|
||||||
|
elif inspect.ismethod(object) or hasattr(object, 'im_func'):
|
||||||
# Get the function from the object otherwise inspect.getargspec()
|
# Get the function from the object otherwise inspect.getargspec()
|
||||||
# complains that the object isn't a Python function.
|
# complains that the object isn't a Python function.
|
||||||
object = object.im_func
|
object = object.im_func
|
||||||
dropSelf = 1
|
|
||||||
elif inspect.isclass(object):
|
elif inspect.isclass(object):
|
||||||
# Get the __init__ method function for the class.
|
# Get the __init__ method function for the class.
|
||||||
constructor = getConstructor(object)
|
constructor = getConstructor(object)
|
||||||
if constructor is not None:
|
if constructor is not None:
|
||||||
object = constructor
|
object = constructor
|
||||||
dropSelf = 1
|
elif callable(object):
|
||||||
|
# Get the __call__ method instead.
|
||||||
|
try:
|
||||||
|
object = object.__call__.im_func
|
||||||
|
except:
|
||||||
|
dropSelf = 0
|
||||||
|
else:
|
||||||
|
dropSelf = 0
|
||||||
|
if hasattr(object, '__name__'):
|
||||||
name = object.__name__
|
name = object.__name__
|
||||||
tip1 = ''
|
tip1 = ''
|
||||||
|
argspec = ''
|
||||||
if inspect.isbuiltin(object):
|
if inspect.isbuiltin(object):
|
||||||
# Builtin functions don't have an argspec that we can get.
|
# Builtin functions don't have an argspec that we can get.
|
||||||
pass
|
pass
|
||||||
@@ -143,9 +155,8 @@ def getCallTip(command='', locals=None):
|
|||||||
tip = '%s\n\n%s\n\n%s' % (tip1, tip2, tip3)
|
tip = '%s\n\n%s\n\n%s' % (tip1, tip2, tip3)
|
||||||
else:
|
else:
|
||||||
tip = tip1
|
tip = tip1
|
||||||
return tip.strip()
|
calltip = (name, argspec[1:-1], tip.strip())
|
||||||
else:
|
return calltip
|
||||||
return ''
|
|
||||||
|
|
||||||
def getConstructor(object):
|
def getConstructor(object):
|
||||||
"""Return constructor for class object, or None if there isn't one."""
|
"""Return constructor for class object, or None if there isn't one."""
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
commands to be sent to the interpreter. This particular shell is based on
|
commands to be sent to the interpreter. This particular shell is based on
|
||||||
wxPython's wxStyledTextCtrl. The latest files are always available at the
|
wxPython's wxStyledTextCtrl. The latest files are always available at the
|
||||||
SourceForge project page at http://sourceforge.net/projects/pycrust/.
|
SourceForge project page at http://sourceforge.net/projects/pycrust/.
|
||||||
Sponsored by Orbtech.com - Your Source For Python Development Services"""
|
Sponsored by Orbtech - Your Source For Python Development Services"""
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
@@ -82,10 +82,13 @@ Ctrl+C Copy selected text, removing prompts.
|
|||||||
Ctrl+Shift+C Copy selected text, retaining prompts.
|
Ctrl+Shift+C Copy selected text, retaining prompts.
|
||||||
Ctrl+X Cut selected text.
|
Ctrl+X Cut selected text.
|
||||||
Ctrl+V Paste from clipboard.
|
Ctrl+V Paste from clipboard.
|
||||||
|
Ctrl+Shift+V Paste and run multiple commands from clipboard.
|
||||||
Ctrl+Up Arrow Retrieve Previous History item.
|
Ctrl+Up Arrow Retrieve Previous History item.
|
||||||
Alt+P Retrieve Previous History item.
|
Alt+P Retrieve Previous History item.
|
||||||
Ctrl+Down Arrow Retrieve Next History item.
|
Ctrl+Down Arrow Retrieve Next History item.
|
||||||
Alt+N Retrieve Next History item.
|
Alt+N Retrieve Next History item.
|
||||||
|
Shift+Up Arrow Insert Previous History item.
|
||||||
|
Shift+Down Arrow Insert Next History item.
|
||||||
F8 Command-completion of History item.
|
F8 Command-completion of History item.
|
||||||
(Type a few characters of a previous command and then press F8.)
|
(Type a few characters of a previous command and then press F8.)
|
||||||
"""
|
"""
|
||||||
@@ -335,17 +338,32 @@ class Shell(wxStyledTextCtrl):
|
|||||||
altDown = event.AltDown()
|
altDown = event.AltDown()
|
||||||
shiftDown = event.ShiftDown()
|
shiftDown = event.ShiftDown()
|
||||||
currpos = self.GetCurrentPos()
|
currpos = self.GetCurrentPos()
|
||||||
# Return is used to submit a command to the interpreter.
|
endpos = self.GetTextLength()
|
||||||
if key == WXK_RETURN:
|
# Return (Enter) is used to submit a command to the interpreter.
|
||||||
|
if not controlDown and key == WXK_RETURN:
|
||||||
if self.AutoCompActive(): self.AutoCompCancel()
|
if self.AutoCompActive(): self.AutoCompCancel()
|
||||||
if self.CallTipActive(): self.CallTipCancel()
|
if self.CallTipActive(): self.CallTipCancel()
|
||||||
self.processLine()
|
self.processLine()
|
||||||
|
# Ctrl+Return (Cntrl+Enter) is used to insert a line break.
|
||||||
|
elif controlDown and key == WXK_RETURN:
|
||||||
|
if self.AutoCompActive(): self.AutoCompCancel()
|
||||||
|
if self.CallTipActive(): self.CallTipCancel()
|
||||||
|
if currpos == endpos:
|
||||||
|
self.processLine()
|
||||||
|
else:
|
||||||
|
self.insertLineBreak()
|
||||||
# If the auto-complete window is up let it do its thing.
|
# If the auto-complete window is up let it do its thing.
|
||||||
elif self.AutoCompActive():
|
elif self.AutoCompActive():
|
||||||
event.Skip()
|
event.Skip()
|
||||||
# Let Ctrl-Alt-* get handled normally.
|
# Let Ctrl-Alt-* get handled normally.
|
||||||
elif controlDown and altDown:
|
elif controlDown and altDown:
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
# Clear the current, unexecuted command.
|
||||||
|
elif key == WXK_ESCAPE:
|
||||||
|
if self.CallTipActive():
|
||||||
|
event.Skip()
|
||||||
|
else:
|
||||||
|
self.clearCommand()
|
||||||
# Cut to the clipboard.
|
# Cut to the clipboard.
|
||||||
elif (controlDown and key in (ord('X'), ord('x'))) \
|
elif (controlDown and key in (ord('X'), ord('x'))) \
|
||||||
or (shiftDown and key == WXK_DELETE):
|
or (shiftDown and key == WXK_DELETE):
|
||||||
@@ -359,17 +377,28 @@ class Shell(wxStyledTextCtrl):
|
|||||||
and key in (ord('C'), ord('c'), WXK_INSERT):
|
and key in (ord('C'), ord('c'), WXK_INSERT):
|
||||||
self.CopyWithPrompts()
|
self.CopyWithPrompts()
|
||||||
# Paste from the clipboard.
|
# Paste from the clipboard.
|
||||||
elif (controlDown and key in (ord('V'), ord('v'), WXK_INSERT)) \
|
elif (controlDown and not shiftDown \
|
||||||
or (shiftDown and key == WXK_INSERT):
|
and key in (ord('V'), ord('v'))) \
|
||||||
|
or (shiftDown and not controlDown and key == WXK_INSERT):
|
||||||
self.Paste()
|
self.Paste()
|
||||||
# Retrieve the previous command from the history buffer.
|
# Paste from the clipboard, run commands.
|
||||||
|
elif controlDown and shiftDown \
|
||||||
|
and key in (ord('V'), ord('v')):
|
||||||
|
self.PasteAndRun()
|
||||||
|
# Replace with the previous command from the history buffer.
|
||||||
elif (controlDown and key == WXK_UP) \
|
elif (controlDown and key == WXK_UP) \
|
||||||
or (altDown and key in (ord('P'), ord('p'))):
|
or (altDown and key in (ord('P'), ord('p'))):
|
||||||
self.OnHistoryRetrieve(step=+1)
|
self.OnHistoryReplace(step=+1)
|
||||||
# Retrieve the next command from the history buffer.
|
# Replace with the next command from the history buffer.
|
||||||
elif (controlDown and key == WXK_DOWN) \
|
elif (controlDown and key == WXK_DOWN) \
|
||||||
or (altDown and key in (ord('N'), ord('n'))):
|
or (altDown and key in (ord('N'), ord('n'))):
|
||||||
self.OnHistoryRetrieve(step=-1)
|
self.OnHistoryReplace(step=-1)
|
||||||
|
# Insert the previous command from the history buffer.
|
||||||
|
elif (shiftDown and key == WXK_UP):
|
||||||
|
self.OnHistoryInsert(step=+1)
|
||||||
|
# Insert the next command from the history buffer.
|
||||||
|
elif (shiftDown and key == WXK_DOWN):
|
||||||
|
self.OnHistoryInsert(step=-1)
|
||||||
# Search up the history for the text in front of the cursor.
|
# Search up the history for the text in front of the cursor.
|
||||||
elif key == WXK_F8:
|
elif key == WXK_F8:
|
||||||
self.OnHistorySearch()
|
self.OnHistorySearch()
|
||||||
@@ -383,6 +412,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
else:
|
else:
|
||||||
self.SetCurrentPos(home)
|
self.SetCurrentPos(home)
|
||||||
self.SetAnchor(home)
|
self.SetAnchor(home)
|
||||||
|
self.EnsureCaretVisible()
|
||||||
else:
|
else:
|
||||||
event.Skip()
|
event.Skip()
|
||||||
# Basic navigation keys should work anywhere.
|
# Basic navigation keys should work anywhere.
|
||||||
@@ -412,22 +442,36 @@ class Shell(wxStyledTextCtrl):
|
|||||||
else:
|
else:
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
def OnHistoryRetrieve(self, step):
|
def clearCommand(self):
|
||||||
"""Retrieve the previous/next command from the history buffer."""
|
"""Delete the current, unexecuted command."""
|
||||||
if not self.CanEdit():
|
startpos = self.promptPosEnd
|
||||||
return
|
endpos = self.GetTextLength()
|
||||||
startpos = self.GetCurrentPos()
|
self.SetSelection(startpos, endpos)
|
||||||
|
self.ReplaceSelection('')
|
||||||
|
self.more = 0
|
||||||
|
|
||||||
|
def OnHistoryReplace(self, step):
|
||||||
|
"""Replace with the previous/next command from the history buffer."""
|
||||||
|
self.clearCommand()
|
||||||
|
self.replaceFromHistory(step)
|
||||||
|
|
||||||
|
def replaceFromHistory(self, step):
|
||||||
|
"""Replace selection with command from the history buffer."""
|
||||||
|
self.ReplaceSelection('')
|
||||||
newindex = self.historyIndex + step
|
newindex = self.historyIndex + step
|
||||||
if not (-1 <= newindex < len(self.history)):
|
if -1 <= newindex <= len(self.history):
|
||||||
return
|
|
||||||
self.historyIndex = newindex
|
self.historyIndex = newindex
|
||||||
if newindex == -1:
|
if 0 <= newindex <= len(self.history)-1:
|
||||||
self.ReplaceSelection('')
|
|
||||||
else:
|
|
||||||
self.ReplaceSelection('')
|
|
||||||
command = self.history[self.historyIndex]
|
command = self.history[self.historyIndex]
|
||||||
command = command.replace('\n', os.linesep + sys.ps2)
|
command = command.replace('\n', os.linesep + sys.ps2)
|
||||||
self.ReplaceSelection(command)
|
self.ReplaceSelection(command)
|
||||||
|
|
||||||
|
def OnHistoryInsert(self, step):
|
||||||
|
"""Insert the previous/next command from the history buffer."""
|
||||||
|
if not self.CanEdit():
|
||||||
|
return
|
||||||
|
startpos = self.GetCurrentPos()
|
||||||
|
self.replaceFromHistory(step)
|
||||||
endpos = self.GetCurrentPos()
|
endpos = self.GetCurrentPos()
|
||||||
self.SetSelection(endpos, startpos)
|
self.SetSelection(endpos, startpos)
|
||||||
|
|
||||||
@@ -469,6 +513,13 @@ class Shell(wxStyledTextCtrl):
|
|||||||
# to do something more interesting, like write to a status bar.
|
# to do something more interesting, like write to a status bar.
|
||||||
print text
|
print text
|
||||||
|
|
||||||
|
def insertLineBreak(self):
|
||||||
|
"""Insert a new line break."""
|
||||||
|
if self.CanEdit():
|
||||||
|
self.write(os.linesep)
|
||||||
|
self.more = 1
|
||||||
|
self.prompt()
|
||||||
|
|
||||||
def processLine(self):
|
def processLine(self):
|
||||||
"""Process the line of text at which the user hit Enter."""
|
"""Process the line of text at which the user hit Enter."""
|
||||||
|
|
||||||
@@ -476,41 +527,28 @@ class Shell(wxStyledTextCtrl):
|
|||||||
# sitting on any line in the shell.
|
# sitting on any line in the shell.
|
||||||
|
|
||||||
thepos = self.GetCurrentPos()
|
thepos = self.GetCurrentPos()
|
||||||
|
startpos = self.promptPosEnd
|
||||||
endpos = self.GetTextLength()
|
endpos = self.GetTextLength()
|
||||||
# If they hit RETURN at the very bottom, execute the command.
|
# If they hit RETURN inside the current command, execute the command.
|
||||||
if thepos == endpos:
|
if self.CanEdit():
|
||||||
|
self.SetCurrentPos(endpos)
|
||||||
self.interp.more = 0
|
self.interp.more = 0
|
||||||
if self.getCommand():
|
command = self.GetTextRange(startpos, endpos)
|
||||||
command = self.GetTextRange(self.promptPosEnd, endpos)
|
lines = command.split(os.linesep + sys.ps2)
|
||||||
else:
|
lines = [line.rstrip() for line in lines]
|
||||||
# This is a hack, now that we allow editing of previous
|
command = '\n'.join(lines)
|
||||||
# lines, which throws off our promptPos values.
|
|
||||||
newend = endpos - len(self.getCommand(rstrip=0))
|
|
||||||
command = self.GetTextRange(self.promptPosEnd, newend)
|
|
||||||
command = command.replace(os.linesep + sys.ps2, '\n')
|
|
||||||
self.push(command)
|
self.push(command)
|
||||||
# Or replace the current command with the other command.
|
# Or replace the current command with the other command.
|
||||||
elif thepos < self.promptPosStart:
|
else:
|
||||||
theline = self.GetCurrentLine()
|
# If the line contains a command (even an invalid one).
|
||||||
command = self.getCommand(rstrip=0)
|
if self.getCommand(rstrip=0):
|
||||||
# If the new line contains a command (even an invalid one).
|
|
||||||
if command:
|
|
||||||
command = self.getMultilineCommand()
|
command = self.getMultilineCommand()
|
||||||
self.SetCurrentPos(endpos)
|
self.clearCommand()
|
||||||
startpos = self.promptPosEnd
|
|
||||||
self.SetSelection(startpos, endpos)
|
|
||||||
self.ReplaceSelection('')
|
|
||||||
self.write(command)
|
self.write(command)
|
||||||
self.more = 0
|
|
||||||
# Otherwise, put the cursor back where we started.
|
# Otherwise, put the cursor back where we started.
|
||||||
else:
|
else:
|
||||||
self.SetCurrentPos(thepos)
|
self.SetCurrentPos(thepos)
|
||||||
self.SetAnchor(thepos)
|
self.SetAnchor(thepos)
|
||||||
# Or add a new line to the current single or multi-line command.
|
|
||||||
elif thepos > self.promptPosEnd:
|
|
||||||
self.write(os.linesep)
|
|
||||||
self.more = 1
|
|
||||||
self.prompt()
|
|
||||||
|
|
||||||
def getMultilineCommand(self, rstrip=1):
|
def getMultilineCommand(self, rstrip=1):
|
||||||
"""Extract a multi-line command from the editor.
|
"""Extract a multi-line command from the editor.
|
||||||
@@ -716,10 +754,19 @@ class Shell(wxStyledTextCtrl):
|
|||||||
def autoCallTipShow(self, command):
|
def autoCallTipShow(self, command):
|
||||||
"""Display argument spec and docstring in a popup bubble thingie."""
|
"""Display argument spec and docstring in a popup bubble thingie."""
|
||||||
if self.CallTipActive: self.CallTipCancel()
|
if self.CallTipActive: self.CallTipCancel()
|
||||||
tip = self.interp.getCallTip(command)
|
(name, argspec, tip) = self.interp.getCallTip(command)
|
||||||
|
if argspec:
|
||||||
|
startpos = self.GetCurrentPos()
|
||||||
|
self.write(argspec + ')')
|
||||||
|
endpos = self.GetCurrentPos()
|
||||||
|
self.SetSelection(endpos, startpos)
|
||||||
if tip:
|
if tip:
|
||||||
offset = self.GetCurrentPos()
|
curpos = self.GetCurrentPos()
|
||||||
self.CallTipShow(offset, tip)
|
tippos = curpos - (len(name) + 1)
|
||||||
|
fallback = curpos - self.GetColumn(curpos)
|
||||||
|
# In case there isn't enough room, only go back to the fallback.
|
||||||
|
tippos = max(tippos, fallback)
|
||||||
|
self.CallTipShow(tippos, tip)
|
||||||
|
|
||||||
def writeOut(self, text):
|
def writeOut(self, text):
|
||||||
"""Replacement for stdout."""
|
"""Replacement for stdout."""
|
||||||
@@ -805,11 +852,11 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def Paste(self):
|
def Paste(self):
|
||||||
"""Replace selection with clipboard contents."""
|
"""Replace selection with clipboard contents."""
|
||||||
if self.CanPaste():
|
if self.CanPaste() and wxTheClipboard.Open():
|
||||||
if wxTheClipboard.Open():
|
|
||||||
if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
|
if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
|
||||||
data = wxTextDataObject()
|
data = wxTextDataObject()
|
||||||
if wxTheClipboard.GetData(data):
|
if wxTheClipboard.GetData(data):
|
||||||
|
self.ReplaceSelection('')
|
||||||
command = data.GetText()
|
command = data.GetText()
|
||||||
command = command.rstrip()
|
command = command.rstrip()
|
||||||
command = self.fixLineEndings(command)
|
command = self.fixLineEndings(command)
|
||||||
@@ -817,10 +864,49 @@ class Shell(wxStyledTextCtrl):
|
|||||||
command = command.replace(os.linesep + sys.ps2, '\n')
|
command = command.replace(os.linesep + sys.ps2, '\n')
|
||||||
command = command.replace(os.linesep, '\n')
|
command = command.replace(os.linesep, '\n')
|
||||||
command = command.replace('\n', os.linesep + sys.ps2)
|
command = command.replace('\n', os.linesep + sys.ps2)
|
||||||
self.ReplaceSelection('')
|
|
||||||
self.write(command)
|
self.write(command)
|
||||||
wxTheClipboard.Close()
|
wxTheClipboard.Close()
|
||||||
|
|
||||||
|
def PasteAndRun(self):
|
||||||
|
"""Replace selection with clipboard contents, run commands."""
|
||||||
|
if wxTheClipboard.Open():
|
||||||
|
if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
|
||||||
|
data = wxTextDataObject()
|
||||||
|
if wxTheClipboard.GetData(data):
|
||||||
|
endpos = self.GetTextLength()
|
||||||
|
self.SetCurrentPos(endpos)
|
||||||
|
startpos = self.promptPosEnd
|
||||||
|
self.SetSelection(startpos, endpos)
|
||||||
|
self.ReplaceSelection('')
|
||||||
|
text = data.GetText()
|
||||||
|
text = text.strip()
|
||||||
|
text = self.fixLineEndings(text)
|
||||||
|
text = self.lstripPrompt(text=text)
|
||||||
|
text = text.replace(os.linesep + sys.ps1, '\n')
|
||||||
|
text = text.replace(os.linesep + sys.ps2, '\n')
|
||||||
|
text = text.replace(os.linesep, '\n')
|
||||||
|
lines = text.split('\n')
|
||||||
|
commands = []
|
||||||
|
command = ''
|
||||||
|
for line in lines:
|
||||||
|
if line.strip() != '' and line.lstrip() == line:
|
||||||
|
# New command.
|
||||||
|
if command:
|
||||||
|
# Add the previous command to the list.
|
||||||
|
commands.append(command)
|
||||||
|
# Start a new command, which may be multiline.
|
||||||
|
command = line
|
||||||
|
else:
|
||||||
|
# Multiline command. Add to the command.
|
||||||
|
command += '\n'
|
||||||
|
command += line
|
||||||
|
commands.append(command)
|
||||||
|
for command in commands:
|
||||||
|
command = command.replace('\n', os.linesep + sys.ps2)
|
||||||
|
self.write(command)
|
||||||
|
self.processLine()
|
||||||
|
wxTheClipboard.Close()
|
||||||
|
|
||||||
|
|
||||||
wxID_SELECTALL = NewId() # This *should* be defined by wxPython.
|
wxID_SELECTALL = NewId() # This *should* be defined by wxPython.
|
||||||
ID_AUTOCOMP = NewId()
|
ID_AUTOCOMP = NewId()
|
||||||
@@ -1014,7 +1100,7 @@ class ShellFrame(wxFrame, ShellMenu):
|
|||||||
"""Create a PyCrust ShellFrame instance."""
|
"""Create a PyCrust ShellFrame instance."""
|
||||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||||
intro += '\nSponsored by Orbtech.com - Your Source For Python Development Services'
|
intro += '\nSponsored by Orbtech - Your Source For Python Development Services'
|
||||||
self.CreateStatusBar()
|
self.CreateStatusBar()
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
self.SetStatusText(intro.replace('\n', ', '))
|
||||||
if wxPlatform == '__WXMSW__':
|
if wxPlatform == '__WXMSW__':
|
||||||
|
Reference in New Issue
Block a user