##// END OF EJS Templates
Update wx frontend.
Gael Varoquaux -
Show More
@@ -0,0 +1,207 b''
1 # encoding: utf-8 -*- test-case-name:
2 # FIXME: Need to add tests.
3 # ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
4
5 """Classes to provide a Wx frontend to the
6 ipython1.kernel.engineservice.EngineService.
7
8 """
9
10 __docformat__ = "restructuredtext en"
11
12 #-------------------------------------------------------------------------------
13 # Copyright (C) 2008 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-------------------------------------------------------------------------------
18
19 #-------------------------------------------------------------------------------
20 # Imports
21 #-------------------------------------------------------------------------------
22
23
24 import wx
25 from console_widget import ConsoleWidget
26 import re
27
28 import IPython
29 from IPython.kernel.engineservice import EngineService
30 from IPython.frontend.frontendbase import FrontEndBase
31
32 #-------------------------------------------------------------------------------
33 # Classes to implement the Wx frontend
34 #-------------------------------------------------------------------------------
35
36
37
38
39 class IPythonWxController(FrontEndBase, ConsoleWidget):
40
41 output_prompt = \
42 '\n\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
43
44 # Are we entering multi line input?
45 multi_line_input = False
46
47 # The added tab stop to the string. It may, for instance, come from
48 # copy and pasting something with tabs.
49 tab_stop = 0
50 # FIXME: We still have to deal with this.
51
52 #--------------------------------------------------------------------------
53 # Public API
54 #--------------------------------------------------------------------------
55
56 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
57 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
58 *args, **kwds):
59 """ Create Shell instance.
60 """
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
62 FrontEndBase.__init__(self, engine=EngineService(),
63 )
64
65 # FIXME: Something is wrong with the history, I instanciate it
66 # with an empty cache, but this is not the way to do.
67 self.lines = {}
68
69 # Start the IPython engine
70 self.engine.startService()
71
72 # Capture Character keys
73 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
74
75 #FIXME: print banner.
76 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
77 % IPython.__version__
78
79
80 def appWillTerminate_(self, notification):
81 """appWillTerminate"""
82
83 self.engine.stopService()
84
85
86 def complete(self, token):
87 """Complete token in engine's user_ns
88
89 Parameters
90 ----------
91 token : string
92
93 Result
94 ------
95 Deferred result of
96 IPython.kernel.engineservice.IEngineBase.complete
97 """
98
99 return self.engine.complete(token)
100
101
102 def render_result(self, result):
103 if 'stdout' in result and result['stdout']:
104 self.write('\n' + result['stdout'])
105 if 'display' in result and result['display']:
106 self.write("%s%s\n" % (
107 self.output_prompt % result['number'],
108 result['display']['pprint']
109 ) )
110
111
112 def render_error(self, failure):
113 self.insert_text('\n\n'+str(failure)+'\n\n')
114 return failure
115
116
117 #--------------------------------------------------------------------------
118 # Private API
119 #--------------------------------------------------------------------------
120
121
122 def _on_key_down(self, event, skip=True):
123 """ Capture the character events, let the parent
124 widget handle them, and put our logic afterward.
125 """
126 current_line_number = self.GetCurrentLine()
127 # Capture enter
128 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
129 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
130 self._on_enter()
131 # Up history
132 elif event.KeyCode == wx.WXK_UP and (
133 ( current_line_number == self.current_prompt_line and
134 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
135 or event.ControlDown() ):
136 new_buffer = self.get_history_previous(
137 self.get_current_edit_buffer())
138 if new_buffer is not None:
139 self.replace_current_edit_buffer(new_buffer)
140 # Down history
141 elif event.KeyCode == wx.WXK_DOWN and (
142 ( current_line_number == self.LineCount -1 and
143 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
144 or event.ControlDown() ):
145 new_buffer = self.get_history_next()
146 if new_buffer is not None:
147 self.replace_current_edit_buffer(new_buffer)
148 else:
149 ConsoleWidget._on_key_down(self, event, skip=True)
150
151
152 def _on_enter(self):
153 """ Called when the return key is pressed in a line editing
154 buffer.
155 """
156 current_buffer = self.get_current_edit_buffer()
157 current_buffer = current_buffer.replace('\r\n', '\n')
158 current_buffer = current_buffer.replace('\t', 4*' ')
159 cleaned_buffer = '\n'.join(l.rstrip()
160 for l in current_buffer.split('\n'))
161 if ( not self.multi_line_input
162 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
163 if self.is_complete(cleaned_buffer):
164 self._add_history(None, cleaned_buffer.rstrip())
165 result = self.engine.shell.execute(cleaned_buffer)
166 self.render_result(result)
167 self.new_prompt(self.prompt % (result['number'] + 1))
168 self.multi_line_input = False
169 else:
170 if self.multi_line_input:
171 self.write('\n' + self._get_indent_string(current_buffer))
172 else:
173 self.multi_line_input = True
174 self.write('\n\t')
175 else:
176 self.write('\n'+self._get_indent_string(current_buffer))
177
178
179 def _get_indent_string(self, string):
180 string = string.split('\n')[-1]
181 indent_chars = len(string) - len(string.lstrip())
182 indent_string = '\t'*(indent_chars // 4) + \
183 ' '*(indent_chars % 4)
184
185 return indent_string
186
187
188
189 if __name__ == '__main__':
190 class MainWindow(wx.Frame):
191 def __init__(self, parent, id, title):
192 wx.Frame.__init__(self, parent, id, title, size=(300,250))
193 self._sizer = wx.BoxSizer(wx.VERTICAL)
194 self.shell = IPythonWxController(self)
195 self._sizer.Add(self.shell, 1, wx.EXPAND)
196 self.SetSizer(self._sizer)
197 self.SetAutoLayout(1)
198 self.Show(True)
199
200 app = wx.PySimpleApp()
201 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
202 frame.shell.SetFocus()
203 frame.SetSize((660, 460))
204 self = frame.shell
205
206 app.MainLoop()
207
@@ -22,21 +22,59 b' __docformat__ = "restructuredtext en"'
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
26
25 import re
27 import re
26
28
27 # FIXME: Need to provide an API for non user-generated display on the
29 # FIXME: Need to provide an API for non user-generated display on the
28 # screen: this should not be editable by the user.
30 # screen: this should not be editable by the user.
29
31
32 if wx.Platform == '__WXMSW__':
33 _DEFAULT_SIZE = 80
34 else:
35 _DEFAULT_SIZE = 10
36
37 _DEFAULT_STYLE = {
38 'stdout' : 'fore:#0000FF',
39 'stderr' : 'fore:#007f00',
40 'trace' : 'fore:#FF0000',
41
42 'default' : 'size:%d' % _DEFAULT_SIZE,
43 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
44 'bracebad' : 'fore:#000000,back:#FF0000,bold',
45
46 # properties for the various Python lexer styles
47 'comment' : 'fore:#007F00',
48 'number' : 'fore:#007F7F',
49 'string' : 'fore:#7F007F,italic',
50 'char' : 'fore:#7F007F,italic',
51 'keyword' : 'fore:#00007F,bold',
52 'triple' : 'fore:#7F0000',
53 'tripledouble': 'fore:#7F0000',
54 'class' : 'fore:#0000FF,bold,underline',
55 'def' : 'fore:#007F7F,bold',
56 'operator' : 'bold',
57
58 }
59
60 # new style numbers
61 _STDOUT_STYLE = 15
62 _STDERR_STYLE = 16
63 _TRACE_STYLE = 17
64
65
30 #-------------------------------------------------------------------------------
66 #-------------------------------------------------------------------------------
31 # The console widget class
67 # The console widget class
32 #-------------------------------------------------------------------------------
68 #-------------------------------------------------------------------------------
33 class ConsoleWidget(stc.StyledTextCtrl):
69 class ConsoleWidget(editwindow.EditWindow):
34 """ Specialized styled text control view for console-like workflow.
70 """ Specialized styled text control view for console-like workflow.
35
71
36 This widget is mainly interested in dealing with the prompt and
72 This widget is mainly interested in dealing with the prompt and
37 keeping the cursor inside the editing line.
73 keeping the cursor inside the editing line.
38 """
74 """
39
75
76 style = _DEFAULT_STYLE.copy()
77
40 # Translation table from ANSI escape sequences to color. Override
78 # Translation table from ANSI escape sequences to color. Override
41 # this to specify your colors.
79 # this to specify your colors.
42 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
80 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
@@ -57,6 +95,97 b' class ConsoleWidget(stc.StyledTextCtrl):'
57 # Public API
95 # Public API
58 #--------------------------------------------------------------------------
96 #--------------------------------------------------------------------------
59
97
98 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
99 size=wx.DefaultSize, style=0,
100 autocomplete_mode='IPYTHON'):
101 """ Autocomplete_mode: Can be 'IPYTHON' or 'STC'
102 'IPYTHON' show autocompletion the ipython way
103 'STC" show it scintilla text control way
104 """
105 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
106 self.configure_scintilla()
107
108 # FIXME: we need to retrieve this from the interpreter.
109 self.prompt = \
110 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02%i\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
111 self.new_prompt(self.prompt % 1)
112
113 self.autocomplete_mode = autocomplete_mode
114
115 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
116
117
118 def configure_scintilla(self):
119 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
120 # the widget
121 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
122 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
123 # Also allow Ctrl Shift "=" for poor non US keyboard users.
124 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
125 stc.STC_CMD_ZOOMIN)
126
127 self.CmdKeyAssign(stc.STC_KEY_PRIOR, stc.STC_SCMOD_SHIFT,
128 stc.STC_CMD_PAGEUP)
129
130 self.CmdKeyAssign(stc.STC_KEY_NEXT, stc.STC_SCMOD_SHIFT,
131 stc.STC_CMD_PAGEDOWN)
132
133 # Keys: we need to clear some of the keys the that don't play
134 # well with a console.
135 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
136 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
137 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
138
139
140 self.SetEOLMode(stc.STC_EOL_CRLF)
141 self.SetWrapMode(stc.STC_WRAP_CHAR)
142 self.SetWrapMode(stc.STC_WRAP_WORD)
143 self.SetBufferedDraw(True)
144 self.SetUseAntiAliasing(True)
145 self.SetLayoutCache(stc.STC_CACHE_PAGE)
146 self.SetUndoCollection(False)
147 self.SetUseTabs(True)
148 self.SetIndent(4)
149 self.SetTabWidth(4)
150
151 self.EnsureCaretVisible()
152
153 self.SetMargins(3, 3) #text is moved away from border with 3px
154 # Suppressing Scintilla margins
155 self.SetMarginWidth(0, 0)
156 self.SetMarginWidth(1, 0)
157 self.SetMarginWidth(2, 0)
158
159 self._apply_style()
160
161 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
162
163 #self.SetEdgeMode(stc.STC_EDGE_LINE)
164 #self.SetEdgeColumn(80)
165
166 # styles
167 p = self.style
168 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
169 self.StyleClearAll()
170 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
171 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
172 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
173
174 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
175 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
176 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
177 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
178 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
179 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
180 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
181 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
182 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
183 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
184 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
185 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
186 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
187
188
60 def write(self, text):
189 def write(self, text):
61 """ Write given text to buffer, while translating the ansi escape
190 """ Write given text to buffer, while translating the ansi escape
62 sequences.
191 sequences.
@@ -94,10 +223,6 b' class ConsoleWidget(stc.StyledTextCtrl):'
94 self.current_prompt_pos = self.GetLength()
223 self.current_prompt_pos = self.GetLength()
95 self.current_prompt_line = self.GetCurrentLine()
224 self.current_prompt_line = self.GetCurrentLine()
96
225
97 autoindent = self.indent * ' '
98 autoindent = autoindent.replace(' ','\t')
99 self.write(autoindent)
100
101
226
102 def replace_current_edit_buffer(self, text):
227 def replace_current_edit_buffer(self, text):
103 """ Replace currently entered command line with given text.
228 """ Replace currently entered command line with given text.
@@ -118,96 +243,10 b' class ConsoleWidget(stc.StyledTextCtrl):'
118 # Private API
243 # Private API
119 #--------------------------------------------------------------------------
244 #--------------------------------------------------------------------------
120
245
121 def __init__(self, parent, pos=wx.DefaultPosition, ID=-1,
122 size=wx.DefaultSize, style=0,
123 autocomplete_mode='IPYTHON'):
124 """ Autocomplete_mode: Can be 'IPYTHON' or 'STC'
125 'IPYTHON' show autocompletion the ipython way
126 'STC" show it scintilla text control way
127 """
128 stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
129
130 #------ Scintilla configuration -----------------------------------
131
132 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
133 # the widget
134 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
135 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
136 # Also allow Ctrl Shift "=" for poor non US keyboard users.
137 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
138 stc.STC_CMD_ZOOMIN)
139
140 self.SetEOLMode(stc.STC_EOL_CRLF)
141 self.SetWrapMode(stc.STC_WRAP_CHAR)
142 self.SetWrapMode(stc.STC_WRAP_WORD)
143 self.SetBufferedDraw(True)
144 self.SetUseAntiAliasing(True)
145 self.SetLayoutCache(stc.STC_CACHE_PAGE)
146 self.SetUndoCollection(False)
147 self.SetUseTabs(True)
148 self.SetIndent(4)
149 self.SetTabWidth(4)
150
151 self.EnsureCaretVisible()
152
153 self.SetMargins(3, 3) #text is moved away from border with 3px
154 # Suppressing Scintilla margins
155 self.SetMarginWidth(0, 0)
156 self.SetMarginWidth(1, 0)
157 self.SetMarginWidth(2, 0)
158
159 self._apply_style()
160
161 self.indent = 0
162 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
163
164 # FIXME: we need to retrieve this from the interpreter.
165 self.prompt = \
166 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x026\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
167 self.new_prompt(self.prompt)
168
169 self.autocomplete_mode = autocomplete_mode
170
171 self.Bind(wx.EVT_KEY_DOWN, self._onKeypress)
172
173
174 def _apply_style(self):
246 def _apply_style(self):
175 """ Applies the colors for the different text elements and the
247 """ Applies the colors for the different text elements and the
176 carret.
248 carret.
177 """
249 """
178 # FIXME: We need to do something for the fonts, but this is
179 # clearly not the right option.
180 #we define platform specific fonts
181 # if wx.Platform == '__WXMSW__':
182 # faces = { 'times': 'Times New Roman',
183 # 'mono' : 'Courier New',
184 # 'helv' : 'Arial',
185 # 'other': 'Comic Sans MS',
186 # 'size' : 10,
187 # 'size2': 8,
188 # }
189 # elif wx.Platform == '__WXMAC__':
190 # faces = { 'times': 'Times New Roman',
191 # 'mono' : 'Monaco',
192 # 'helv' : 'Arial',
193 # 'other': 'Comic Sans MS',
194 # 'size' : 10,
195 # 'size2': 8,
196 # }
197 # else:
198 # faces = { 'times': 'Times',
199 # 'mono' : 'Courier',
200 # 'helv' : 'Helvetica',
201 # 'other': 'new century schoolbook',
202 # 'size' : 10,
203 # 'size2': 8,
204 # }
205 # self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
206 # "fore:%s,back:%s,size:%d,face:%s"
207 # % (self.ANSI_STYLES['0;30'][1],
208 # self.background_color,
209 # faces['size'], faces['mono']))
210
211 self.SetCaretForeground(self.carret_color)
250 self.SetCaretForeground(self.carret_color)
212
251
213 self.StyleClearAll()
252 self.StyleClearAll()
@@ -220,7 +259,7 b' class ConsoleWidget(stc.StyledTextCtrl):'
220 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
259 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
221
260
222
261
223 def removeFromTo(self, from_pos, to_pos):
262 def removeFromTo(self, from_pos, to_pos):
224 if from_pos < to_pos:
263 if from_pos < to_pos:
225 self.SetSelection(from_pos, to_pos)
264 self.SetSelection(from_pos, to_pos)
226 self.DeleteBack()
265 self.DeleteBack()
@@ -266,8 +305,13 b' class ConsoleWidget(stc.StyledTextCtrl):'
266 last_word = last_word.split(breaker)[-1]
305 last_word = last_word.split(breaker)[-1]
267 self.AutoCompShow(len(last_word), " ".join(possibilities))
306 self.AutoCompShow(len(last_word), " ".join(possibilities))
268
307
308
309 def scroll_to_bottom(self):
310 maxrange = self.GetScrollRange(wx.VERTICAL)
311 self.ScrollLines(maxrange)
312
269
313
270 def _onKeypress(self, event, skip=True):
314 def _on_key_down(self, event, skip=True):
271 """ Key press callback used for correcting behavior for
315 """ Key press callback used for correcting behavior for
272 console-like interfaces: the cursor is constraint to be after
316 console-like interfaces: the cursor is constraint to be after
273 the last prompt.
317 the last prompt.
@@ -275,20 +319,25 b' class ConsoleWidget(stc.StyledTextCtrl):'
275 Return True if event as been catched.
319 Return True if event as been catched.
276 """
320 """
277 catched = False
321 catched = False
322 if event.KeyCode == ord('L') and event.ControlDown() :
323 skip = False
324 catched = True
325 self.scroll_to_bottom()
326
278 if self.AutoCompActive():
327 if self.AutoCompActive():
279 event.Skip()
328 event.Skip()
280 else:
329 else:
281 if event.GetKeyCode() == wx.WXK_HOME:
330 if event.KeyCode == wx.WXK_HOME:
282 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
331 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
283 self.GotoPos(self.current_prompt_pos)
332 self.GotoPos(self.current_prompt_pos)
284 catched = True
333 catched = True
285
334
286 elif event.Modifiers == wx.MOD_SHIFT:
335 elif event.Modifiers in (wx.MOD_SHIFT, wx.MOD_WIN) :
287 self.selectFromTo(self.current_prompt_pos,
336 self.selectFromTo(self.current_prompt_pos,
288 self.GetCurrentPos())
337 self.GetCurrentPos())
289 catched = True
338 catched = True
290
339
291 elif event.GetKeyCode() == wx.WXK_UP:
340 elif event.KeyCode == wx.WXK_UP:
292 if self.GetCurrentLine() > self.current_prompt_line:
341 if self.GetCurrentLine() > self.current_prompt_line:
293 if self.GetCurrentLine() == self.current_prompt_line + 1 \
342 if self.GetCurrentLine() == self.current_prompt_line + 1 \
294 and self.GetColumn(self.GetCurrentPos()) < \
343 and self.GetColumn(self.GetCurrentPos()) < \
@@ -298,7 +347,7 b' class ConsoleWidget(stc.StyledTextCtrl):'
298 event.Skip()
347 event.Skip()
299 catched = True
348 catched = True
300
349
301 elif event.GetKeyCode() in (wx.WXK_LEFT, wx.WXK_BACK):
350 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
302 if self.GetCurrentPos() > self.current_prompt_pos:
351 if self.GetCurrentPos() > self.current_prompt_pos:
303 event.Skip()
352 event.Skip()
304 catched = True
353 catched = True
@@ -306,7 +355,7 b' class ConsoleWidget(stc.StyledTextCtrl):'
306 if skip and not catched:
355 if skip and not catched:
307 event.Skip()
356 event.Skip()
308
357
309 if event.GetKeyCode() not in (wx.WXK_PAGEUP, wx.WXK_PAGEDOWN)\
358 if event.KeyCode not in (wx.WXK_PAGEUP, wx.WXK_PAGEDOWN)\
310 and event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
359 and event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
311 wx.MOD_SHIFT):
360 wx.MOD_SHIFT):
312 # If cursor is outside the editing region, put it back.
361 # If cursor is outside the editing region, put it back.
@@ -316,37 +365,6 b' class ConsoleWidget(stc.StyledTextCtrl):'
316 return catched
365 return catched
317
366
318
367
319 def OnUpdateUI(self, evt):
320 # check for matching braces
321 braceAtCaret = -1
322 braceOpposite = -1
323 charBefore = None
324 caretPos = self.GetCurrentPos()
325
326 if caretPos > 0:
327 charBefore = self.GetCharAt(caretPos - 1)
328 styleBefore = self.GetStyleAt(caretPos - 1)
329
330 # check before
331 if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
332 braceAtCaret = caretPos - 1
333
334 # check after
335 if braceAtCaret < 0:
336 charAfter = self.GetCharAt(caretPos)
337 styleAfter = self.GetStyleAt(caretPos)
338
339 if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
340 braceAtCaret = caretPos
341
342 if braceAtCaret >= 0:
343 braceOpposite = self.BraceMatch(braceAtCaret)
344
345 if braceAtCaret != -1 and braceOpposite == -1:
346 self.BraceBadLight(braceAtCaret)
347 else:
348 self.BraceHighlight(braceAtCaret, braceOpposite)
349
350
368
351 if __name__ == '__main__':
369 if __name__ == '__main__':
352 # Some simple code to test the console widget.
370 # Some simple code to test the console widget.
General Comments 0
You need to be logged in to leave comments. Login now