dialog.Destroy()
+ def OnHelp(self, event):
+ """Show a help dialog."""
+ frame.ShellFrameMixin.OnHelp(self, event)
+
+
def LoadSettings(self):
if self.config is not None:
frame.ShellFrameMixin.LoadSettings(self)
frame.Frame.LoadSettings(self, self.config)
self.shell.LoadSettings(self.config)
- def SaveSettings(self):
+ def SaveSettings(self, force=False):
if self.config is not None:
frame.ShellFrameMixin.SaveSettings(self)
- if self.autoSaveSettings:
+ if self.autoSaveSettings or force:
frame.Frame.SaveSettings(self, self.config)
self.shell.SaveSettings(self.config)
def DoSaveSettings(self):
if self.config is not None:
- self.SaveSettings()
+ self.SaveSettings(force=True)
self.config.Flush()
Ctrl+= Default font size.
Ctrl-Space Show Auto Completion.
Ctrl-Alt-Space Show Call Tip.
-Alt+Shift+C Clear Screen.
Shift+Enter Complete Text from History.
-Ctrl+F Search (backwards) TODO: regexp-wholeWords-...
-Ctrl+G Search next
+Ctrl+F Search
+F3 Search next
Ctrl+H "hide" lines containing selection / "unhide"
F12 on/off "free-edit" mode
"""
d = self.__dict__
d['other'] = other
d['helpText'] = HELP_TEXT
+ d['this'] = other.this
def help(self):
"""Display some useful information about how to use the shell."""
wx.CallAfter(self.ScrollToLine, 0)
+ def clearHistory(self):
+ self.history = []
+ self.historyIndex = -1
+ dispatcher.send(signal="Shell.clearHistory")
+
def destroy(self):
del self.interp
currpos = self.GetCurrentPos()
stoppos = self.promptPosEnd
# Return (Enter) needs to be ignored in this handler.
- if key == wx.WXK_RETURN:
+ if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
pass
elif key in self.autoCompleteKeys:
# Usually the dot (period) key activates auto completion.
if self.AutoCompActive():
event.Skip()
return
+
# Prevent modification of previously submitted
# commands/responses.
controlDown = event.ControlDown()
endpos = self.GetTextLength()
selecting = self.GetSelectionStart() != self.GetSelectionEnd()
- if controlDown and key in (ord('H'), ord('h')):
+ if controlDown and shiftDown and key in (ord('F'), ord('f')):
li = self.GetCurrentLine()
m = self.MarkerGet(li)
if m & 1<<0:
# Return (Enter) is used to submit a command to the
# interpreter.
- if (not controlDown and not shiftDown and not altDown) and key == wx.WXK_RETURN:
+ if (not controlDown and not shiftDown and not altDown) and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
if self.CallTipActive():
self.CallTipCancel()
self.processLine()
- #Complete Text (from already typed words)
- elif shiftDown and key == wx.WXK_RETURN:
+
+ # Complete Text (from already typed words)
+ elif shiftDown and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
self.OnShowCompHistory()
- # Ctrl+Return (Cntrl+Enter) is used to insert a line break.
- elif controlDown and key == wx.WXK_RETURN:
+
+ # Ctrl+Return (Ctrl+Enter) is used to insert a line break.
+ elif controlDown and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
if self.CallTipActive():
self.CallTipCancel()
if currpos == endpos:
self.processLine()
else:
self.insertLineBreak()
+
# Let Ctrl-Alt-* get handled normally.
elif controlDown and altDown:
event.Skip()
+
# Clear the current, unexecuted command.
elif key == wx.WXK_ESCAPE:
if self.CallTipActive():
event.Skip()
else:
self.clearCommand()
+
+ # Clear the current command
+ elif key == wx.WXK_BACK and controlDown and shiftDown:
+ self.clearCommand()
+
# Increase font size.
- elif controlDown and key in (ord(']'),):
+ elif controlDown and key in (ord(']'), wx.WXK_NUMPAD_ADD):
dispatcher.send(signal='FontIncrease')
+
# Decrease font size.
- elif controlDown and key in (ord('['),):
+ elif controlDown and key in (ord('['), wx.WXK_NUMPAD_SUBTRACT):
dispatcher.send(signal='FontDecrease')
+
# Default font size.
- elif controlDown and key in (ord('='),):
+ elif controlDown and key in (ord('='), wx.WXK_NUMPAD_DIVIDE):
dispatcher.send(signal='FontDefault')
+
# Cut to the clipboard.
elif (controlDown and key in (ord('X'), ord('x'))) \
- or (shiftDown and key == wx.WXK_DELETE):
+ or (shiftDown and key == wx.WXK_DELETE):
self.Cut()
+
# Copy to the clipboard.
elif controlDown and not shiftDown \
- and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
self.Copy()
+
# Copy to the clipboard, including prompts.
elif controlDown and shiftDown \
- and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
self.CopyWithPrompts()
+
# Copy to the clipboard, including prefixed prompts.
elif altDown and not controlDown \
- and key in (ord('C'), ord('c'), wx.WXK_INSERT):
+ and key in (ord('C'), ord('c'), wx.WXK_INSERT):
self.CopyWithPromptsPrefixed()
+
# Home needs to be aware of the prompt.
elif key == wx.WXK_HOME:
home = self.promptPosEnd
self.EnsureCaretVisible()
else:
event.Skip()
+
#
# The following handlers modify text, so we need to see if
# there is a selection that includes text prior to the prompt.
# Don't modify a selection with text prior to the prompt.
elif selecting and key not in NAVKEYS and not self.CanEdit():
pass
+
# Paste from the clipboard.
elif (controlDown and not shiftDown and key in (ord('V'), ord('v'))) \
or (shiftDown and not controlDown and key == wx.WXK_INSERT):
self.Paste()
+
+ # manually invoke AutoComplete and Calltips
elif controlDown and key == wx.WXK_SPACE:
- """AutoComplete and Calltips manually."""
- self.OnCallTipAutoCompleteManually (shiftDown)
+ self.OnCallTipAutoCompleteManually(shiftDown)
+
# 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 == wx.WXK_UP) \
or (altDown and key in (ord('P'), ord('p'))):
self.OnHistoryReplace(step=+1)
+
# Replace with the next command from the history buffer.
elif (controlDown and key == wx.WXK_DOWN) \
or (altDown and key in (ord('N'), ord('n'))):
self.OnHistoryReplace(step=-1)
+
# Insert the previous command from the history buffer.
elif (shiftDown and key == wx.WXK_UP) and self.CanEdit():
self.OnHistoryInsert(step=+1)
+
# Insert the next command from the history buffer.
elif (shiftDown and key == wx.WXK_DOWN) and self.CanEdit():
self.OnHistoryInsert(step=-1)
+
# Search up the history for the text in front of the cursor.
elif key == wx.WXK_F8:
self.OnHistorySearch()
+
# Don't backspace over the latest non-continuation prompt.
elif key == wx.WXK_BACK:
if selecting and self.CanEdit():
event.Skip()
elif currpos > self.promptPosEnd:
event.Skip()
+
# Only allow these keys after the latest prompt.
elif key in (wx.WXK_TAB, wx.WXK_DELETE):
if self.CanEdit():
event.Skip()
+
# Don't toggle between insert mode and overwrite mode.
elif key == wx.WXK_INSERT:
pass
+
# Don't allow line deletion.
elif controlDown and key in (ord('L'), ord('l')):
pass
+
# Don't allow line transposition.
elif controlDown and key in (ord('T'), ord('t')):
pass
+
# Basic navigation keys should work anywhere.
elif key in NAVKEYS:
event.Skip()
+
# Protect the readonly portion of the shell.
elif not self.CanEdit():
pass
+
else:
event.Skip()
+
def OnShowCompHistory(self):
"""Show possible autocompletion Words from already typed words."""
if command != '' \
and (len(self.history) == 0 or command != self.history[0]):
self.history.insert(0, command)
+ dispatcher.send(signal="Shell.addHistory", command=command)
def write(self, text):
"""Display text in the shell.
ctindex = ctips.find ('(')
if ctindex != -1 and not self.CallTipActive():
#insert calltip, if current pos is '(', otherwise show it only
- self.autoCallTipShow(ctips[:ctindex + 1], \
- self.GetCharAt(currpos - 1) == ord('(') and self.GetCurrentPos() == self.GetTextLength(),\
+ self.autoCallTipShow(ctips[:ctindex + 1],
+ self.GetCharAt(currpos - 1) == ord('(') and self.GetCurrentPos() == self.GetTextLength(),
True)
self.write(command)
wx.TheClipboard.Close()
+
def PasteAndRun(self):
"""Replace selection with clipboard contents, run commands."""
+ text = ''
if wx.TheClipboard.Open():
- ps1 = str(sys.ps1)
- ps2 = str(sys.ps2)
if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
data = wx.TextDataObject()
if wx.TheClipboard.GetData(data):
- endpos = self.GetTextLength()
- self.SetCurrentPos(endpos)
- startpos = self.promptPosEnd
- self.SetSelection(startpos, endpos)
- self.ReplaceSelection('')
text = data.GetText()
- text = text.lstrip()
- text = self.fixLineEndings(text)
- text = self.lstripPrompt(text)
- text = text.replace(os.linesep + ps1, '\n')
- text = text.replace(os.linesep + ps2, '\n')
- text = text.replace(os.linesep, '\n')
- lines = text.split('\n')
- commands = []
- command = ''
- for line in lines:
- if line.strip() == ps2.strip():
- # If we are pasting from something like a
- # web page that drops the trailing space
- # from the ps2 prompt of a blank line.
- line = ''
- 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 + ps2)
- self.write(command)
- self.processLine()
wx.TheClipboard.Close()
+ if text:
+ self.Execute(text)
+
+
+ def Execute(self, text):
+ """Replace selection with text and run commands."""
+ ps1 = str(sys.ps1)
+ ps2 = str(sys.ps2)
+ endpos = self.GetTextLength()
+ self.SetCurrentPos(endpos)
+ startpos = self.promptPosEnd
+ self.SetSelection(startpos, endpos)
+ self.ReplaceSelection('')
+ text = text.lstrip()
+ text = self.fixLineEndings(text)
+ text = self.lstripPrompt(text)
+ text = text.replace(os.linesep + ps1, '\n')
+ text = text.replace(os.linesep + ps2, '\n')
+ text = text.replace(os.linesep, '\n')
+ lines = text.split('\n')
+ commands = []
+ command = ''
+ for line in lines:
+ if line.strip() == ps2.strip():
+ # If we are pasting from something like a
+ # web page that drops the trailing space
+ # from the ps2 prompt of a blank line.
+ line = ''
+ lstrip = line.lstrip()
+ if line.strip() != '' and lstrip == line and \
+ lstrip[:4] not in ['else','elif'] and \
+ lstrip[:6] != 'except':
+ # 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 + ps2)
+ self.write(command)
+ self.processLine()
+
def wrap(self, wrap=True):
"""Sets whether text is word wrapped."""