Show More
@@ -295,6 +295,17 b' class LineFrontEndBase(FrontEndBase):' | |||||
295 | self.write(prompt) |
|
295 | self.write(prompt) | |
296 |
|
296 | |||
297 |
|
297 | |||
|
298 | def continuation_prompt(self): | |||
|
299 | """Returns the current continuation prompt. | |||
|
300 | Overridden to generate a continuation prompt matching the length of the | |||
|
301 | current prompt.""" | |||
|
302 | ||||
|
303 | # FIXME: This is a bad hack.. I need to find a way to use the 'Prompt2' | |||
|
304 | # class in IPython/kernel/prompts.py. Basically, I am trying to get the | |||
|
305 | # length of the current prompt ("In ['number']"). | |||
|
306 | return ("."*(5+len(str(self.last_result['number']))) + ':') | |||
|
307 | ||||
|
308 | ||||
298 | def execute_command(self, command, hidden=False): |
|
309 | def execute_command(self, command, hidden=False): | |
299 | """ Execute a command, not only in the model, but also in the |
|
310 | """ Execute a command, not only in the model, but also in the | |
300 | view, if any. |
|
311 | view, if any. | |
@@ -310,14 +321,19 b' class LineFrontEndBase(FrontEndBase):' | |||||
310 | buffer. |
|
321 | buffer. | |
311 | """ |
|
322 | """ | |
312 | current_buffer = self.input_buffer |
|
323 | current_buffer = self.input_buffer | |
313 | cleaned_buffer = self.prefilter_input(current_buffer) |
|
324 | # XXX: This string replace is ugly, but there should be no way it | |
|
325 | # fails. | |||
|
326 | prompt_less_buffer = re.sub('^' + self.continuation_prompt(), | |||
|
327 | '', current_buffer).replace('\n' + self.continuation_prompt(), | |||
|
328 | '\n') | |||
|
329 | cleaned_buffer = self.prefilter_input(prompt_less_buffer) | |||
314 | if self.is_complete(cleaned_buffer): |
|
330 | if self.is_complete(cleaned_buffer): | |
315 | self.execute(cleaned_buffer, raw_string=current_buffer) |
|
331 | self.execute(cleaned_buffer, raw_string=current_buffer) | |
316 | else: |
|
332 | else: | |
317 |
self.input_buffer += self. |
|
333 | self.input_buffer += self.continuation_prompt() + \ | |
318 | current_buffer[:-1]) |
|
334 | self._get_indent_string(prompt_less_buffer[:-1]) | |
319 | if len(current_buffer.split('\n')) == 2: |
|
335 | if len(current_buffer.split('\n')) == 2: | |
320 |
self.input_buffer += '\t |
|
336 | self.input_buffer += '\t' | |
321 | if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'): |
|
337 | if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'): | |
322 | self.input_buffer += '\t' |
|
338 | self.input_buffer += '\t' | |
323 |
|
339 |
@@ -24,6 +24,7 b' __docformat__ = "restructuredtext en"' | |||||
24 | import sys |
|
24 | import sys | |
25 | import pydoc |
|
25 | import pydoc | |
26 | import os |
|
26 | import os | |
|
27 | import re | |||
27 | import __builtin__ |
|
28 | import __builtin__ | |
28 |
|
29 | |||
29 | from IPython.ipmaker import make_IPython |
|
30 | from IPython.ipmaker import make_IPython | |
@@ -113,9 +114,9 b' class PrefilterFrontEnd(LineFrontEndBase):' | |||||
113 |
|
114 | |||
114 |
|
115 | |||
115 | if not 'banner' in kwargs and self.banner is None: |
|
116 | if not 'banner' in kwargs and self.banner is None: | |
116 |
self.banner = self.ipython0.BANNER |
|
117 | self.banner = self.ipython0.BANNER | |
117 | This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code.""" |
|
|||
118 |
|
118 | |||
|
119 | # FIXME: __init__ and start should be two different steps | |||
119 | self.start() |
|
120 | self.start() | |
120 |
|
121 | |||
121 | #-------------------------------------------------------------------------- |
|
122 | #-------------------------------------------------------------------------- | |
@@ -182,7 +183,9 b' This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""' | |||||
182 | def complete(self, line): |
|
183 | def complete(self, line): | |
183 | # FIXME: This should be factored out in the linefrontendbase |
|
184 | # FIXME: This should be factored out in the linefrontendbase | |
184 | # method. |
|
185 | # method. | |
|
186 | word = self._get_completion_text(line) | |||
185 | word = line.split('\n')[-1].split(' ')[-1] |
|
187 | word = line.split('\n')[-1].split(' ')[-1] | |
|
188 | print 'Completion', word | |||
186 | completions = self.ipython0.complete(word) |
|
189 | completions = self.ipython0.complete(word) | |
187 | # FIXME: The proper sort should be done in the complete method. |
|
190 | # FIXME: The proper sort should be done in the complete method. | |
188 | key = lambda x: x.replace('_', '') |
|
191 | key = lambda x: x.replace('_', '') | |
@@ -255,3 +258,18 b' This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""' | |||||
255 | """ |
|
258 | """ | |
256 | self.ipython0.atexit_operations() |
|
259 | self.ipython0.atexit_operations() | |
257 |
|
260 | |||
|
261 | ||||
|
262 | def _get_completion_text(self, line): | |||
|
263 | """ Returns the text to be completed by breaking the line at specified | |||
|
264 | delimiters. | |||
|
265 | """ | |||
|
266 | # Break at: spaces, '=', all parentheses (except if balanced). | |||
|
267 | # FIXME2: In the future, we need to make the implementation similar to | |||
|
268 | # that in the 'pyreadline' module (modes/basemode.py) where we break at | |||
|
269 | # each delimiter and try to complete the residual line, until we get a | |||
|
270 | # successful list of completions. | |||
|
271 | expression = '\s|=|,|:|\((?!.*\))|\[(?!.*\])|\{(?!.*\})' | |||
|
272 | complete_sep = re.compile(expression) | |||
|
273 | text = complete_sep.split(line)[-1] | |||
|
274 | return text | |||
|
275 |
@@ -216,6 +216,16 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
216 | """ |
|
216 | """ | |
217 | return self.GetSize()[0]/self.GetCharWidth() |
|
217 | return self.GetSize()[0]/self.GetCharWidth() | |
218 |
|
218 | |||
|
219 | ||||
|
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 | ||||
219 | #-------------------------------------------------------------------------- |
|
229 | #-------------------------------------------------------------------------- | |
220 | # EditWindow API |
|
230 | # EditWindow API | |
221 | #-------------------------------------------------------------------------- |
|
231 | #-------------------------------------------------------------------------- | |
@@ -391,15 +401,16 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
391 | catched = True |
|
401 | catched = True | |
392 |
|
402 | |||
393 | elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK): |
|
403 | elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK): | |
394 | if self.GetCurrentPos() > self.current_prompt_pos: |
|
404 | if not self._keep_cursor_in_buffer(): | |
395 | event.Skip() |
|
405 | event.Skip() | |
396 | catched = True |
|
406 | catched = True | |
397 |
|
407 | |||
398 | if skip and not catched: |
|
408 | if skip and not catched: | |
399 | # Put the cursor back in the edit region |
|
409 | # Put the cursor back in the edit region | |
400 | if self.GetCurrentPos() < self.current_prompt_pos: |
|
410 | if not self._keep_cursor_in_buffer(): | |
401 | self.GotoPos(self.current_prompt_pos) |
|
411 | if (self.GetCurrentPos() == self.GetLength() | |
402 | else: |
|
412 | and event.KeyCode == wx.WXK_DELETE): | |
|
413 | pass | |||
403 | event.Skip() |
|
414 | event.Skip() | |
404 |
|
415 | |||
405 | return catched |
|
416 | return catched | |
@@ -408,9 +419,44 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
408 | def _on_key_up(self, event, skip=True): |
|
419 | def _on_key_up(self, event, skip=True): | |
409 | """ If cursor is outside the editing region, put it back. |
|
420 | """ If cursor is outside the editing region, put it back. | |
410 | """ |
|
421 | """ | |
411 |
|
|
422 | if skip: | |
412 | if self.GetCurrentPos() < self.current_prompt_pos: |
|
423 | event.Skip() | |
|
424 | self._keep_cursor_in_buffer() | |||
|
425 | ||||
|
426 | ||||
|
427 | def _keep_cursor_in_buffer(self): | |||
|
428 | """ Checks if the cursor is where it is allowed to be. If not, | |||
|
429 | put it back. | |||
|
430 | ||||
|
431 | Returns | |||
|
432 | ------- | |||
|
433 | cursor_moved: Boolean | |||
|
434 | whether or not the cursor was moved by this routine. | |||
|
435 | ||||
|
436 | Notes | |||
|
437 | ------ | |||
|
438 | WARNING: This does proper checks only for horizontal | |||
|
439 | movements. | |||
|
440 | """ | |||
|
441 | current_pos = self.GetCurrentPos() | |||
|
442 | if current_pos < self.current_prompt_pos: | |||
413 | self.GotoPos(self.current_prompt_pos) |
|
443 | self.GotoPos(self.current_prompt_pos) | |
|
444 | return True | |||
|
445 | line, line_pos = self.GetCurLine() | |||
|
446 | # Jump the continuation prompt | |||
|
447 | continuation_prompt = self.continuation_prompt() | |||
|
448 | if ( line.startswith(continuation_prompt) | |||
|
449 | and line_pos < len(continuation_prompt)+1): | |||
|
450 | if line_pos < 2: | |||
|
451 | # We are at the beginning of the line, trying to move | |||
|
452 | # forward: jump forward. | |||
|
453 | self.GotoPos(current_pos + 1 + | |||
|
454 | len(continuation_prompt) - line_pos) | |||
|
455 | else: | |||
|
456 | # Jump back up | |||
|
457 | self.GotoPos(self.GetLineEndPosition(self.GetCurrentLine()-1)) | |||
|
458 | return True | |||
|
459 | return False | |||
414 |
|
460 | |||
415 |
|
461 | |||
416 |
|
462 |
@@ -485,6 +485,12 b' class WxController(ConsoleWidget, PrefilterFrontEnd):' | |||||
485 | wx.CallAfter(self._popup_completion, create=True) |
|
485 | wx.CallAfter(self._popup_completion, create=True) | |
486 | else: |
|
486 | else: | |
487 | ConsoleWidget._on_key_up(self, event, skip=skip) |
|
487 | ConsoleWidget._on_key_up(self, event, skip=skip) | |
|
488 | if (self.input_buffer.split('\n')[-1] == self.continuation_prompt() | |||
|
489 | and self._input_state == 'readline'): | |||
|
490 | # Make sure the continuation_prompt is followed by a whitespace | |||
|
491 | position = self.GetCurrentPos() | |||
|
492 | self.input_buffer += ' ' | |||
|
493 | self.GotoPos(position) | |||
488 |
|
494 | |||
489 |
|
495 | |||
490 | def _on_enter(self): |
|
496 | def _on_enter(self): |
General Comments 0
You need to be logged in to leave comments.
Login now