📄 shell.py
字号:
def clearCommand(self):
"""Delete the current, unexecuted command."""
startpos = self.promptPosEnd
endpos = self.GetTextLength()
self.SetSelection(startpos, endpos)
self.ReplaceSelection('')
self.more = False
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."""
ps2 = str(sys.ps2)
self.ReplaceSelection('')
newindex = self.historyIndex + step
if -1 <= newindex <= len(self.history):
self.historyIndex = newindex
if 0 <= newindex <= len(self.history)-1:
command = self.history[self.historyIndex]
command = command.replace('\n', os.linesep + ps2)
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()
self.SetSelection(endpos, startpos)
def OnHistorySearch(self):
"""Search up the history buffer for the text in front of the cursor."""
if not self.CanEdit():
return
startpos = self.GetCurrentPos()
# The text up to the cursor is what we search for.
numCharsAfterCursor = self.GetTextLength() - startpos
searchText = self.getCommand(rstrip=False)
if numCharsAfterCursor > 0:
searchText = searchText[:-numCharsAfterCursor]
if not searchText:
return
# Search upwards from the current history position and loop
# back to the beginning if we don't find anything.
if (self.historyIndex <= -1) \
or (self.historyIndex >= len(self.history)-2):
searchOrder = range(len(self.history))
else:
searchOrder = range(self.historyIndex+1, len(self.history)) + \
range(self.historyIndex)
for i in searchOrder:
command = self.history[i]
if command[:len(searchText)] == searchText:
# Replace the current selection with the one we found.
self.ReplaceSelection(command[len(searchText):])
endpos = self.GetCurrentPos()
self.SetSelection(endpos, startpos)
# We've now warped into middle of the history.
self.historyIndex = i
break
def setStatusText(self, text):
"""Display status information."""
# This method will likely be replaced by the enclosing app to
# do something more interesting, like write to a status bar.
print text
def insertLineBreak(self):
"""Insert a new line break."""
if self.CanEdit():
self.write(os.linesep)
self.more = True
self.prompt()
def processLine(self):
"""Process the line of text at which the user hit Enter."""
# The user hit ENTER and we need to decide what to do. They
# could be sitting on any line in the shell.
thepos = self.GetCurrentPos()
startpos = self.promptPosEnd
endpos = self.GetTextLength()
ps2 = str(sys.ps2)
# If they hit RETURN inside the current command, execute the
# command.
if self.CanEdit():
self.SetCurrentPos(endpos)
self.interp.more = False
command = self.GetTextRange(startpos, endpos)
lines = command.split(os.linesep + ps2)
lines = [line.rstrip() for line in lines]
command = '\n'.join(lines)
if self.reader.isreading:
if not command:
# Match the behavior of the standard Python shell
# when the user hits return without entering a
# value.
command = '\n'
self.reader.input = command
self.write(os.linesep)
else:
self.push(command)
wx.FutureCall(1, self.EnsureCaretVisible)
# Or replace the current command with the other command.
else:
# If the line contains a command (even an invalid one).
if self.getCommand(rstrip=False):
command = self.getMultilineCommand()
self.clearCommand()
self.write(command)
# Otherwise, put the cursor back where we started.
else:
self.SetCurrentPos(thepos)
self.SetAnchor(thepos)
def getMultilineCommand(self, rstrip=True):
"""Extract a multi-line command from the editor.
The command may not necessarily be valid Python syntax."""
# XXX Need to extract real prompts here. Need to keep track of
# the prompt every time a command is issued.
ps1 = str(sys.ps1)
ps1size = len(ps1)
ps2 = str(sys.ps2)
ps2size = len(ps2)
# This is a total hack job, but it works.
text = self.GetCurLine()[0]
line = self.GetCurrentLine()
while text[:ps2size] == ps2 and line > 0:
line -= 1
self.GotoLine(line)
text = self.GetCurLine()[0]
if text[:ps1size] == ps1:
line = self.GetCurrentLine()
self.GotoLine(line)
startpos = self.GetCurrentPos() + ps1size
line += 1
self.GotoLine(line)
while self.GetCurLine()[0][:ps2size] == ps2:
line += 1
self.GotoLine(line)
stoppos = self.GetCurrentPos()
command = self.GetTextRange(startpos, stoppos)
command = command.replace(os.linesep + ps2, '\n')
command = command.rstrip()
command = command.replace('\n', os.linesep + ps2)
else:
command = ''
if rstrip:
command = command.rstrip()
return command
def getCommand(self, text=None, rstrip=True):
"""Extract a command from text which may include a shell prompt.
The command may not necessarily be valid Python syntax."""
if not text:
text = self.GetCurLine()[0]
# Strip the prompt off the front leaving just the command.
command = self.lstripPrompt(text)
if command == text:
command = '' # Real commands have prompts.
if rstrip:
command = command.rstrip()
return command
def lstripPrompt(self, text):
"""Return text without a leading prompt."""
ps1 = str(sys.ps1)
ps1size = len(ps1)
ps2 = str(sys.ps2)
ps2size = len(ps2)
# Strip the prompt off the front of text.
if text[:ps1size] == ps1:
text = text[ps1size:]
elif text[:ps2size] == ps2:
text = text[ps2size:]
return text
def push(self, command, silent = False):
"""Send command to the interpreter for execution."""
if not silent:
self.write(os.linesep)
busy = wx.BusyCursor()
self.waiting = True
self.more = self.interp.push(command)
self.waiting = False
del busy
if not self.more:
self.addHistory(command.rstrip())
if not silent:
self.prompt()
def addHistory(self, command):
"""Add command to the command history."""
# Reset the history position.
self.historyIndex = -1
# Insert this command into the history, unless it's a blank
# line or the same as the last command.
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.
Replace line endings with OS-specific endings."""
text = self.fixLineEndings(text)
self.AddText(text)
self.EnsureCaretVisible()
def fixLineEndings(self, text):
"""Return text with line endings replaced by OS-specific endings."""
lines = text.split('\r\n')
for l in range(len(lines)):
chunks = lines[l].split('\r')
for c in range(len(chunks)):
chunks[c] = os.linesep.join(chunks[c].split('\n'))
lines[l] = os.linesep.join(chunks)
text = os.linesep.join(lines)
return text
def prompt(self):
"""Display proper prompt for the context: ps1, ps2 or ps3.
If this is a continuation line, autoindent as necessary."""
isreading = self.reader.isreading
skip = False
if isreading:
prompt = str(sys.ps3)
elif self.more:
prompt = str(sys.ps2)
else:
prompt = str(sys.ps1)
pos = self.GetCurLine()[1]
if pos > 0:
if isreading:
skip = True
else:
self.write(os.linesep)
if not self.more:
self.promptPosStart = self.GetCurrentPos()
if not skip:
self.write(prompt)
if not self.more:
self.promptPosEnd = self.GetCurrentPos()
# Keep the undo feature from undoing previous responses.
self.EmptyUndoBuffer()
# XXX Add some autoindent magic here if more.
if self.more:
self.write(' '*4) # Temporary hack indentation.
self.EnsureCaretVisible()
self.ScrollToColumn(0)
def readline(self):
"""Replacement for stdin.readline()."""
input = ''
reader = self.reader
reader.isreading = True
self.prompt()
try:
while not reader.input:
wx.YieldIfNeeded()
input = reader.input
finally:
reader.input = ''
reader.isreading = False
input = str(input) # In case of Unicode.
return input
def readlines(self):
"""Replacement for stdin.readlines()."""
lines = []
while lines[-1:] != ['\n']:
lines.append(self.readline())
return lines
def raw_input(self, prompt=''):
"""Return string based on user input."""
if prompt:
self.write(prompt)
return self.readline()
def ask(self, prompt='Please enter your response:'):
"""Get response from the user using a dialog box."""
dialog = wx.TextEntryDialog(None, prompt,
'Input Dialog (Raw)', '')
try:
if dialog.ShowModal() == wx.ID_OK:
text = dialog.GetValue()
return text
finally:
dialog.Destroy()
return ''
def pause(self):
"""Halt execution pending a response from the user."""
self.ask('Press enter to continue:')
def clear(self):
"""Delete all text from the shell."""
self.ClearAll()
def run(self, command, prompt=True, verbose=True):
"""Execute command as if it was typed in directly.
>>> shell.run('print "this"')
>>> print "this"
this
>>>
"""
# Go to the very bottom of the text.
endpos = self.GetTextLength()
self.SetCurrentPos(endpos)
command = command.rstrip()
if prompt: self.prompt()
if verbose: self.write(command)
self.push(command)
def runfile(self, filename):
"""Execute all commands in file as if they were typed into the
shell."""
file = open(filename)
try:
self.prompt()
for command in file.readlines():
if command[:6] == 'shell.':
# Run shell methods silently.
self.run(command, prompt=False, verbose=False)
else:
self.run(command, prompt=False, verbose=True)
finally:
file.close()
def autoCompleteShow(self, command, offset = 0):
"""Display auto-completion popup list."""
self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
list = self.interp.getAutoCompleteList(command,
includeMagic=self.autoCompleteIncludeMagic,
includeSingle=self.autoCompleteIncludeSingle,
includeDouble=self.autoCompleteIncludeDouble)
if list:
options = ' '.join(list)
#offset = 0
self.AutoCompShow(offset, options)
def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False):
"""Display argument spec and docstring in a popup window."""
if self.CallTipActive():
self.CallTipCancel()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -