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