]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/pyshell.py
229e2e51906afecd695d35a079d8907239e9c3fc
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.
26 from wxPython
.wx
import *
27 from wxPython
.stc
import *
29 import sys
, string
, keyword
30 from code
import InteractiveInterpreter
32 #----------------------------------------------------------------------
33 # default styles, etc. to use for the STC
35 if wxPlatform
== '__WXMSW__':
41 _default_properties
= {
45 'stdout' : 'fore:#0000FF',
46 'stderr' : 'fore:#007f00',
47 'trace' : 'fore:#FF0000',
49 'default' : 'size:%d' % _defaultSize
,
50 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
51 'bracebad' : 'fore:#000000,back:#FF0000,bold',
53 # properties for the various Python lexer styles
54 'comment' : 'fore:#007F00',
55 'number' : 'fore:#007F7F',
56 'string' : 'fore:#7F007F,italic',
57 'char' : 'fore:#7F007F,italic',
58 'keyword' : 'fore:#00007F,bold',
59 'triple' : 'fore:#7F0000',
60 'tripledouble': 'fore:#7F0000',
61 'class' : 'fore:#0000FF,bold,underline',
62 'def' : 'fore:#007F7F,bold',
74 #----------------------------------------------------------------------
76 class PyShellWindow(wxStyledTextCtrl
, InteractiveInterpreter
):
77 def __init__(self
, parent
, ID
, pos
=wxDefaultPosition
,
78 size
=wxDefaultSize
, style
=0,
79 locals=None, properties
=None, banner
=None):
80 wxStyledTextCtrl
.__init
__(self
, parent
, ID
, pos
, size
, style
)
81 InteractiveInterpreter
.__init
__(self
, locals)
83 self
.lastPromptPos
= 0
85 # the line cache is used to cycle through previous commands
87 self
.lastUsedLine
= self
.curLine
= 0
89 # set defaults and then deal with any user defined properties
91 self
.props
.update(_default_properties
)
93 self
.props
.update(properties
)
94 self
.UpdateProperties()
96 # copyright/banner message
98 self
.write("Python %s on %s\n" % #%s\n(%s)\n" %
99 (sys
.version
, sys
.platform
,
100 #sys.copyright, self.__class__.__name__
103 self
.write("%s\n" % banner
)
105 # write the initial prompt
109 EVT_KEY_DOWN(self
, self
.OnKey
)
110 EVT_STC_UPDATEUI(self
, ID
, self
.OnUpdateUI
)
111 #EVT_STC_STYLENEEDED(self, ID, self.OnStyle)
114 def GetLocals(self
): return self
.locals
115 def SetLocals(self
, locals): self
.locals = locals
117 def GetProperties(self
): return self
.props
118 def SetProperties(self
, properties
):
119 self
.props
.update(properties
)
120 self
.UpdateProperties()
123 def UpdateProperties(self
):
125 Reset the editor and other settings based on the contents of the
126 current properties dictionary.
130 #self.SetEdgeMode(wxSTC_EDGE_LINE)
131 #self.SetEdgeColumn(80)
134 # set the selection margin and window margin
135 self
.SetMarginWidth(1, p
['selMargin'])
136 self
.SetMargins(p
['marginWidth'], p
['marginWidth'])
139 self
.StyleSetSpec(wxSTC_STYLE_DEFAULT
, p
['default'])
141 self
.StyleSetSpec(_stdout_style
, p
['stdout'])
142 self
.StyleSetSpec(_stderr_style
, p
['stderr'])
143 self
.StyleSetSpec(_trace_style
, p
['trace'])
145 self
.StyleSetSpec(wxSTC_STYLE_BRACELIGHT
, p
['bracegood'])
146 self
.StyleSetSpec(wxSTC_STYLE_BRACEBAD
, p
['bracebad'])
147 self
.StyleSetSpec(wxSTC_P_COMMENTLINE
, p
['comment'])
148 self
.StyleSetSpec(wxSTC_P_NUMBER
, p
['number'])
149 self
.StyleSetSpec(wxSTC_P_STRING
, p
['string'])
150 self
.StyleSetSpec(wxSTC_P_CHARACTER
, p
['char'])
151 self
.StyleSetSpec(wxSTC_P_WORD
, p
['keyword'])
152 self
.StyleSetSpec(wxSTC_P_TRIPLE
, p
['triple'])
153 self
.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE
, p
['tripledouble'])
154 self
.StyleSetSpec(wxSTC_P_CLASSNAME
, p
['class'])
155 self
.StyleSetSpec(wxSTC_P_DEFNAME
, p
['def'])
156 self
.StyleSetSpec(wxSTC_P_OPERATOR
, p
['operator'])
157 self
.StyleSetSpec(wxSTC_P_COMMENTBLOCK
, p
['comment'])
160 # used for writing to stdout, etc.
161 def _write(self
, text
, style
=_stdout_style
):
162 self
.lastPromptPos
= 0
163 pos
= self
.GetCurrentPos()
165 self
.StartStyling(pos
, 0xFF)
166 self
.SetStyling(len(text
), style
)
167 self
.EnsureCaretVisible()
172 def writeTrace(self
, text
):
173 self
._write
(text
, _trace_style
)
177 # is the current line non-empty?
178 text
, pos
= self
.GetCurLine()
181 self
.AddText(self
.props
['ps1'])
182 self
.lastPromptPos
= self
.GetCurrentPos()
183 self
.EnsureCaretVisible()
184 self
.ScrollToColumn(0)
187 def PushLine(self
, text
):
188 # TODO: Add the text to the line cache, manage the cache so
189 # it doesn't get too big.
194 def OnKey(self
, evt
):
196 if key
== WXK_RETURN
:
197 pos
= self
.GetCurrentPos()
198 lastPos
= self
.GetTextLength()
200 # if not on the last line, duplicate the current line
201 if self
.GetLineCount()-1 != self
.GetCurrentLine():
202 text
, col
= self
.GetCurLine()
203 prompt
= self
.props
['ps1']
205 if text
[:lp
] == prompt
:
208 self
.SetSelection(self
.lastPromptPos
, lastPos
)
209 self
.ReplaceSelection(text
[:-1])
211 else: # try to execute the text from the prompt to the end
212 if lastPos
== self
.lastPromptPos
:
217 text
= self
.GetTextRange(self
.lastPromptPos
, lastPos
)
220 more
= self
.runsource(text
)
225 # TODO: Add handlers for Alt-P and Alt-N to cycle through entries
232 def OnStyle(self
, evt
):
233 # Only style from the prompt pos to the end
234 lastPos
= self
.GetTextLength()
235 if self
.lastPromptPos
and self
.lastPromptPos
!= lastPos
:
236 self
.SetLexer(wxSTC_LEX_PYTHON
)
237 self
.SetKeywords(0, string
.join(keyword
.kwlist
))
239 self
.Colourise(self
.lastPromptPos
, lastPos
)
244 def OnUpdateUI(self
, evt
):
245 # check for matching braces
249 caretPos
= self
.GetCurrentPos()
251 charBefore
= self
.GetCharAt(caretPos
- 1)
252 styleBefore
= self
.GetStyleAt(caretPos
- 1)
255 if charBefore
and chr(charBefore
) in "[]{}()" and styleBefore
== wxSTC_P_OPERATOR
:
256 braceAtCaret
= caretPos
- 1
260 charAfter
= self
.GetCharAt(caretPos
)
261 styleAfter
= self
.GetStyleAt(caretPos
)
262 if charAfter
and chr(charAfter
) in "[]{}()" and styleAfter
== wxSTC_P_OPERATOR
:
263 braceAtCaret
= caretPos
265 if braceAtCaret
>= 0:
266 braceOpposite
= self
.BraceMatch(braceAtCaret
)
268 if braceAtCaret
!= -1 and braceOpposite
== -1:
269 self
.BraceBadlight(braceAtCaret
)
271 self
.BraceHighlight(braceAtCaret
, braceOpposite
)
275 #----------------------------------------------
276 # overloaded methods from InteractiveInterpreter
277 def runsource(self
, source
):
278 stdout
, stderr
= sys
.stdout
, sys
.stderr
279 sys
.stdout
= FauxFile(self
, _stdout_style
)
280 sys
.stderr
= FauxFile(self
, _stderr_style
)
282 more
= InteractiveInterpreter
.runsource(self
, source
)
284 sys
.stdout
, sys
.stderr
= stdout
, stderr
287 def showsyntaxerror(self
, filename
=None):
288 self
.write
= self
.writeTrace
289 InteractiveInterpreter
.showsyntaxerror(self
, filename
)
290 self
.write
= self
._write
292 def showtraceback(self
):
293 self
.write
= self
.writeTrace
294 InteractiveInterpreter
.showtraceback(self
)
295 self
.write
= self
._write
297 #----------------------------------------------------------------------
300 def __init__(self
, psw
, style
):
304 def write(self
, text
):
305 self
.psw
.write(text
, self
.style
)
307 def writelines(self
, lst
):
314 #----------------------------------------------------------------------
317 if __name__
== '__main__':
318 app
= wxPyWidgetTester(size
= (640, 480))
319 app
.SetWidget(PyShellWindow
, -1)
323 #----------------------------------------------------------------------