# Programmer: Daniel Pozmanter
# E-mail: drpython@bluebottle.com
# Note: You must reply to the verification e-mail to get through.
#
# Copyright 2003-2005 Daniel Pozmanter
#
# Distributed under the terms of the GPL (GNU Public License)
#
# DrPython is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#The Prompt
import sys, os.path, re, traceback
import wx
import wx.stc
from drProperty import *
import drEncoding
import drKeywords
import drSTC
reserved = [wx.stc.STC_CMD_NEWLINE, wx.stc.STC_CMD_CHARLEFT,
wx.stc.STC_CMD_CHARRIGHT, wx.stc.STC_CMD_LINEUP, wx.stc.STC_CMD_LINEDOWN,
wx.stc.STC_CMD_DELETEBACK, wx.stc.STC_CMD_HOME]
class DrPrompt(drSTC.DrStyledTextControl):
def __init__(self, parent, id, grandparent):
drSTC.DrStyledTextControl.__init__(self, parent, id, grandparent)
#Maximum Number of Commands to Keep Track of in Prompt
self.MAX_PROMPT_COMMANDS = 25
self.CommandArray = []
self.CommandArrayPos = -1
self.IsAPrompt = True
self.editpoint = 0
#Process
self.process = None
self.pid = -1
self.pythonintepreter = 0
self.commandinprogress = False
#Goto Traceback:
self.reTFilename = re.compile('\".*\"')
self.reTLinenumber = re.compile('line.*\d')
self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified, id=id)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
self.Bind(wx.EVT_UPDATE_UI, self.RunCheck, id=id)
self.Bind(wx.EVT_IDLE, self.OnIdle)
self.Bind(wx.EVT_LEFT_DCLICK, self.OnGotoTraceback)
def _addoutput(self, checkinput=True):
wx.Usleep(25)
a = ''
if checkinput and self.process.IsInputAvailable():
a = self._getoutput(self.inputstream)
if self.process.IsErrorAvailable():
a += self._getoutput(self.errorstream)
self.AddText(a)
return a
def _getoutput(self, targetstream):
#used to get the output of a command in the prompt, and immediately add it to the prompt.
added = False
while (not added):
if targetstream.CanRead():
text = targetstream.read()
added = True
return text
def _waitforoutput(self, targetoutput):
'''
Dangerous! Only use this if you know what you are doing.
Waits for output that has not yet appeared to show up
in either the stdout or stderr of the current process.
'''
text = ''
while True:
if text.find(targetoutput) > -1:
return
text = self._addoutput()
def AddEncodedText(self, text):
try:
etext = drEncoding.EncodeText(self.grandparent, text)
wx.stc.StyledTextCtrl.AddText(self, etext)
except:
print 'Error Encoding Text'
def AddText(self, text):
ro = self.GetReadOnly()
self.SetReadOnly(0)
self.AddEncodedText(text)
self.SetReadOnly(ro)
def ExecuteCommands(self, text):
'''Executes Commands Separated by '\n' '''
if len(text) == 0:
return
self._addoutput()
self.commandinprogress = True
text = text.rstrip()
commands = text.split('\n')
for command in commands:
command += '\n'
self._addoutput()
try:
etext = drEncoding.EncodeText(self.grandparent, command)
except:
print 'Error Encoding Text'
return
self.outputstream.write(etext)
self.GotoPos(self.GetLength())
wx.stc.StyledTextCtrl.AddText(self, etext)
self._addoutput((len(command) > 1))
self.editpoint = self.GetLength()
self.ScrollToLine(self.LineFromPosition(self.editpoint))
self.commandinprogress = False
def GetEditPoint(self):
return self.editpoint
def InsertEncodedText(self, pos, text):
try:
etext = drEncoding.EncodeText(self.grandparent, text)
wx.stc.StyledTextCtrl.InsertText(self, pos, etext)
except:
print 'Error Encoding Text'
def InsertText(self, pos, text):
ro = self.GetReadOnly()
self.SetReadOnly(0)
self.InsertEncodedText(pos, text)
self.SetReadOnly(ro)
def OnIdle(self, event):
if (self.process is not None) and (not self.commandinprogress):
if self.inputstream.CanRead():
text = self.inputstream.read()
self.AddEncodedText(text)
self.EmptyUndoBuffer()
self.editpoint = self.GetLength()
self.GotoPos(self.editpoint)
self.ScrollToLine(self.LineFromPosition(self.editpoint))
if self.errorstream.CanRead():
text = self.errorstream.read()
self.AddEncodedText(text)
self.EmptyUndoBuffer()
self.editpoint = self.GetLength()
self.GotoPos(self.editpoint)
self.ScrollToLine(self.LineFromPosition(self.editpoint))
def OnGotoTraceback(self, event):
line = self.GetLine(self.GetCurrentLine())
fn = self.reTFilename.search(line)
ln = self.reTLinenumber.search(line)
if (fn is not None) and (ln is not None):
filename = fn.group().strip('\"').replace('\\', '/')
try:
linenumber = int(ln.group().strip('line ')) - 1
except:
linenumber = 0
if os.path.exists(filename):
alreadyopen = map(lambda x: x.filename, self.grandparent.txtDocumentArray)
if filename in alreadyopen:
i = alreadyopen.index(filename)
self.grandparent.setDocumentTo(i)
else:
self.grandparent.OpenFile(filename, (len(self.grandparent.txtDocument.filename) > 0))
self.grandparent.txtDocument.ScrollToLine(linenumber)
self.grandparent.txtDocument.GotoLine(linenumber)
self.grandparent.txtDocument.EnsureCaretVisible()
self.grandparent.txtDocument.SetFocus()
def OnKeyDown(self, event):
if self.pid == -1:
return
result = self.grandparent.RunShortcuts(event)
if result > -1:
pos = self.GetCurrentPos()
if (not self.pid == -1):
if (pos >= self.editpoint) and (result == wx.stc.STC_CMD_NEWLINE):
self.commandinprogress = True
text = self.GetTextRange(self.editpoint, self.GetLength())
l = len(self.CommandArray)
if (l < self.MAX_PROMPT_COMMANDS):
if text in self.CommandArray:
self.CommandArray.pop(self.CommandArray.index(text))
self.CommandArray.insert(0, text)
self.CommandArrayPos = -1
else:
self.CommandArray.pop()
self.CommandArray.insert(0, text)
self.CommandArrayPos = -1
if len(text) == 0:
text = '\n'
self.GotoPos(self.GetLength())
self.AddText(self.GetEndOfLineCharacter())
elif text[-1] != '\n':
text += '\n'
self.GotoPos(self.GetLength())
self.AddText(self.GetEndOfLineCharacter())
try:
etext = drEncoding.EncodeText(self.grandparent, text)
except:
print 'Error Encoding Text'
return
self.outputstream.write(etext)
self.GotoPos(self.GetLength())
self._addoutput()
self.editpoint = self.GetLength()
self.ScrollToLine(self.LineFromPosition(self.editpoint))
self.commandinprogress = False
elif (result == wx.stc.STC_CMD_LINEUP):
l = len(self.CommandArray)
if (len(self.CommandArray) > 0):
if (self.CommandArrayPos + 1) < l:
self.GotoPos(self.editpoint)
self.SetTargetStart(self.editpoint)
self.SetTargetEnd(self.GetLength())
self.CommandArrayPos = self.CommandArrayPos + 1
self.ReplaceTarget(self.CommandArray[self.CommandArrayPos])
elif (result == wx.stc.STC_CMD_LINEDOWN):
if (len(self.CommandArray) > 0):
self.GotoPos(self.editpoint)
self.SetTargetStart(self.editpoint)
self.SetTargetEnd(self.GetLength())
if (self.CommandArrayPos - 1) > -1:
self.CommandArrayPos = self.CommandArrayPos - 1
self.ReplaceTarget(self.CommandArray[self.CommandArrayPos])
else:
if (self.CommandArrayPos - 1) > -2:
self.CommandArrayPos = self.CommandArrayPos - 1
self.ReplaceTarget("")
if (((pos > self.editpoint) and (result in reserved)) or
(pos >= self.editpoint) and (result == wx.stc.STC_CMD_CHARRIGHT)):
event.Skip()
def OnKeyUp(self, event):
if self.pid == -1:
event.Skip()
return
keycode = event.GetKeyCode()
#franz: pos was not used
if keycode == wx.WXK_HOME:
if (self.GetCurrentPos() < self.editpoint):
self.GotoPos(self.editpoint)
return
elif keycode == wx.WXK_PRIOR:
if (self.GetCurrentPos() < self.editpoint):
self.GotoPos(self.editpoint)
return
event.Skip()
def OnModified(self, event):
if not (self.grandparent.prefs.promptwordwrap):
ll = self.TextWidth(wx.stc.STC_STYLE_DEFAULT, "OOO")
x = 0
spaces = ""
while (x < self.grandparent.prefs.prompttabwidth):
spaces = spaces + " "
x = x + 1
current_width = self.GetScrollWidth()
line = self.GetCurLine()[0].replace('\t', spaces)
actual_width = self.TextWidth(wx.stc.STC_STYLE_DEFAULT, line)
if (current_width < actual_width):
self.SetScrollWidth(actual_width + ll)
def RunCheck(self, event):
if (self.GetCurrentPos() < self.editpoint) or (self.pid == -1):
self.SetReadOnly(1)
else:
self.SetReadOnly(0)
def SetupPrefsPrompt(self, notmdiupdate = 1):
self.SetEndAtLastLine(not self.grandparent.prefs.promptscrollextrapage)
if notmdiupdate:
self.SetViewWhiteSpace(self.grandparent.prefs.promptwhitespaceisvisible)
self.SetViewEOL(self.grandparent.prefs.promptwhitespaceisvisible and self.grandparent.prefs.vieweol)
if (self.grandparent.prefs.promptwordwrap):
self.SetWrapMode(wx.stc.STC_WRAP_WORD)
else:
self.SetWrapMode(wx.stc.STC_WRAP_NONE)
if (self.grandparent.prefs.prompteolmode == 1):
self.SetEOLMode(wx.stc.STC_EOL_CRLF)
elif (self.grandparent.prefs.prompteolmode == 2):
self.SetEOLMode(wx.stc.STC_EOL_CR)
else:
self.SetEOLMode(wx.stc.STC_EOL_LF)
self.SetTabWidth(self.grandparent.prefs.prompttabwidth)
self.SetUseTabs(self.grandparent.prefs.promptusetabs)
self.SetMarginWidth(1, self.grandparent.prefs.promptmarginwidth)
if self.grandparent.prefs.promptusestyles:
self.SetKeyWords(0, drKeywords.GetKeyWords(0))
self.SetLexer(drKeywords.GetLexer(0))
self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, self.grandparent.prefs.txtPromptStyleDictionary[0])
self.StyleClearAll()
self.StartStyling(0, 0xff)
self.SetCaretWidth(self.grandparent.prefs.promptcaretwidth)
self.SetCaretForeground(self.grandparent.prefs.txtPromptStyleDictionary[15])
if (self.grandparent.prefs.promptusestyles < 2):
self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER, self.grandparent.prefs.txtPromptStyleDictionary[1])
self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT, self.grandparent.prefs.txtPromptStyleDictionary[2])
self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD, self.grandparent.prefs.txtPromptStyleDictionary[3])
self.StyleSetSpec(wx.stc.STC_P_CHARACTER, self.grandparent.prefs.txtPromptStyleDictionary[4])
self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, self.grandparent.prefs.txtPromptStyleDictionary[5])
self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, self.grandparent.prefs.txtPromptStyleDictionary[6])
self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, self.grandparent.prefs.txtPromptStyleDictionary[7])
self.StyleSetSpec(wx.stc.STC_P_DEFNAME, self.grandparent.prefs.txtPromptStyleDictionary[8])
self.StyleSetSpec(wx.stc.STC_P_WORD, self.grandparent.prefs.txtPromptStyleDictionary[9])
self.StyleSetSpec(wx.stc.STC_P_NUMBER, self.grandparent.prefs.txtPromptStyleDictionary[10])
self.StyleSetSpec(wx.stc.STC_P_OPERATOR, self.grandparent.prefs.txtPromptStyleDictionary[11])
self.StyleSetSpec(wx.stc.STC_P_STRING, self.grandparent.prefs.txtPromptStyleDictionary[12])
self.StyleSetSpec(wx.stc.STC_P_STRINGEOL, self.grandparent.prefs.txtPromptStyleDictionary[13])
self.StyleSetSpec(wx.stc.STC_P_TRIPLE, self.grandparent.prefs.txtPromptStyleDictionary[14])
self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, self.grandparent.prefs.txtPromptStyleDictionary[14])
self.SetSelForeground(1, getStyleProperty("fore", self.grandparent.prefs.txtPromptStyleDictionary[16]))
self.SetSelBackground(1, getStyleProperty("back", self.grandparent.prefs.txtPromptStyleDictionary[16]))
def SetText(self, text):
ro = self.GetReadOnly()
self.SetReadOnly(0)
wx.stc.StyledTextCtrl.SetText(self, text)
self.SetReadOnly(ro)
def SetSelectedText(self, text):
ro = self.GetReadOnly()
self.SetReadOnly(0)
self.SetTargetStart(self.GetSelectionStart())
self.SetTargetEnd(self.GetSelectionEnd())
self.ReplaceTarget(text)
self.SetReadOnly(ro)
syntax highlighted by Code2HTML, v. 0.9.1