Show More
@@ -151,7 +151,12 else: | |||||
151 | self._thread = ht |
|
151 | self._thread = ht | |
152 | self.pid = pid |
|
152 | self.pid = pid | |
153 |
|
153 | |||
154 | winprocess.AssignProcessToJobObject(self._job, hp) |
|
154 | # XXX: A try/except to fix UAC-related problems under | |
|
155 | # Windows Vista, when reparenting jobs. | |||
|
156 | try: | |||
|
157 | winprocess.AssignProcessToJobObject(self._job, hp) | |||
|
158 | except WindowsError: | |||
|
159 | pass | |||
155 | winprocess.ResumeThread(ht) |
|
160 | winprocess.ResumeThread(ht) | |
156 |
|
161 | |||
157 | if p2cread is not None: |
|
162 | if p2cread is not None: |
@@ -56,6 +56,9 class LineFrontEndBase(FrontEndBase): | |||||
56 | # programatic control of the frontend. |
|
56 | # programatic control of the frontend. | |
57 | last_result = dict(number=0) |
|
57 | last_result = dict(number=0) | |
58 |
|
58 | |||
|
59 | # The last prompt displayed. Useful for continuation prompts. | |||
|
60 | last_prompt = '' | |||
|
61 | ||||
59 | # The input buffer being edited |
|
62 | # The input buffer being edited | |
60 | input_buffer = '' |
|
63 | input_buffer = '' | |
61 |
|
64 | |||
@@ -301,13 +304,8 class LineFrontEndBase(FrontEndBase): | |||||
301 |
|
304 | |||
302 | def continuation_prompt(self): |
|
305 | def continuation_prompt(self): | |
303 | """Returns the current continuation prompt. |
|
306 | """Returns the current continuation prompt. | |
304 | Overridden to generate a continuation prompt matching the length of the |
|
307 | """ | |
305 | current prompt.""" |
|
308 | return ("."*(len(self.last_prompt)-2) + ': ') | |
306 |
|
||||
307 | # FIXME: This is a bad hack.. I need to find a way to use the 'Prompt2' |
|
|||
308 | # class in IPython/kernel/prompts.py. Basically, I am trying to get the |
|
|||
309 | # length of the current prompt ("In ['number']"). |
|
|||
310 | return ("."*(5+len(str(self.last_result['number']))) + ':') |
|
|||
311 |
|
309 | |||
312 |
|
310 | |||
313 | def execute_command(self, command, hidden=False): |
|
311 | def execute_command(self, command, hidden=False): |
@@ -25,6 +25,8 import wx.stc as stc | |||||
25 | from wx.py import editwindow |
|
25 | from wx.py import editwindow | |
26 | import time |
|
26 | import time | |
27 | import sys |
|
27 | import sys | |
|
28 | import string | |||
|
29 | ||||
28 | LINESEP = '\n' |
|
30 | LINESEP = '\n' | |
29 | if sys.platform == 'win32': |
|
31 | if sys.platform == 'win32': | |
30 | LINESEP = '\n\r' |
|
32 | LINESEP = '\n\r' | |
@@ -33,20 +35,26 import re | |||||
33 |
|
35 | |||
34 | # FIXME: Need to provide an API for non user-generated display on the |
|
36 | # FIXME: Need to provide an API for non user-generated display on the | |
35 | # screen: this should not be editable by the user. |
|
37 | # screen: this should not be editable by the user. | |
|
38 | #------------------------------------------------------------------------------- | |||
|
39 | # Constants | |||
|
40 | #------------------------------------------------------------------------------- | |||
|
41 | _COMPLETE_BUFFER_MARKER = 31 | |||
|
42 | _ERROR_MARKER = 30 | |||
|
43 | _INPUT_MARKER = 29 | |||
36 |
|
44 | |||
37 | _DEFAULT_SIZE = 10 |
|
45 | _DEFAULT_SIZE = 10 | |
38 | if sys.platform == 'darwin': |
|
46 | if sys.platform == 'darwin': | |
39 | _DEFAULT_SIZE = 12 |
|
47 | _DEFAULT_SIZE = 12 | |
40 |
|
48 | |||
41 | _DEFAULT_STYLE = { |
|
49 | _DEFAULT_STYLE = { | |
42 | 'stdout' : 'fore:#0000FF', |
|
50 | #background definition | |
43 | 'stderr' : 'fore:#007f00', |
|
|||
44 | 'trace' : 'fore:#FF0000', |
|
|||
45 |
|
||||
46 | 'default' : 'size:%d' % _DEFAULT_SIZE, |
|
51 | 'default' : 'size:%d' % _DEFAULT_SIZE, | |
47 | 'bracegood' : 'fore:#00AA00,back:#000000,bold', |
|
52 | 'bracegood' : 'fore:#00AA00,back:#000000,bold', | |
48 | 'bracebad' : 'fore:#FF0000,back:#000000,bold', |
|
53 | 'bracebad' : 'fore:#FF0000,back:#000000,bold', | |
49 |
|
54 | |||
|
55 | # Edge column: a number of None | |||
|
56 | 'edge_column' : -1, | |||
|
57 | ||||
50 | # properties for the various Python lexer styles |
|
58 | # properties for the various Python lexer styles | |
51 | 'comment' : 'fore:#007F00', |
|
59 | 'comment' : 'fore:#007F00', | |
52 | 'number' : 'fore:#007F7F', |
|
60 | 'number' : 'fore:#007F7F', | |
@@ -69,6 +77,44 _TRACE_STYLE = 17 | |||||
69 | # system colors |
|
77 | # system colors | |
70 | #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND) |
|
78 | #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND) | |
71 |
|
79 | |||
|
80 | # Translation table from ANSI escape sequences to color. | |||
|
81 | ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'], | |||
|
82 | '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'], | |||
|
83 | '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'], | |||
|
84 | '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'], | |||
|
85 | '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'], | |||
|
86 | '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'], | |||
|
87 | '1;34': [12, 'LIGHT BLUE'], '1;35': | |||
|
88 | [13, 'MEDIUM VIOLET RED'], | |||
|
89 | '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']} | |||
|
90 | ||||
|
91 | #we define platform specific fonts | |||
|
92 | if wx.Platform == '__WXMSW__': | |||
|
93 | FACES = { 'times': 'Times New Roman', | |||
|
94 | 'mono' : 'Courier New', | |||
|
95 | 'helv' : 'Arial', | |||
|
96 | 'other': 'Comic Sans MS', | |||
|
97 | 'size' : 10, | |||
|
98 | 'size2': 8, | |||
|
99 | } | |||
|
100 | elif wx.Platform == '__WXMAC__': | |||
|
101 | FACES = { 'times': 'Times New Roman', | |||
|
102 | 'mono' : 'Monaco', | |||
|
103 | 'helv' : 'Arial', | |||
|
104 | 'other': 'Comic Sans MS', | |||
|
105 | 'size' : 10, | |||
|
106 | 'size2': 8, | |||
|
107 | } | |||
|
108 | else: | |||
|
109 | FACES = { 'times': 'Times', | |||
|
110 | 'mono' : 'Courier', | |||
|
111 | 'helv' : 'Helvetica', | |||
|
112 | 'other': 'new century schoolbook', | |||
|
113 | 'size' : 10, | |||
|
114 | 'size2': 8, | |||
|
115 | } | |||
|
116 | ||||
|
117 | ||||
72 | #------------------------------------------------------------------------------- |
|
118 | #------------------------------------------------------------------------------- | |
73 | # The console widget class |
|
119 | # The console widget class | |
74 | #------------------------------------------------------------------------------- |
|
120 | #------------------------------------------------------------------------------- | |
@@ -83,6 +129,9 class ConsoleWidget(editwindow.EditWindow): | |||||
83 | # stored. |
|
129 | # stored. | |
84 | title = 'Console' |
|
130 | title = 'Console' | |
85 |
|
131 | |||
|
132 | # Last prompt printed | |||
|
133 | last_prompt = '' | |||
|
134 | ||||
86 | # The buffer being edited. |
|
135 | # The buffer being edited. | |
87 | def _set_input_buffer(self, string): |
|
136 | def _set_input_buffer(self, string): | |
88 | self.SetSelection(self.current_prompt_pos, self.GetLength()) |
|
137 | self.SetSelection(self.current_prompt_pos, self.GetLength()) | |
@@ -103,19 +152,11 class ConsoleWidget(editwindow.EditWindow): | |||||
103 |
|
152 | |||
104 | # Translation table from ANSI escape sequences to color. Override |
|
153 | # Translation table from ANSI escape sequences to color. Override | |
105 | # this to specify your colors. |
|
154 | # this to specify your colors. | |
106 | ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'], |
|
155 | ANSI_STYLES = ANSI_STYLES.copy() | |
107 | '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'], |
|
|||
108 | '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'], |
|
|||
109 | '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'], |
|
|||
110 | '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'], |
|
|||
111 | '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'], |
|
|||
112 | '1;34': [12, 'LIGHT BLUE'], '1;35': |
|
|||
113 | [13, 'MEDIUM VIOLET RED'], |
|
|||
114 | '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']} |
|
|||
115 |
|
||||
116 | # The color of the carret (call _apply_style() after setting) |
|
|||
117 | carret_color = 'BLACK' |
|
|||
118 |
|
156 | |||
|
157 | # Font faces | |||
|
158 | faces = FACES.copy() | |||
|
159 | ||||
119 | # Store the last time a refresh was done |
|
160 | # Store the last time a refresh was done | |
120 | _last_refresh_time = 0 |
|
161 | _last_refresh_time = 0 | |
121 |
|
162 | |||
@@ -126,7 +167,11 class ConsoleWidget(editwindow.EditWindow): | |||||
126 | def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, |
|
167 | def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, | |
127 | size=wx.DefaultSize, style=wx.WANTS_CHARS, ): |
|
168 | size=wx.DefaultSize, style=wx.WANTS_CHARS, ): | |
128 | editwindow.EditWindow.__init__(self, parent, id, pos, size, style) |
|
169 | editwindow.EditWindow.__init__(self, parent, id, pos, size, style) | |
129 |
self. |
|
170 | self.configure_scintilla() | |
|
171 | # Track if 'enter' key as ever been processed | |||
|
172 | # This variable will only be reallowed until key goes up | |||
|
173 | self.enter_catched = False | |||
|
174 | self.current_prompt_pos = 0 | |||
130 |
|
175 | |||
131 | self.Bind(wx.EVT_KEY_DOWN, self._on_key_down) |
|
176 | self.Bind(wx.EVT_KEY_DOWN, self._on_key_down) | |
132 | self.Bind(wx.EVT_KEY_UP, self._on_key_up) |
|
177 | self.Bind(wx.EVT_KEY_UP, self._on_key_up) | |
@@ -193,7 +238,16 class ConsoleWidget(editwindow.EditWindow): | |||||
193 | self.current_prompt_pos = self.GetLength() |
|
238 | self.current_prompt_pos = self.GetLength() | |
194 | self.current_prompt_line = self.GetCurrentLine() |
|
239 | self.current_prompt_line = self.GetCurrentLine() | |
195 | self.EnsureCaretVisible() |
|
240 | self.EnsureCaretVisible() | |
|
241 | self.last_prompt = prompt | |||
|
242 | ||||
196 |
|
243 | |||
|
244 | def continuation_prompt(self): | |||
|
245 | """Returns the current continuation prompt. | |||
|
246 | """ | |||
|
247 | # ASCII-less prompt | |||
|
248 | ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2]) | |||
|
249 | return "."*(len(ascii_less)-2) + ': ' | |||
|
250 | ||||
197 |
|
251 | |||
198 | def scroll_to_bottom(self): |
|
252 | def scroll_to_bottom(self): | |
199 | maxrange = self.GetScrollRange(wx.VERTICAL) |
|
253 | maxrange = self.GetScrollRange(wx.VERTICAL) | |
@@ -217,14 +271,6 class ConsoleWidget(editwindow.EditWindow): | |||||
217 | return self.GetSize()[0]/self.GetCharWidth() |
|
271 | return self.GetSize()[0]/self.GetCharWidth() | |
218 |
|
272 | |||
219 |
|
273 | |||
220 | def clear_screen(self): |
|
|||
221 | """ Empty completely the widget. |
|
|||
222 | """ |
|
|||
223 | self.ClearAll() |
|
|||
224 | self.new_prompt(self.input_prompt_template.substitute( |
|
|||
225 | number=(self.last_result['number'] + 1))) |
|
|||
226 |
|
||||
227 |
|
||||
228 |
|
274 | |||
229 | #-------------------------------------------------------------------------- |
|
275 | #-------------------------------------------------------------------------- | |
230 | # EditWindow API |
|
276 | # EditWindow API | |
@@ -237,26 +283,40 class ConsoleWidget(editwindow.EditWindow): | |||||
237 | """ |
|
283 | """ | |
238 |
|
284 | |||
239 | #-------------------------------------------------------------------------- |
|
285 | #-------------------------------------------------------------------------- | |
240 |
# |
|
286 | # Styling API | |
241 | #-------------------------------------------------------------------------- |
|
287 | #-------------------------------------------------------------------------- | |
242 |
|
||||
243 | def _apply_style(self): |
|
|||
244 | """ Applies the colors for the different text elements and the |
|
|||
245 | carret. |
|
|||
246 | """ |
|
|||
247 | self.SetCaretForeground(self.carret_color) |
|
|||
248 |
|
288 | |||
249 | #self.StyleClearAll() |
|
289 | def configure_scintilla(self): | |
250 | self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, |
|
290 | ||
251 | "fore:#FF0000,back:#0000FF,bold") |
|
291 | p = self.style | |
252 | self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, |
|
292 | ||
253 | "fore:#000000,back:#FF0000,bold") |
|
293 | #First we define the special background colors | |
|
294 | if 'trace' in p: | |||
|
295 | _COMPLETE_BUFFER_BG = p['trace'] | |||
|
296 | else: | |||
|
297 | _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green | |||
|
298 | ||||
|
299 | if 'stdout' in p: | |||
|
300 | _INPUT_BUFFER_BG = p['stdout'] | |||
|
301 | else: | |||
|
302 | _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow | |||
|
303 | ||||
|
304 | if 'stderr' in p: | |||
|
305 | _ERROR_BG = p['stderr'] | |||
|
306 | else: | |||
|
307 | _ERROR_BG = '#FFF1F1' # Nice red | |||
254 |
|
308 | |||
255 | for style in self.ANSI_STYLES.values(): |
|
309 | # Marker for complete buffer. | |
256 | self.StyleSetSpec(style[0], "bold,fore:%s" % style[1]) |
|
310 | self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND, | |
|
311 | background = _COMPLETE_BUFFER_BG) | |||
|
312 | ||||
|
313 | # Marker for current input buffer. | |||
|
314 | self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND, | |||
|
315 | background = _INPUT_BUFFER_BG) | |||
|
316 | # Marker for tracebacks. | |||
|
317 | self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND, | |||
|
318 | background = _ERROR_BG) | |||
257 |
|
319 | |||
258 |
|
||||
259 | def _configure_scintilla(self): |
|
|||
260 | self.SetEOLMode(stc.STC_EOL_LF) |
|
320 | self.SetEOLMode(stc.STC_EOL_LF) | |
261 |
|
321 | |||
262 | # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside |
|
322 | # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside | |
@@ -278,7 +338,12 class ConsoleWidget(editwindow.EditWindow): | |||||
278 | self.SetWrapMode(stc.STC_WRAP_CHAR) |
|
338 | self.SetWrapMode(stc.STC_WRAP_CHAR) | |
279 | self.SetWrapMode(stc.STC_WRAP_WORD) |
|
339 | self.SetWrapMode(stc.STC_WRAP_WORD) | |
280 | self.SetBufferedDraw(True) |
|
340 | self.SetBufferedDraw(True) | |
281 | self.SetUseAntiAliasing(True) |
|
341 | ||
|
342 | if 'antialiasing' in p: | |||
|
343 | self.SetUseAntiAliasing(p['antialiasing']) | |||
|
344 | else: | |||
|
345 | self.SetUseAntiAliasing(True) | |||
|
346 | ||||
282 | self.SetLayoutCache(stc.STC_CACHE_PAGE) |
|
347 | self.SetLayoutCache(stc.STC_CACHE_PAGE) | |
283 | self.SetUndoCollection(False) |
|
348 | self.SetUndoCollection(False) | |
284 | self.SetUseTabs(True) |
|
349 | self.SetUseTabs(True) | |
@@ -299,38 +364,108 class ConsoleWidget(editwindow.EditWindow): | |||||
299 | self.SetMarginWidth(1, 0) |
|
364 | self.SetMarginWidth(1, 0) | |
300 | self.SetMarginWidth(2, 0) |
|
365 | self.SetMarginWidth(2, 0) | |
301 |
|
366 | |||
302 | self._apply_style() |
|
|||
303 |
|
||||
304 | # Xterm escape sequences |
|
367 | # Xterm escape sequences | |
305 | self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?') |
|
368 | self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?') | |
306 | self.title_pat = re.compile('\x1b]0;(.*?)\x07') |
|
369 | self.title_pat = re.compile('\x1b]0;(.*?)\x07') | |
307 |
|
370 | |||
308 | #self.SetEdgeMode(stc.STC_EDGE_LINE) |
|
|||
309 | #self.SetEdgeColumn(80) |
|
|||
310 |
|
||||
311 | # styles |
|
371 | # styles | |
312 | p = self.style |
|
372 | ||
313 | self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default']) |
|
373 | if 'carret_color' in p: | |
|
374 | self.SetCaretForeground(p['carret_color']) | |||
|
375 | else: | |||
|
376 | self.SetCaretForeground('BLACK') | |||
|
377 | ||||
|
378 | if 'background_color' in p: | |||
|
379 | background_color = p['background_color'] | |||
|
380 | else: | |||
|
381 | background_color = 'WHITE' | |||
|
382 | ||||
|
383 | if 'default' in p: | |||
|
384 | if 'back' not in p['default']: | |||
|
385 | p['default'] += ',back:%s' % background_color | |||
|
386 | if 'size' not in p['default']: | |||
|
387 | p['default'] += ',size:%s' % self.faces['size'] | |||
|
388 | if 'face' not in p['default']: | |||
|
389 | p['default'] += ',face:%s' % self.faces['mono'] | |||
|
390 | ||||
|
391 | self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default']) | |||
|
392 | else: | |||
|
393 | self.StyleSetSpec(stc.STC_STYLE_DEFAULT, | |||
|
394 | "fore:%s,back:%s,size:%d,face:%s" | |||
|
395 | % (self.ANSI_STYLES['0;30'][1], | |||
|
396 | background_color, | |||
|
397 | self.faces['size'], self.faces['mono'])) | |||
|
398 | ||||
|
399 | #all styles = default one | |||
314 | self.StyleClearAll() |
|
400 | self.StyleClearAll() | |
315 | self.StyleSetSpec(_STDOUT_STYLE, p['stdout']) |
|
401 | ||
316 | self.StyleSetSpec(_STDERR_STYLE, p['stderr']) |
|
402 | # XXX: two lines below are usefull if not using the lexer | |
317 | self.StyleSetSpec(_TRACE_STYLE, p['trace']) |
|
403 | #for style in self.ANSI_STYLES.values(): | |
318 |
|
404 | # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1]) | ||
319 | self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood']) |
|
405 | ||
320 | self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad']) |
|
406 | #prompt definition | |
321 | self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment']) |
|
407 | if 'prompt_in1' in p: | |
322 | self.StyleSetSpec(stc.STC_P_NUMBER, p['number']) |
|
408 | self.prompt_in1 = p['prompt_in1'] | |
323 | self.StyleSetSpec(stc.STC_P_STRING, p['string']) |
|
409 | else: | |
324 | self.StyleSetSpec(stc.STC_P_CHARACTER, p['char']) |
|
410 | self.prompt_in1 = \ | |
325 | self.StyleSetSpec(stc.STC_P_WORD, p['keyword']) |
|
411 | '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02' | |
326 | self.StyleSetSpec(stc.STC_P_WORD2, p['keyword']) |
|
|||
327 | self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple']) |
|
|||
328 | self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble']) |
|
|||
329 | self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class']) |
|
|||
330 | self.StyleSetSpec(stc.STC_P_DEFNAME, p['def']) |
|
|||
331 | self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator']) |
|
|||
332 | self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment']) |
|
|||
333 |
|
412 | |||
|
413 | if 'prompt_out' in p: | |||
|
414 | self.prompt_out = p['prompt_out'] | |||
|
415 | else: | |||
|
416 | self.prompt_out = \ | |||
|
417 | '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02' | |||
|
418 | ||||
|
419 | self.output_prompt_template = string.Template(self.prompt_out) | |||
|
420 | self.input_prompt_template = string.Template(self.prompt_in1) | |||
|
421 | ||||
|
422 | if 'stdout' in p: | |||
|
423 | self.StyleSetSpec(_STDOUT_STYLE, p['stdout']) | |||
|
424 | if 'stderr' in p: | |||
|
425 | self.StyleSetSpec(_STDERR_STYLE, p['stderr']) | |||
|
426 | if 'trace' in p: | |||
|
427 | self.StyleSetSpec(_TRACE_STYLE, p['trace']) | |||
|
428 | if 'bracegood' in p: | |||
|
429 | self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood']) | |||
|
430 | if 'bracebad' in p: | |||
|
431 | self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad']) | |||
|
432 | if 'comment' in p: | |||
|
433 | self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment']) | |||
|
434 | if 'number' in p: | |||
|
435 | self.StyleSetSpec(stc.STC_P_NUMBER, p['number']) | |||
|
436 | if 'string' in p: | |||
|
437 | self.StyleSetSpec(stc.STC_P_STRING, p['string']) | |||
|
438 | if 'char' in p: | |||
|
439 | self.StyleSetSpec(stc.STC_P_CHARACTER, p['char']) | |||
|
440 | if 'keyword' in p: | |||
|
441 | self.StyleSetSpec(stc.STC_P_WORD, p['keyword']) | |||
|
442 | if 'keyword' in p: | |||
|
443 | self.StyleSetSpec(stc.STC_P_WORD2, p['keyword']) | |||
|
444 | if 'triple' in p: | |||
|
445 | self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple']) | |||
|
446 | if 'tripledouble' in p: | |||
|
447 | self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble']) | |||
|
448 | if 'class' in p: | |||
|
449 | self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class']) | |||
|
450 | if 'def' in p: | |||
|
451 | self.StyleSetSpec(stc.STC_P_DEFNAME, p['def']) | |||
|
452 | if 'operator' in p: | |||
|
453 | self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator']) | |||
|
454 | if 'comment' in p: | |||
|
455 | self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment']) | |||
|
456 | ||||
|
457 | if 'edge_column' in p: | |||
|
458 | edge_column = p['edge_column'] | |||
|
459 | if edge_column is not None and edge_column > 0: | |||
|
460 | #we add a vertical line to console widget | |||
|
461 | self.SetEdgeMode(stc.STC_EDGE_LINE) | |||
|
462 | self.SetEdgeColumn(88) | |||
|
463 | ||||
|
464 | ||||
|
465 | #-------------------------------------------------------------------------- | |||
|
466 | # Private API | |||
|
467 | #-------------------------------------------------------------------------- | |||
|
468 | ||||
334 | def _on_key_down(self, event, skip=True): |
|
469 | def _on_key_down(self, event, skip=True): | |
335 | """ Key press callback used for correcting behavior for |
|
470 | """ Key press callback used for correcting behavior for | |
336 | console-like interfaces: the cursor is constraint to be after |
|
471 | console-like interfaces: the cursor is constraint to be after | |
@@ -369,14 +504,16 class ConsoleWidget(editwindow.EditWindow): | |||||
369 | if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \ |
|
504 | if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \ | |
370 | event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): |
|
505 | event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): | |
371 | catched = True |
|
506 | catched = True | |
372 |
self. |
|
507 | if not self.enter_catched: | |
373 | self.write('\n', refresh=False) |
|
508 | self.CallTipCancel() | |
374 | # Under windows scintilla seems to be doing funny stuff to the |
|
509 | self.write('\n', refresh=False) | |
375 | # line returns here, but the getter for input_buffer filters |
|
510 | # Under windows scintilla seems to be doing funny | |
376 | # this out. |
|
511 | # stuff to the line returns here, but the getter for | |
377 | if sys.platform == 'win32': |
|
512 | # input_buffer filters this out. | |
378 | self.input_buffer = self.input_buffer |
|
513 | if sys.platform == 'win32': | |
379 | self._on_enter() |
|
514 | self.input_buffer = self.input_buffer | |
|
515 | self._on_enter() | |||
|
516 | self.enter_catched = True | |||
380 |
|
517 | |||
381 | elif event.KeyCode == wx.WXK_HOME: |
|
518 | elif event.KeyCode == wx.WXK_HOME: | |
382 | if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): |
|
519 | if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): | |
@@ -481,15 +618,16 class ConsoleWidget(editwindow.EditWindow): | |||||
481 | self.GotoPos(current_pos + 1 + |
|
618 | self.GotoPos(current_pos + 1 + | |
482 | len(continuation_prompt)) |
|
619 | len(continuation_prompt)) | |
483 | return True |
|
620 | return True | |
484 | return False |
|
|||
485 |
|
621 | |||
|
622 | self.enter_catched = False #we re-allow enter event processing | |||
|
623 | return False | |||
486 |
|
624 | |||
487 |
|
625 | |||
488 | if __name__ == '__main__': |
|
626 | if __name__ == '__main__': | |
489 | # Some simple code to test the console widget. |
|
627 | # Some simple code to test the console widget. | |
490 | class MainWindow(wx.Frame): |
|
628 | class MainWindow(wx.Frame): | |
491 | def __init__(self, parent, id, title): |
|
629 | def __init__(self, parent, id, title): | |
492 | wx.Frame.__init__(self, parent, id, title, size=(300,250)) |
|
630 | wx.Frame.__init__(self, parent, id, title, size=(300, 250)) | |
493 | self._sizer = wx.BoxSizer(wx.VERTICAL) |
|
631 | self._sizer = wx.BoxSizer(wx.VERTICAL) | |
494 | self.console_widget = ConsoleWidget(self) |
|
632 | self.console_widget = ConsoleWidget(self) | |
495 | self._sizer.Add(self.console_widget, 1, wx.EXPAND) |
|
633 | self._sizer.Add(self.console_widget, 1, wx.EXPAND) |
@@ -27,35 +27,17 import re | |||||
27 | import __builtin__ |
|
27 | import __builtin__ | |
28 | import sys |
|
28 | import sys | |
29 | from threading import Lock |
|
29 | from threading import Lock | |
30 | import string |
|
|||
31 |
|
30 | |||
32 | import wx |
|
31 | import wx | |
33 | from wx import stc |
|
32 | from wx import stc | |
34 |
|
33 | |||
35 | # Ipython-specific imports. |
|
34 | # Ipython-specific imports. | |
36 | from IPython.frontend._process import PipedProcess |
|
35 | from IPython.frontend._process import PipedProcess | |
37 | from console_widget import ConsoleWidget |
|
36 | from console_widget import ConsoleWidget, _COMPLETE_BUFFER_MARKER, \ | |
|
37 | _ERROR_MARKER, _INPUT_MARKER | |||
38 | from IPython.frontend.prefilterfrontend import PrefilterFrontEnd |
|
38 | from IPython.frontend.prefilterfrontend import PrefilterFrontEnd | |
39 |
|
39 | |||
40 | #------------------------------------------------------------------------------- |
|
40 | #------------------------------------------------------------------------------- | |
41 | # Constants |
|
|||
42 | #------------------------------------------------------------------------------- |
|
|||
43 |
|
||||
44 | _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green |
|
|||
45 | _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow |
|
|||
46 | _ERROR_BG = '#FFF1F1' # Nice red |
|
|||
47 |
|
||||
48 | _COMPLETE_BUFFER_MARKER = 31 |
|
|||
49 | _ERROR_MARKER = 30 |
|
|||
50 | _INPUT_MARKER = 29 |
|
|||
51 |
|
||||
52 | prompt_in1 = \ |
|
|||
53 | '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02' |
|
|||
54 |
|
||||
55 | prompt_out = \ |
|
|||
56 | '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02' |
|
|||
57 |
|
||||
58 | #------------------------------------------------------------------------------- |
|
|||
59 | # Classes to implement the Wx frontend |
|
41 | # Classes to implement the Wx frontend | |
60 | #------------------------------------------------------------------------------- |
|
42 | #------------------------------------------------------------------------------- | |
61 | class WxController(ConsoleWidget, PrefilterFrontEnd): |
|
43 | class WxController(ConsoleWidget, PrefilterFrontEnd): | |
@@ -65,11 +47,7 class WxController(ConsoleWidget, PrefilterFrontEnd): | |||||
65 | This class inherits from ConsoleWidget, that provides a console-like |
|
47 | This class inherits from ConsoleWidget, that provides a console-like | |
66 | widget to provide a text-rendering widget suitable for a terminal. |
|
48 | widget to provide a text-rendering widget suitable for a terminal. | |
67 | """ |
|
49 | """ | |
68 |
|
50 | |||
69 | output_prompt_template = string.Template(prompt_out) |
|
|||
70 |
|
||||
71 | input_prompt_template = string.Template(prompt_in1) |
|
|||
72 |
|
||||
73 | # Print debug info on what is happening to the console. |
|
51 | # Print debug info on what is happening to the console. | |
74 | debug = False |
|
52 | debug = False | |
75 |
|
53 | |||
@@ -137,25 +115,24 class WxController(ConsoleWidget, PrefilterFrontEnd): | |||||
137 | def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, |
|
115 | def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, | |
138 | size=wx.DefaultSize, |
|
116 | size=wx.DefaultSize, | |
139 | style=wx.CLIP_CHILDREN|wx.WANTS_CHARS, |
|
117 | style=wx.CLIP_CHILDREN|wx.WANTS_CHARS, | |
|
118 | styledef=None, | |||
140 | *args, **kwds): |
|
119 | *args, **kwds): | |
141 | """ Create Shell instance. |
|
120 | """ Create Shell instance. | |
|
121 | ||||
|
122 | Parameters | |||
|
123 | ----------- | |||
|
124 | styledef : dict, optional | |||
|
125 | styledef is the dictionary of options used to define the | |||
|
126 | style. | |||
142 | """ |
|
127 | """ | |
|
128 | if styledef is not None: | |||
|
129 | self.style = styledef | |||
143 | ConsoleWidget.__init__(self, parent, id, pos, size, style) |
|
130 | ConsoleWidget.__init__(self, parent, id, pos, size, style) | |
144 | PrefilterFrontEnd.__init__(self, **kwds) |
|
131 | PrefilterFrontEnd.__init__(self, **kwds) | |
145 |
|
132 | |||
146 | # Stick in our own raw_input: |
|
133 | # Stick in our own raw_input: | |
147 | self.ipython0.raw_input = self.raw_input |
|
134 | self.ipython0.raw_input = self.raw_input | |
148 |
|
135 | |||
149 | # Marker for complete buffer. |
|
|||
150 | self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND, |
|
|||
151 | background=_COMPLETE_BUFFER_BG) |
|
|||
152 | # Marker for current input buffer. |
|
|||
153 | self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND, |
|
|||
154 | background=_INPUT_BUFFER_BG) |
|
|||
155 | # Marker for tracebacks. |
|
|||
156 | self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND, |
|
|||
157 | background=_ERROR_BG) |
|
|||
158 |
|
||||
159 | # A time for flushing the write buffer |
|
136 | # A time for flushing the write buffer | |
160 | BUFFER_FLUSH_TIMER_ID = 100 |
|
137 | BUFFER_FLUSH_TIMER_ID = 100 | |
161 | self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID) |
|
138 | self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID) | |
@@ -170,8 +147,7 class WxController(ConsoleWidget, PrefilterFrontEnd): | |||||
170 | self.shell.user_ns['self'] = self |
|
147 | self.shell.user_ns['self'] = self | |
171 | # Inject our own raw_input in namespace |
|
148 | # Inject our own raw_input in namespace | |
172 | self.shell.user_ns['raw_input'] = self.raw_input |
|
149 | self.shell.user_ns['raw_input'] = self.raw_input | |
173 |
|
150 | |||
174 |
|
||||
175 | def raw_input(self, prompt=''): |
|
151 | def raw_input(self, prompt=''): | |
176 | """ A replacement from python's raw_input. |
|
152 | """ A replacement from python's raw_input. | |
177 | """ |
|
153 | """ | |
@@ -272,6 +248,14 class WxController(ConsoleWidget, PrefilterFrontEnd): | |||||
272 | milliseconds=100, oneShot=True) |
|
248 | milliseconds=100, oneShot=True) | |
273 |
|
249 | |||
274 |
|
250 | |||
|
251 | def clear_screen(self): | |||
|
252 | """ Empty completely the widget. | |||
|
253 | """ | |||
|
254 | self.ClearAll() | |||
|
255 | self.new_prompt(self.input_prompt_template.substitute( | |||
|
256 | number=(self.last_result['number'] + 1))) | |||
|
257 | ||||
|
258 | ||||
275 | #-------------------------------------------------------------------------- |
|
259 | #-------------------------------------------------------------------------- | |
276 | # LineFrontEnd interface |
|
260 | # LineFrontEnd interface | |
277 | #-------------------------------------------------------------------------- |
|
261 | #-------------------------------------------------------------------------- | |
@@ -385,10 +369,16 class WxController(ConsoleWidget, PrefilterFrontEnd): | |||||
385 | self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER) |
|
369 | self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER) | |
386 |
|
370 | |||
387 |
|
371 | |||
|
372 | def continuation_prompt(self, *args, **kwargs): | |||
|
373 | # Avoid multiple inheritence, be explicit about which | |||
|
374 | # parent method class gets called | |||
|
375 | return ConsoleWidget.continuation_prompt(self, *args, **kwargs) | |||
|
376 | ||||
|
377 | ||||
388 | def write(self, *args, **kwargs): |
|
378 | def write(self, *args, **kwargs): | |
389 | # Avoid multiple inheritence, be explicit about which |
|
379 | # Avoid multiple inheritence, be explicit about which | |
390 | # parent method class gets called |
|
380 | # parent method class gets called | |
391 | ConsoleWidget.write(self, *args, **kwargs) |
|
381 | return ConsoleWidget.write(self, *args, **kwargs) | |
392 |
|
382 | |||
393 |
|
383 | |||
394 | def _on_key_down(self, event, skip=True): |
|
384 | def _on_key_down(self, event, skip=True): |
General Comments 0
You need to be logged in to leave comments.
Login now