📄 shell.py
字号:
import __builtin__
__builtin__.close = __builtin__.exit = __builtin__.quit = \
'Click on the close button to leave the application.'
def quit(self):
"""Quit the application."""
# XXX Good enough for now but later we want to send a close event.
# In the close event handler we can make sure they want to
# quit. Other applications, like PythonCard, may choose to
# hide rather than quit so we should just post the event and
# let the surrounding app decide what it wants to do.
self.write('Click on the close button to leave the application.')
def setLocalShell(self):
"""Add 'shell' to locals as reference to ShellFacade instance."""
self.interp.locals['shell'] = ShellFacade(other=self)
def execStartupScript(self, startupScript):
"""Execute the user's PYTHONSTARTUP script if they have one."""
if startupScript and os.path.isfile(startupScript):
text = 'Startup script executed: ' + startupScript
self.push('print %r; execfile(%r)' % (text, startupScript))
self.interp.startupScript = startupScript
else:
self.push('')
def about(self):
"""Display information about Py."""
text = """
Author: %r
Py Version: %s
Py Shell Revision: %s
Py Interpreter Revision: %s
Python Version: %s
wxPython Version: %s
wxPython PlatformInfo: %s
Platform: %s""" % \
(__author__, VERSION, self.revision, self.interp.revision,
sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo),
sys.platform)
self.write(text.strip())
def OnChar(self, event):
"""Keypress event handler.
Only receives an event if OnKeyDown calls event.Skip() for the
corresponding event."""
if self.noteMode:
event.Skip()
return
# Prevent modification of previously submitted
# commands/responses.
if not self.CanEdit():
return
key = event.KeyCode()
currpos = self.GetCurrentPos()
stoppos = self.promptPosEnd
# Return (Enter) needs to be ignored in this handler.
if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
pass
elif key in self.autoCompleteKeys:
# Usually the dot (period) key activates auto completion.
# Get the command between the prompt and the cursor. Add
# the autocomplete character to the end of the command.
if self.AutoCompActive():
self.AutoCompCancel()
command = self.GetTextRange(stoppos, currpos) + chr(key)
self.write(chr(key))
if self.autoComplete:
self.autoCompleteShow(command)
elif key == ord('('):
# The left paren activates a call tip and cancels an
# active auto completion.
if self.AutoCompActive():
self.AutoCompCancel()
# Get the command between the prompt and the cursor. Add
# the '(' to the end of the command.
self.ReplaceSelection('')
command = self.GetTextRange(stoppos, currpos) + '('
self.write('(')
self.autoCallTipShow(command, self.GetCurrentPos() == self.GetTextLength())
else:
# Allow the normal event handling to take place.
event.Skip()
def OnKeyDown(self, event):
"""Key down event handler."""
key = event.KeyCode()
# If the auto-complete window is up let it do its thing.
if self.AutoCompActive():
event.Skip()
return
# Prevent modification of previously submitted
# commands/responses.
controlDown = event.ControlDown()
altDown = event.AltDown()
shiftDown = event.ShiftDown()
currpos = self.GetCurrentPos()
endpos = self.GetTextLength()
selecting = self.GetSelectionStart() != self.GetSelectionEnd()
if controlDown and shiftDown and key in (ord('F'), ord('f')):
li = self.GetCurrentLine()
m = self.MarkerGet(li)
if m & 1<<0:
startP = self.PositionFromLine(li)
self.MarkerDelete(li, 0)
maxli = self.GetLineCount()
li += 1 # li stayed visible as header-line
li0 = li
while li<maxli and self.GetLineVisible(li) == 0:
li += 1
endP = self.GetLineEndPosition(li-1)
self.ShowLines(li0, li-1)
self.SetSelection( startP, endP ) # select reappearing text to allow "hide again"
return
startP,endP = self.GetSelection()
endP-=1
startL,endL = self.LineFromPosition(startP), self.LineFromPosition(endP)
if endL == self.LineFromPosition(self.promptPosEnd): # never hide last prompt
endL -= 1
m = self.MarkerGet(startL)
self.MarkerAdd(startL, 0)
self.HideLines(startL+1,endL)
self.SetCurrentPos( startP ) # to ensure caret stays visible !
if key == wx.WXK_F12: #seb
if self.noteMode:
# self.promptPosStart not used anyway - or ?
self.promptPosEnd = self.PositionFromLine( self.GetLineCount()-1 ) + len(str(sys.ps1))
self.GotoLine(self.GetLineCount())
self.GotoPos(self.promptPosEnd)
self.prompt() #make sure we have a prompt
self.SetCaretForeground("black")
self.SetCaretWidth(1) #default
self.SetCaretPeriod(500) #default
else:
self.SetCaretForeground("red")
self.SetCaretWidth(4)
self.SetCaretPeriod(0) #steady
self.noteMode = not self.noteMode
return
if self.noteMode:
event.Skip()
return
# Return (Enter) is used to submit a command to the
# interpreter.
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 in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
self.OnShowCompHistory()
# 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(']'), wx.WXK_NUMPAD_ADD):
dispatcher.send(signal='FontIncrease')
# Decrease font size.
elif controlDown and key in (ord('['), wx.WXK_NUMPAD_SUBTRACT):
dispatcher.send(signal='FontDecrease')
# Default font size.
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):
self.Cut()
# Copy to the clipboard.
elif controlDown and not shiftDown \
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):
self.CopyWithPrompts()
# Copy to the clipboard, including prefixed prompts.
elif altDown and not controlDown \
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
if currpos > home:
self.SetCurrentPos(home)
if not selecting and not shiftDown:
self.SetAnchor(home)
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:
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."""
#copy from history
his = self.history[:]
#put together in one string
joined = " ".join (his)
import re
#sort out only "good" words
newlist = re.split("[ \.\[\]=}(\)\,0-9\"]", joined)
#length > 1 (mix out "trash")
thlist = []
for i in newlist:
if len (i) > 1:
thlist.append (i)
#unique (no duplicate words
#oneliner from german python forum => unique list
unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]]
#sort lowercase
unlist.sort(lambda a, b: cmp(a.lower(), b.lower()))
#this is more convenient, isn't it?
self.AutoCompSetIgnoreCase(True)
#join again together in a string
stringlist = " ".join(unlist)
#pos von 0 noch ausrechnen
#how big is the offset?
cpos = self.GetCurrentPos() - 1
while chr (self.GetCharAt (cpos)).isalnum():
cpos -= 1
#the most important part
self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -