##// END OF EJS Templates
Clean up history. Tweak multiline input. Improve key handling.
Gael Varoquaux -
Show More
@@ -102,7 +102,6 b' class ConsoleWidget(editwindow.EditWindow):'
102 'IPYTHON' show autocompletion the ipython way
102 'IPYTHON' show autocompletion the ipython way
103 'STC" show it scintilla text control way
103 'STC" show it scintilla text control way
104 """
104 """
105 #stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
106 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
105 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
107 self.configure_scintilla()
106 self.configure_scintilla()
108
107
@@ -113,7 +112,7 b' class ConsoleWidget(editwindow.EditWindow):'
113
112
114 self.autocomplete_mode = autocomplete_mode
113 self.autocomplete_mode = autocomplete_mode
115
114
116 self.Bind(wx.EVT_KEY_DOWN, self._onKeypress)
115 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
117
116
118
117
119 def configure_scintilla(self):
118 def configure_scintilla(self):
@@ -146,7 +145,6 b' class ConsoleWidget(editwindow.EditWindow):'
146
145
147 self._apply_style()
146 self._apply_style()
148
147
149 self.indent = 0
150 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
148 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
151
149
152 #self.SetEdgeMode(stc.STC_EDGE_LINE)
150 #self.SetEdgeMode(stc.STC_EDGE_LINE)
@@ -175,9 +173,6 b' class ConsoleWidget(editwindow.EditWindow):'
175 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
173 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
176
174
177
175
178
179
180
181 def write(self, text):
176 def write(self, text):
182 """ Write given text to buffer, while translating the ansi escape
177 """ Write given text to buffer, while translating the ansi escape
183 sequences.
178 sequences.
@@ -215,10 +210,6 b' class ConsoleWidget(editwindow.EditWindow):'
215 self.current_prompt_pos = self.GetLength()
210 self.current_prompt_pos = self.GetLength()
216 self.current_prompt_line = self.GetCurrentLine()
211 self.current_prompt_line = self.GetCurrentLine()
217
212
218 autoindent = self.indent * ' '
219 autoindent = autoindent.replace(' ','\t')
220 self.write(autoindent)
221
222
213
223 def replace_current_edit_buffer(self, text):
214 def replace_current_edit_buffer(self, text):
224 """ Replace currently entered command line with given text.
215 """ Replace currently entered command line with given text.
@@ -243,39 +234,6 b' class ConsoleWidget(editwindow.EditWindow):'
243 """ Applies the colors for the different text elements and the
234 """ Applies the colors for the different text elements and the
244 carret.
235 carret.
245 """
236 """
246 # FIXME: We need to do something for the fonts, but this is
247 # clearly not the right option.
248 #we define platform specific fonts
249 # if wx.Platform == '__WXMSW__':
250 # faces = { 'times': 'Times New Roman',
251 # 'mono' : 'Courier New',
252 # 'helv' : 'Arial',
253 # 'other': 'Comic Sans MS',
254 # 'size' : 10,
255 # 'size2': 8,
256 # }
257 # elif wx.Platform == '__WXMAC__':
258 # faces = { 'times': 'Times New Roman',
259 # 'mono' : 'Monaco',
260 # 'helv' : 'Arial',
261 # 'other': 'Comic Sans MS',
262 # 'size' : 10,
263 # 'size2': 8,
264 # }
265 # else:
266 # faces = { 'times': 'Times',
267 # 'mono' : 'Courier',
268 # 'helv' : 'Helvetica',
269 # 'other': 'new century schoolbook',
270 # 'size' : 10,
271 # 'size2': 8,
272 # }
273 # self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
274 # "fore:%s,back:%s,size:%d,face:%s"
275 # % (self.ANSI_STYLES['0;30'][1],
276 # self.background_color,
277 # faces['size'], faces['mono']))
278
279 self.SetCaretForeground(self.carret_color)
237 self.SetCaretForeground(self.carret_color)
280
238
281 self.StyleClearAll()
239 self.StyleClearAll()
@@ -335,7 +293,7 b' class ConsoleWidget(editwindow.EditWindow):'
335 self.AutoCompShow(len(last_word), " ".join(possibilities))
293 self.AutoCompShow(len(last_word), " ".join(possibilities))
336
294
337
295
338 def _onKeypress(self, event, skip=True):
296 def _on_key_down(self, event, skip=True):
339 """ Key press callback used for correcting behavior for
297 """ Key press callback used for correcting behavior for
340 console-like interfaces: the cursor is constraint to be after
298 console-like interfaces: the cursor is constraint to be after
341 the last prompt.
299 the last prompt.
@@ -343,6 +301,11 b' class ConsoleWidget(editwindow.EditWindow):'
343 Return True if event as been catched.
301 Return True if event as been catched.
344 """
302 """
345 catched = False
303 catched = False
304 # Intercept annoying entries (eg: ctrl-D, ctrl-L)
305 if event.KeyCode in (68, 76) and event.ControlDown() :
306 skip = False
307 catched = True
308
346 if self.AutoCompActive():
309 if self.AutoCompActive():
347 event.Skip()
310 event.Skip()
348 else:
311 else:
@@ -351,7 +314,7 b' class ConsoleWidget(editwindow.EditWindow):'
351 self.GotoPos(self.current_prompt_pos)
314 self.GotoPos(self.current_prompt_pos)
352 catched = True
315 catched = True
353
316
354 elif event.Modifiers == wx.MOD_SHIFT:
317 elif event.Modifiers in (wx.MOD_SHIFT, wx.MOD_WIN) :
355 self.selectFromTo(self.current_prompt_pos,
318 self.selectFromTo(self.current_prompt_pos,
356 self.GetCurrentPos())
319 self.GetCurrentPos())
357 catched = True
320 catched = True
@@ -384,37 +347,6 b' class ConsoleWidget(editwindow.EditWindow):'
384 return catched
347 return catched
385
348
386
349
387 def OnUpdateUI(self, evt):
388 # check for matching braces
389 braceAtCaret = -1
390 braceOpposite = -1
391 charBefore = None
392 caretPos = self.GetCurrentPos()
393
394 if caretPos > 0:
395 charBefore = self.GetCharAt(caretPos - 1)
396 styleBefore = self.GetStyleAt(caretPos - 1)
397
398 # check before
399 if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
400 braceAtCaret = caretPos - 1
401
402 # check after
403 if braceAtCaret < 0:
404 charAfter = self.GetCharAt(caretPos)
405 styleAfter = self.GetStyleAt(caretPos)
406
407 if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
408 braceAtCaret = caretPos
409
410 if braceAtCaret >= 0:
411 braceOpposite = self.BraceMatch(braceAtCaret)
412
413 if braceAtCaret != -1 and braceOpposite == -1:
414 self.BraceBadLight(braceAtCaret)
415 else:
416 self.BraceHighlight(braceAtCaret, braceOpposite)
417
418
350
419 if __name__ == '__main__':
351 if __name__ == '__main__':
420 # Some simple code to test the console widget.
352 # Some simple code to test the console widget.
@@ -1,7 +1,7 b''
1 # encoding: utf-8
1 # encoding: utf-8 -*- test-case-name:
2 # -*- test-case-name: ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
2 # ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
3
3
4 """Classes to provide a Wx frontend to the
4 """Classes to provide a Wx frontend to the
5 ipython1.kernel.engineservice.EngineService.
5 ipython1.kernel.engineservice.EngineService.
6
6
7 """
7 """
@@ -26,9 +26,9 b' import re'
26
26
27 import IPython
27 import IPython
28 from IPython.kernel.engineservice import EngineService
28 from IPython.kernel.engineservice import EngineService
29 from IPython.kernel.core.history import FrontEndHistory
29 from IPython.frontend.frontendbase import FrontEndBase
30 from IPython.frontend.frontendbase import FrontEndBase
30
31
31
32 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
33 # Classes to implement the Wx frontend
33 # Classes to implement the Wx frontend
34 #-------------------------------------------------------------------------------
34 #-------------------------------------------------------------------------------
@@ -59,15 +59,18 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
59 """ Create Shell instance.
59 """ Create Shell instance.
60 """
60 """
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
62 FrontEndBase.__init__(self, engine=EngineService())
62 FrontEndBase.__init__(self, engine=EngineService(),
63 )
63
64
65 # FIXME: Something is wrong with the history, I instanciate it
66 # with an empty cache, but this is not the way to do.
64 self.lines = {}
67 self.lines = {}
65
68
66 # Start the IPython engine
69 # Start the IPython engine
67 self.engine.startService()
70 self.engine.startService()
68
71
69 # Capture Character keys
72 # Capture Character keys
70 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
73 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
71
74
72 #FIXME: print banner.
75 #FIXME: print banner.
73 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
76 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
@@ -97,11 +100,13 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
97
100
98
101
99 def render_result(self, result):
102 def render_result(self, result):
100 if 'stdout' in result:
103 if 'stdout' in result and result['stdout']:
101 self.write(result['stdout'])
104 self.write('\n' + result['stdout'])
102 if 'display' in result:
105 if 'display' in result and result['display']:
103 self.write(self.output_prompt % result['number']
106 self.write("%s%s\n" % (
104 + result['display']['pprint'])
107 self.output_prompt % result['number'],
108 result['display']['pprint']
109 ) )
105
110
106
111
107 def render_error(self, failure):
112 def render_error(self, failure):
@@ -114,17 +119,36 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
114 #--------------------------------------------------------------------------
119 #--------------------------------------------------------------------------
115
120
116
121
117 def _on_key_up(self, event, skip=True):
122 def _on_key_down(self, event, skip=True):
118 """ Capture the character events, let the parent
123 """ Capture the character events, let the parent
119 widget handle them, and put our logic afterward.
124 widget handle them, and put our logic afterward.
120 """
125 """
121 event.Skip()
126 current_line_number = self.GetCurrentLine()
122 # Capture enter
127 # Capture enter
123 if event.KeyCode == 13 and \
128 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
124 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
129 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
125 self._on_enter()
130 self._on_enter()
131 # Up history
132 elif event.KeyCode == wx.WXK_UP and (
133 ( current_line_number == self.current_prompt_line and
134 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
135 or event.ControlDown() ):
136 new_buffer = self.get_history_previous(
137 self.get_current_edit_buffer())
138 if new_buffer is not None:
139 self.replace_current_edit_buffer(new_buffer)
140 # Down history
141 elif event.KeyCode == wx.WXK_DOWN and (
142 ( current_line_number == self.LineCount -1 and
143 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
144 or event.ControlDown() ):
145 new_buffer = self.get_history_next()
146 if new_buffer is not None:
147 self.replace_current_edit_buffer(new_buffer)
148 else:
149 ConsoleWidget._on_key_down(self, event, skip=True)
150
126
151
127
128 def _on_enter(self):
152 def _on_enter(self):
129 """ Called when the return key is pressed in a line editing
153 """ Called when the return key is pressed in a line editing
130 buffer.
154 buffer.
@@ -132,21 +156,24 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
132 current_buffer = self.get_current_edit_buffer()
156 current_buffer = self.get_current_edit_buffer()
133 current_buffer = current_buffer.replace('\r\n', '\n')
157 current_buffer = current_buffer.replace('\r\n', '\n')
134 current_buffer = current_buffer.replace('\t', 4*' ')
158 current_buffer = current_buffer.replace('\t', 4*' ')
159 cleaned_buffer = '\n'.join(l.rstrip()
160 for l in current_buffer.split('\n'))
135 if ( not self.multi_line_input
161 if ( not self.multi_line_input
136 or re.findall(r"\n[\t ]*\n[\t ]*$", current_buffer)):
162 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
137 if self.is_complete(current_buffer):
163 if self.is_complete(cleaned_buffer):
138 result = self.engine.shell.execute(current_buffer)
164 self._add_history(None, cleaned_buffer.rstrip())
165 result = self.engine.shell.execute(cleaned_buffer)
139 self.render_result(result)
166 self.render_result(result)
140 self.new_prompt(self.prompt % result['number'])
167 self.new_prompt(self.prompt % (result['number'] + 1))
141 self.multi_line_input = False
168 self.multi_line_input = False
142 else:
169 else:
143 if self.multi_line_input:
170 if self.multi_line_input:
144 self.write(self._get_indent_string(current_buffer[:-1]))
171 self.write('\n' + self._get_indent_string(current_buffer))
145 else:
172 else:
146 self.multi_line_input = True
173 self.multi_line_input = True
147 self.write('\t')
174 self.write('\n\t')
148 else:
175 else:
149 self.write(self._get_indent_string(current_buffer[:-1]))
176 self.write('\n'+self._get_indent_string(current_buffer))
150
177
151
178
152 def _get_indent_string(self, string):
179 def _get_indent_string(self, string):
@@ -173,8 +200,8 b" if __name__ == '__main__':"
173 app = wx.PySimpleApp()
200 app = wx.PySimpleApp()
174 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
201 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
175 frame.shell.SetFocus()
202 frame.shell.SetFocus()
176 frame.SetSize((780, 460))
203 frame.SetSize((660, 460))
177 shell = frame.shell
204 self = frame.shell
178
205
179 # app.MainLoop()
206 # app.MainLoop()
180
207
General Comments 0
You need to be logged in to leave comments. Login now