##// END OF EJS Templates
Minor bug.
Gael Varoquaux -
Show More
@@ -1,418 +1,418 b''
1 1 # encoding: utf-8
2 2 """
3 3 A Wx widget to act as a console and input commands.
4 4
5 5 This widget deals with prompts and provides an edit buffer
6 6 restricted to after the last prompt.
7 7 """
8 8
9 9 __docformat__ = "restructuredtext en"
10 10
11 11 #-------------------------------------------------------------------------------
12 12 # Copyright (C) 2008 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is
15 15 # in the file COPYING, distributed as part of this software.
16 16 #-------------------------------------------------------------------------------
17 17
18 18 #-------------------------------------------------------------------------------
19 19 # Imports
20 20 #-------------------------------------------------------------------------------
21 21
22 22 import wx
23 23 import wx.stc as stc
24 24
25 25 from wx.py import editwindow
26 26
27 27 import re
28 28
29 29 # FIXME: Need to provide an API for non user-generated display on the
30 30 # screen: this should not be editable by the user.
31 31
32 32 if wx.Platform == '__WXMSW__':
33 33 _DEFAULT_SIZE = 80
34 34 else:
35 35 _DEFAULT_SIZE = 10
36 36
37 37 _DEFAULT_STYLE = {
38 38 'stdout' : 'fore:#0000FF',
39 39 'stderr' : 'fore:#007f00',
40 40 'trace' : 'fore:#FF0000',
41 41
42 42 'default' : 'size:%d' % _DEFAULT_SIZE,
43 43 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
44 44 'bracebad' : 'fore:#000000,back:#FF0000,bold',
45 45
46 46 # properties for the various Python lexer styles
47 47 'comment' : 'fore:#007F00',
48 48 'number' : 'fore:#007F7F',
49 49 'string' : 'fore:#7F007F,italic',
50 50 'char' : 'fore:#7F007F,italic',
51 51 'keyword' : 'fore:#00007F,bold',
52 52 'triple' : 'fore:#7F0000',
53 53 'tripledouble' : 'fore:#7F0000',
54 54 'class' : 'fore:#0000FF,bold,underline',
55 55 'def' : 'fore:#007F7F,bold',
56 56 'operator' : 'bold'
57 57 }
58 58
59 59 # new style numbers
60 60 _STDOUT_STYLE = 15
61 61 _STDERR_STYLE = 16
62 62 _TRACE_STYLE = 17
63 63
64 64
65 65 # system colors
66 66 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
67 67
68 68 #-------------------------------------------------------------------------------
69 69 # The console widget class
70 70 #-------------------------------------------------------------------------------
71 71 class ConsoleWidget(editwindow.EditWindow):
72 72 """ Specialized styled text control view for console-like workflow.
73 73
74 74 This widget is mainly interested in dealing with the prompt and
75 75 keeping the cursor inside the editing line.
76 76 """
77 77
78 78 title = 'Console'
79 79
80 80 style = _DEFAULT_STYLE.copy()
81 81
82 82 # Translation table from ANSI escape sequences to color. Override
83 83 # this to specify your colors.
84 84 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
85 85 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
86 86 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
87 87 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
88 88 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
89 89 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
90 90 '1;34': [12, 'LIGHT BLUE'], '1;35':
91 91 [13, 'MEDIUM VIOLET RED'],
92 92 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
93 93
94 94 # The color of the carret (call _apply_style() after setting)
95 95 carret_color = 'BLACK'
96 96
97 97
98 98 #--------------------------------------------------------------------------
99 99 # Public API
100 100 #--------------------------------------------------------------------------
101 101
102 102 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
103 103 size=wx.DefaultSize, style=0, ):
104 104 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
105 105 self.configure_scintilla()
106 106
107 107 # FIXME: we need to retrieve this from the interpreter.
108 108 self.prompt = \
109 109 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02%i\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
110 110 self.new_prompt(self.prompt % 1)
111 111
112 112 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
113 113 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
114 114
115 115
116 116 def configure_scintilla(self):
117 117 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
118 118 # the widget
119 119 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
120 120 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
121 121 # Also allow Ctrl Shift "=" for poor non US keyboard users.
122 122 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
123 123 stc.STC_CMD_ZOOMIN)
124 124
125 125 #self.CmdKeyAssign(stc.STC_KEY_PRIOR, stc.STC_SCMOD_SHIFT,
126 126 # stc.STC_CMD_PAGEUP)
127 127
128 128 #self.CmdKeyAssign(stc.STC_KEY_NEXT, stc.STC_SCMOD_SHIFT,
129 129 # stc.STC_CMD_PAGEDOWN)
130 130
131 131 # Keys: we need to clear some of the keys the that don't play
132 132 # well with a console.
133 133 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
134 134 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
135 135 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
136 136
137 137
138 138 self.SetEOLMode(stc.STC_EOL_CRLF)
139 139 self.SetWrapMode(stc.STC_WRAP_CHAR)
140 140 self.SetWrapMode(stc.STC_WRAP_WORD)
141 141 self.SetBufferedDraw(True)
142 142 self.SetUseAntiAliasing(True)
143 143 self.SetLayoutCache(stc.STC_CACHE_PAGE)
144 144 self.SetUndoCollection(False)
145 145 self.SetUseTabs(True)
146 146 self.SetIndent(4)
147 147 self.SetTabWidth(4)
148 148
149 149 self.EnsureCaretVisible()
150 150 # we don't want scintilla's autocompletion to choose
151 151 # automaticaly out of a single choice list, as we pop it up
152 152 # automaticaly
153 153 self.AutoCompSetChooseSingle(False)
154 154 self.AutoCompSetMaxHeight(10)
155 155
156 156 self.SetMargins(3, 3) #text is moved away from border with 3px
157 157 # Suppressing Scintilla margins
158 158 self.SetMarginWidth(0, 0)
159 159 self.SetMarginWidth(1, 0)
160 160 self.SetMarginWidth(2, 0)
161 161
162 162 self._apply_style()
163 163
164 164 # Xterm escape sequences
165 165 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
166 166 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
167 167
168 168 #self.SetEdgeMode(stc.STC_EDGE_LINE)
169 169 #self.SetEdgeColumn(80)
170 170
171 171 # styles
172 172 p = self.style
173 173 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
174 174 self.StyleClearAll()
175 175 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
176 176 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
177 177 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
178 178
179 179 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
180 180 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
181 181 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
182 182 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
183 183 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
184 184 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
185 185 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
186 186 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
187 187 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
188 188 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
189 189 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
190 190 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
191 191 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
192 192 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
193 193
194 194
195 195 def write(self, text):
196 196 """ Write given text to buffer, while translating the ansi escape
197 197 sequences.
198 198 """
199 199 title = self.title_pat.split(text)
200 200 if len(title)>0:
201 201 self.title = title[-1]
202 202
203 203 text = self.title_pat.sub('', text)
204 204 segments = self.color_pat.split(text)
205 205 segment = segments.pop(0)
206 206 self.StartStyling(self.GetLength(), 0xFF)
207 207 self.AppendText(segment)
208 208
209 209 if segments:
210 210 for ansi_tag, text in zip(segments[::2], segments[1::2]):
211 211 self.StartStyling(self.GetLength(), 0xFF)
212 212 self.AppendText(text)
213 213
214 214 if ansi_tag == '0':
215 215 style = 0
216 216 else:
217 217 style = self.ANSI_STYLES[ansi_tag][0]
218 218
219 219 self.SetStyling(len(text), style)
220 220
221 221 self.GotoPos(self.GetLength())
222 222 wx.Yield()
223 223
224 224
225 225 def new_prompt(self, prompt):
226 226 """ Prints a prompt at start of line, and move the start of the
227 227 current block there.
228 228
229 229 The prompt can be give with ascii escape sequences.
230 230 """
231 231 self.write(prompt)
232 232 # now we update our cursor giving end of prompt
233 233 self.current_prompt_pos = self.GetLength()
234 234 self.current_prompt_line = self.GetCurrentLine()
235 235 wx.Yield()
236 236 self.EnsureCaretVisible()
237 237
238 238
239 239 def replace_current_edit_buffer(self, text):
240 240 """ Replace currently entered command line with given text.
241 241 """
242 242 self.SetSelection(self.current_prompt_pos, self.GetLength())
243 243 self.ReplaceSelection(text)
244 244 self.GotoPos(self.GetLength())
245 245
246 246
247 247 def get_current_edit_buffer(self):
248 248 """ Returns the text in current edit buffer.
249 249 """
250 250 return self.GetTextRange(self.current_prompt_pos,
251 251 self.GetLength())
252 252
253 253
254 254 #--------------------------------------------------------------------------
255 255 # Private API
256 256 #--------------------------------------------------------------------------
257 257
258 258 def _apply_style(self):
259 259 """ Applies the colors for the different text elements and the
260 260 carret.
261 261 """
262 262 self.SetCaretForeground(self.carret_color)
263 263
264 264 #self.StyleClearAll()
265 265 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
266 266 "fore:#FF0000,back:#0000FF,bold")
267 267 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
268 268 "fore:#000000,back:#FF0000,bold")
269 269
270 270 for style in self.ANSI_STYLES.values():
271 271 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
272 272
273 273
274 274 def write_completion(self, possibilities):
275 275 # FIXME: This is non Wx specific and needs to be moved into
276 276 # the base class.
277 277 current_buffer = self.get_current_edit_buffer()
278 278
279 279 self.write('\n')
280 280 max_len = len(max(possibilities, key=len)) + 1
281 281
282 282 #now we check how much symbol we can put on a line...
283 283 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
284 284 symbols_per_line = max(1, chars_per_line/max_len)
285 285
286 286 pos = 1
287 287 buf = []
288 288 for symbol in possibilities:
289 289 if pos < symbols_per_line:
290 290 buf.append(symbol.ljust(max_len))
291 291 pos += 1
292 292 else:
293 293 buf.append(symbol.rstrip() +'\n')
294 294 pos = 1
295 295 self.write(''.join(buf))
296 296 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
297 297 self.replace_current_edit_buffer(current_buffer)
298 298
299 299
300 300 def pop_completion(self, possibilities, offset=0):
301 301 """ Pops up an autocompletion menu. Offset is the offset
302 302 in characters of the position at which the menu should
303 303 appear, relativ to the cursor.
304 304 """
305 305 self.AutoCompSetIgnoreCase(False)
306 306 self.AutoCompSetAutoHide(False)
307 307 self.AutoCompSetMaxHeight(len(possibilities))
308 308 self.AutoCompShow(offset, " ".join(possibilities))
309 309
310 310
311 311 def scroll_to_bottom(self):
312 312 maxrange = self.GetScrollRange(wx.VERTICAL)
313 313 self.ScrollLines(maxrange)
314 314
315 315
316 316 def _on_enter(self):
317 317 """ Called when the return key is hit.
318 318 """
319 319 pass
320 320
321 321
322 322 def _on_key_down(self, event, skip=True):
323 323 """ Key press callback used for correcting behavior for
324 324 console-like interfaces: the cursor is constraint to be after
325 325 the last prompt.
326 326
327 327 Return True if event as been catched.
328 328 """
329 329 catched = True
330 330 # Intercept some specific keys.
331 331 if event.KeyCode == ord('L') and event.ControlDown() :
332 332 self.scroll_to_bottom()
333 333 elif event.KeyCode == ord('K') and event.ControlDown() :
334 334 self.replace_current_edit_buffer('')
335 335 elif event.KeyCode == wx.WXK_PAGEUP and event.ShiftDown():
336 336 self.ScrollPages(-1)
337 337 elif event.KeyCode == wx.WXK_PAGEDOWN and event.ShiftDown():
338 338 self.ScrollPages(1)
339 339 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
340 340 self.ScrollLines(-1)
341 341 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
342 self.ScrollLinees(1)
342 self.ScrollLines(1)
343 343 else:
344 344 catched = False
345 345
346 346 if self.AutoCompActive():
347 347 event.Skip()
348 348 else:
349 349 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
350 350 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
351 351 catched = True
352 352 self.CallTipCancel()
353 353 self.write('\n')
354 354 self._on_enter()
355 355
356 356 elif event.KeyCode == wx.WXK_HOME:
357 357 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
358 358 self.GotoPos(self.current_prompt_pos)
359 359 catched = True
360 360
361 361 elif event.Modifiers in (wx.MOD_SHIFT, wx.MOD_WIN) :
362 362 # FIXME: This behavior is not ideal: if the selection
363 363 # is already started, it will jump.
364 364 self.SetSelectionStart(self.current_prompt_pos)
365 365 self.SetSelectionEnd(self.GetCurrentPos())
366 366 catched = True
367 367
368 368 elif event.KeyCode == wx.WXK_UP:
369 369 if self.GetCurrentLine() > self.current_prompt_line:
370 370 if self.GetCurrentLine() == self.current_prompt_line + 1 \
371 371 and self.GetColumn(self.GetCurrentPos()) < \
372 372 self.GetColumn(self.current_prompt_pos):
373 373 self.GotoPos(self.current_prompt_pos)
374 374 else:
375 375 event.Skip()
376 376 catched = True
377 377
378 378 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
379 379 if self.GetCurrentPos() > self.current_prompt_pos:
380 380 event.Skip()
381 381 catched = True
382 382
383 383 if skip and not catched:
384 384 event.Skip()
385 385
386 386 return catched
387 387
388 388
389 389 def _on_key_up(self, event, skip=True):
390 390 """ If cursor is outside the editing region, put it back.
391 391 """
392 392 event.Skip()
393 393 if self.GetCurrentPos() < self.current_prompt_pos:
394 394 self.GotoPos(self.current_prompt_pos)
395 395
396 396
397 397
398 398
399 399 if __name__ == '__main__':
400 400 # Some simple code to test the console widget.
401 401 class MainWindow(wx.Frame):
402 402 def __init__(self, parent, id, title):
403 403 wx.Frame.__init__(self, parent, id, title, size=(300,250))
404 404 self._sizer = wx.BoxSizer(wx.VERTICAL)
405 405 self.console_widget = ConsoleWidget(self)
406 406 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
407 407 self.SetSizer(self._sizer)
408 408 self.SetAutoLayout(1)
409 409 self.Show(True)
410 410
411 411 app = wx.PySimpleApp()
412 412 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
413 413 w.SetSize((780, 460))
414 414 w.Show()
415 415
416 416 app.MainLoop()
417 417
418 418
@@ -1,252 +1,252 b''
1 1 # encoding: utf-8 -*- test-case-name:
2 2 # FIXME: Need to add tests.
3 3 # ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
4 4
5 5 """Classes to provide a Wx frontend to the
6 6 IPython.kernel.core.interpreter.
7 7
8 8 """
9 9
10 10 __docformat__ = "restructuredtext en"
11 11
12 12 #-------------------------------------------------------------------------------
13 13 # Copyright (C) 2008 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-------------------------------------------------------------------------------
18 18
19 19 #-------------------------------------------------------------------------------
20 20 # Imports
21 21 #-------------------------------------------------------------------------------
22 22
23 23
24 24 import wx
25 25 import re
26 26 from wx import stc
27 27 from console_widget import ConsoleWidget
28 28 import __builtin__
29 29 from time import sleep
30 30
31 31 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
32 32
33 33 #_COMMAND_BG = '#FAFAF1' # Nice green
34 34 _RUNNING_BUFFER_BG = '#FDFFD3' # Nice yellow
35 35 _ERROR_BG = '#FFF1F1' # Nice red
36 36
37 37 _RUNNING_BUFFER_MARKER = 31
38 38 _ERROR_MARKER = 30
39 39
40 40 #-------------------------------------------------------------------------------
41 41 # Classes to implement the Wx frontend
42 42 #-------------------------------------------------------------------------------
43 class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):
43 class WxController(PrefilterFrontEnd, ConsoleWidget):
44 44
45 45 output_prompt = \
46 46 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
47 47
48 48 #--------------------------------------------------------------------------
49 49 # Public API
50 50 #--------------------------------------------------------------------------
51 51
52 52 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
53 53 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
54 54 *args, **kwds):
55 55 """ Create Shell instance.
56 56 """
57 57 ConsoleWidget.__init__(self, parent, id, pos, size, style)
58 58 PrefilterFrontEnd.__init__(self)
59 59
60 60 # Capture Character keys
61 61 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
62 62
63 63 # Marker for running buffer.
64 64 self.MarkerDefine(_RUNNING_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
65 65 background=_RUNNING_BUFFER_BG)
66 66 # Marker for tracebacks.
67 67 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
68 68 background=_ERROR_BG)
69 69
70 70
71 71
72 72 def do_completion(self):
73 73 """ Do code completion.
74 74 """
75 75 line = self.get_current_edit_buffer()
76 76 new_line, completions = self.complete(line)
77 77 if len(completions)>1:
78 78 self.write_completion(completions)
79 79 self.replace_current_edit_buffer(new_line)
80 80
81 81
82 82 def do_calltip(self):
83 83 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
84 84 symbol = self.get_current_edit_buffer()
85 85 symbol_string = separators.split(symbol)[-1]
86 86 base_symbol_string = symbol_string.split('.')[0]
87 87 if base_symbol_string in self.shell.user_ns:
88 88 symbol = self.shell.user_ns[base_symbol_string]
89 89 elif base_symbol_string in self.shell.user_global_ns:
90 90 symbol = self.shell.user_global_ns[base_symbol_string]
91 91 elif base_symbol_string in __builtin__.__dict__:
92 92 symbol = __builtin__.__dict__[base_symbol_string]
93 93 else:
94 94 return False
95 95 for name in symbol_string.split('.')[1:] + ['__doc__']:
96 96 symbol = getattr(symbol, name)
97 97 try:
98 98 self.AutoCompCancel()
99 99 wx.Yield()
100 100 self.CallTipShow(self.GetCurrentPos(), symbol)
101 101 except:
102 102 # The retrieve symbol couldn't be converted to a string
103 103 pass
104 104
105 105
106 106 def popup_completion(self, create=False):
107 107 """ Updates the popup completion menu if it exists. If create is
108 108 true, open the menu.
109 109 """
110 110 line = self.get_current_edit_buffer()
111 111 if (self.AutoCompActive() and not line[-1] == '.') \
112 112 or create==True:
113 113 suggestion, completions = self.complete(line)
114 114 offset=0
115 115 if completions:
116 116 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
117 117 residual = complete_sep.split(line)[-1]
118 118 offset = len(residual)
119 119 self.pop_completion(completions, offset=offset)
120 120
121 121
122 122 def raw_input(self, prompt):
123 123 """ A replacement from python's raw_input.
124 124 """
125 125 self.new_prompt(prompt)
126 126 self.waiting = True
127 127 self.__old_on_enter = self._on_enter
128 128 def my_on_enter():
129 129 self.waiting = False
130 130 self._on_enter = my_on_enter
131 # Busy waiting, ugly.
131 # XXX: Busy waiting, ugly.
132 132 while self.waiting:
133 133 wx.Yield()
134 134 sleep(0.1)
135 135 self._on_enter = self.__old_on_enter
136 136 return self.get_current_edit_buffer().rstrip('\n')
137 137
138 138
139 139 def execute(self, python_string, raw_string=None):
140 140 self.CallTipCancel()
141 141 self._cursor = wx.BusyCursor()
142 142 if raw_string is None:
143 143 raw_string = python_string
144 144 end_line = self.current_prompt_line \
145 145 + max(1, len(raw_string.split('\n'))-1)
146 146 for i in range(self.current_prompt_line, end_line):
147 147 self.MarkerAdd(i, _RUNNING_BUFFER_MARKER)
148 148 # Update the display:
149 149 wx.Yield()
150 150 ## Remove the trailing "\n" for cleaner display
151 151 #self.SetSelection(self.GetLength()-1, self.GetLength())
152 152 #self.ReplaceSelection('')
153 153 self.GotoPos(self.GetLength())
154 154 self.__old_raw_input = __builtin__.raw_input
155 155 __builtin__.raw_input = self.raw_input
156 156 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
157 157 __builtin__.raw_input = self.__old_raw_input
158 158
159 159
160 160 def after_execute(self):
161 161 PrefilterFrontEnd.after_execute(self)
162 162 if hasattr(self, '_cursor'):
163 163 del self._cursor
164 164
165 165
166 166 def show_traceback(self):
167 167 start_line = self.GetCurrentLine()
168 168 PrefilterFrontEnd.show_traceback(self)
169 169 wx.Yield()
170 170 for i in range(start_line, self.GetCurrentLine()):
171 171 self.MarkerAdd(i, _ERROR_MARKER)
172 172
173 173
174 174 #--------------------------------------------------------------------------
175 175 # Private API
176 176 #--------------------------------------------------------------------------
177 177
178 178
179 179 def _on_key_down(self, event, skip=True):
180 180 """ Capture the character events, let the parent
181 181 widget handle them, and put our logic afterward.
182 182 """
183 183 current_line_number = self.GetCurrentLine()
184 184 if event.KeyCode == ord('('):
185 185 event.Skip()
186 186 self.do_calltip()
187 187 elif self.AutoCompActive():
188 188 event.Skip()
189 189 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
190 190 wx.CallAfter(self.popup_completion, create=True)
191 191 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
192 192 wx.WXK_RIGHT):
193 193 wx.CallAfter(self.popup_completion)
194 194 else:
195 195 # Up history
196 196 if event.KeyCode == wx.WXK_UP and (
197 197 ( current_line_number == self.current_prompt_line and
198 198 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
199 199 or event.ControlDown() ):
200 200 new_buffer = self.get_history_previous(
201 201 self.get_current_edit_buffer())
202 202 if new_buffer is not None:
203 203 self.replace_current_edit_buffer(new_buffer)
204 204 if self.GetCurrentLine() > self.current_prompt_line:
205 205 # Go to first line, for seemless history up.
206 206 self.GotoPos(self.current_prompt_pos)
207 207 # Down history
208 208 elif event.KeyCode == wx.WXK_DOWN and (
209 209 ( current_line_number == self.LineCount -1 and
210 210 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
211 211 or event.ControlDown() ):
212 212 new_buffer = self.get_history_next()
213 213 if new_buffer is not None:
214 214 self.replace_current_edit_buffer(new_buffer)
215 215 elif event.KeyCode == ord('\t'):
216 216 last_line = self.get_current_edit_buffer().split('\n')[-1]
217 217 if not re.match(r'^\s*$', last_line):
218 218 self.do_completion()
219 219 else:
220 220 event.Skip()
221 221 else:
222 222 ConsoleWidget._on_key_down(self, event, skip=skip)
223 223
224 224
225 225 def _on_key_up(self, event, skip=True):
226 226 if event.KeyCode == 59:
227 227 # Intercepting '.'
228 228 event.Skip()
229 229 self.popup_completion(create=True)
230 230 else:
231 231 ConsoleWidget._on_key_up(self, event, skip=skip)
232 232
233 233
234 234 if __name__ == '__main__':
235 235 class MainWindow(wx.Frame):
236 236 def __init__(self, parent, id, title):
237 237 wx.Frame.__init__(self, parent, id, title, size=(300,250))
238 238 self._sizer = wx.BoxSizer(wx.VERTICAL)
239 self.shell = IPythonWxController(self)
239 self.shell = WxController(self)
240 240 self._sizer.Add(self.shell, 1, wx.EXPAND)
241 241 self.SetSizer(self._sizer)
242 242 self.SetAutoLayout(1)
243 243 self.Show(True)
244 244
245 245 app = wx.PySimpleApp()
246 246 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
247 247 frame.shell.SetFocus()
248 248 frame.SetSize((680, 460))
249 249 self = frame.shell
250 250
251 251 app.MainLoop()
252 252
General Comments 0
You need to be logged in to leave comments. Login now