1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.pyshell
3 # Purpose: A Python Interactive Interpreter running in a wxStyledTextCtrl
10 # Copyright: (c) 2000 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------
15 PyShellWindow is a class that provides an Interactive Interpreter running
16 inside a wxStyledTextCtrl, similar to the Python shell windows found in
19 There is still much to be done to improve this class, such as line
20 buffering/recall, autoindent, calltips, autocomplete, fixing the colourizer,
21 etc... But it's a good start.
24 8-10-2001 THIS MODULE IS NOW DEPRECATED. Please see the most excellent
25 PyCrust package instead.
30 from wxPython
.wx
import *
31 from wxPython
.stc
import *
34 from code
import InteractiveInterpreter
36 #----------------------------------------------------------------------
37 # default styles, etc. to use for the STC
39 if wxPlatform
== '__WXMSW__':
45 _default_properties
= {
49 'stdout' : 'fore:#0000FF',
50 'stderr' : 'fore:#007f00',
51 'trace' : 'fore:#FF0000',
53 'default' : 'size:%d' % _defaultSize
,
54 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
55 'bracebad' : 'fore:#000000,back:#FF0000,bold',
57 # properties for the various Python lexer styles
58 'comment' : 'fore:#007F00',
59 'number' : 'fore:#007F7F',
60 'string' : 'fore:#7F007F,italic',
61 'char' : 'fore:#7F007F,italic',
62 'keyword' : 'fore:#00007F,bold',
63 'triple' : 'fore:#7F0000',
64 'tripledouble': 'fore:#7F0000',
65 'class' : 'fore:#0000FF,bold,underline',
66 'def' : 'fore:#007F7F,bold',
78 #----------------------------------------------------------------------
80 class PyShellWindow(wxStyledTextCtrl
, InteractiveInterpreter
):
81 def __init__(self
, parent
, ID
, pos
=wxDefaultPosition
,
82 size
=wxDefaultSize
, style
=0,
83 locals=None, properties
=None, banner
=None):
84 wxStyledTextCtrl
.__init
__(self
, parent
, ID
, pos
, size
, style
)
85 InteractiveInterpreter
.__init
__(self
, locals)
87 self
.lastPromptPos
= 0
89 # the line cache is used to cycle through previous commands
91 self
.lastUsedLine
= self
.curLine
= 0
93 # set defaults and then deal with any user defined properties
95 self
.props
.update(_default_properties
)
97 self
.props
.update(properties
)
98 self
.UpdateProperties()
100 # copyright/banner message
102 self
.write("Python %s on %s\n" % #%s\n(%s)\n" %
103 (sys
.version
, sys
.platform
,
104 #sys.copyright, self.__class__.__name__
107 self
.write("%s\n" % banner
)
109 # write the initial prompt
113 EVT_KEY_DOWN(self
, self
.OnKey
)
114 EVT_STC_UPDATEUI(self
, ID
, self
.OnUpdateUI
)
115 #EVT_STC_STYLENEEDED(self, ID, self.OnStyle)
118 def GetLocals(self
): return self
.locals
119 def SetLocals(self
, locals): self
.locals = locals
121 def GetProperties(self
): return self
.props
122 def SetProperties(self
, properties
):
123 self
.props
.update(properties
)
124 self
.UpdateProperties()
127 def UpdateProperties(self
):
129 Reset the editor and other settings based on the contents of the
130 current properties dictionary.
134 #self.SetEdgeMode(wxSTC_EDGE_LINE)
135 #self.SetEdgeColumn(80)
138 # set the selection margin and window margin
139 self
.SetMarginWidth(1, p
['selMargin'])
140 self
.SetMargins(p
['marginWidth'], p
['marginWidth'])
143 self
.StyleSetSpec(wxSTC_STYLE_DEFAULT
, p
['default'])
145 self
.StyleSetSpec(_stdout_style
, p
['stdout'])
146 self
.StyleSetSpec(_stderr_style
, p
['stderr'])
147 self
.StyleSetSpec(_trace_style
, p
['trace'])
149 self
.StyleSetSpec(wxSTC_STYLE_BRACELIGHT
, p
['bracegood'])
150 self
.StyleSetSpec(wxSTC_STYLE_BRACEBAD
, p
['bracebad'])
151 self
.StyleSetSpec(wxSTC_P_COMMENTLINE
, p
['comment'])
152 self
.StyleSetSpec(wxSTC_P_NUMBER
, p
['number'])
153 self
.StyleSetSpec(wxSTC_P_STRING
, p
['string'])
154 self
.StyleSetSpec(wxSTC_P_CHARACTER
, p
['char'])
155 self
.StyleSetSpec(wxSTC_P_WORD
, p
['keyword'])
156 self
.StyleSetSpec(wxSTC_P_TRIPLE
, p
['triple'])
157 self
.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE
, p
['tripledouble'])
158 self
.StyleSetSpec(wxSTC_P_CLASSNAME
, p
['class'])
159 self
.StyleSetSpec(wxSTC_P_DEFNAME
, p
['def'])
160 self
.StyleSetSpec(wxSTC_P_OPERATOR
, p
['operator'])
161 self
.StyleSetSpec(wxSTC_P_COMMENTBLOCK
, p
['comment'])
164 # used for writing to stdout, etc.
165 def _write(self
, text
, style
=_stdout_style
):
166 self
.lastPromptPos
= 0
167 pos
= self
.GetCurrentPos()
169 self
.StartStyling(pos
, 0xFF)
170 self
.SetStyling(len(text
), style
)
171 self
.EnsureCaretVisible()
176 def writeTrace(self
, text
):
177 self
._write
(text
, _trace_style
)
181 # is the current line non-empty?
182 text
, pos
= self
.GetCurLine()
185 self
.AddText(self
.props
['ps1'])
186 self
.lastPromptPos
= self
.GetCurrentPos()
187 self
.EnsureCaretVisible()
188 self
.ScrollToColumn(0)
191 def PushLine(self
, text
):
192 # TODO: Add the text to the line cache, manage the cache so
193 # it doesn't get too big.
198 def OnKey(self
, evt
):
200 if key
== WXK_RETURN
:
201 pos
= self
.GetCurrentPos()
202 lastPos
= self
.GetTextLength()
204 # if not on the last line, duplicate the current line
205 if self
.GetLineCount()-1 != self
.GetCurrentLine():
206 text
, col
= self
.GetCurLine()
207 prompt
= self
.props
['ps1']
209 if text
[:lp
] == prompt
:
212 self
.SetSelection(self
.lastPromptPos
, lastPos
)
213 self
.ReplaceSelection(text
[:-1])
215 else: # try to execute the text from the prompt to the end
216 if lastPos
== self
.lastPromptPos
:
221 text
= self
.GetTextRange(self
.lastPromptPos
, lastPos
)
224 more
= self
.runsource(text
)
229 # TODO: Add handlers for Alt-P and Alt-N to cycle through entries
236 def OnStyle(self
, evt
):
237 # Only style from the prompt pos to the end
238 lastPos
= self
.GetTextLength()
239 if self
.lastPromptPos
and self
.lastPromptPos
!= lastPos
:
240 self
.SetLexer(wxSTC_LEX_PYTHON
)
241 self
.SetKeywords(0, ' '.join(keyword
.kwlist
))
243 self
.Colourise(self
.lastPromptPos
, lastPos
)
248 def OnUpdateUI(self
, evt
):
249 # check for matching braces
253 caretPos
= self
.GetCurrentPos()
255 charBefore
= self
.GetCharAt(caretPos
- 1)
256 styleBefore
= self
.GetStyleAt(caretPos
- 1)
259 if charBefore
and chr(charBefore
) in "[]{}()" and styleBefore
== wxSTC_P_OPERATOR
:
260 braceAtCaret
= caretPos
- 1
264 charAfter
= self
.GetCharAt(caretPos
)
265 styleAfter
= self
.GetStyleAt(caretPos
)
266 if charAfter
and chr(charAfter
) in "[]{}()" and styleAfter
== wxSTC_P_OPERATOR
:
267 braceAtCaret
= caretPos
269 if braceAtCaret
>= 0:
270 braceOpposite
= self
.BraceMatch(braceAtCaret
)
272 if braceAtCaret
!= -1 and braceOpposite
== -1:
273 self
.BraceBadlight(braceAtCaret
)
275 self
.BraceHighlight(braceAtCaret
, braceOpposite
)
279 #----------------------------------------------
280 # overloaded methods from InteractiveInterpreter
281 def runsource(self
, source
):
282 stdout
, stderr
= sys
.stdout
, sys
.stderr
283 sys
.stdout
= FauxFile(self
, _stdout_style
)
284 sys
.stderr
= FauxFile(self
, _stderr_style
)
286 more
= InteractiveInterpreter
.runsource(self
, source
)
288 sys
.stdout
, sys
.stderr
= stdout
, stderr
291 def showsyntaxerror(self
, filename
=None):
292 self
.write
= self
.writeTrace
293 InteractiveInterpreter
.showsyntaxerror(self
, filename
)
294 self
.write
= self
._write
296 def showtraceback(self
):
297 self
.write
= self
.writeTrace
298 InteractiveInterpreter
.showtraceback(self
)
299 self
.write
= self
._write
301 #----------------------------------------------------------------------
304 def __init__(self
, psw
, style
):
308 def write(self
, text
):
309 self
.psw
.write(text
, self
.style
)
311 def writelines(self
, lst
):
318 #----------------------------------------------------------------------
321 if __name__
== '__main__':
322 app
= wxPyWidgetTester(size
= (640, 480))
323 app
.SetWidget(PyShellWindow
, -1)
327 #----------------------------------------------------------------------