##// END OF EJS Templates
ENH: Enter adds lines at the right position
Gael Varoquaux -
Show More
@@ -188,16 +188,6 b' class LineFrontEndBase(FrontEndBase):'
188 # Create a false result, in case there is an exception
188 # Create a false result, in case there is an exception
189 self.last_result = dict(number=self.prompt_number)
189 self.last_result = dict(number=self.prompt_number)
190
190
191 ## try:
192 ## self.history.input_cache[-1] = raw_string.rstrip()
193 ## result = self.shell.execute(python_string)
194 ## self.last_result = result
195 ## self.render_result(result)
196 ## except:
197 ## self.show_traceback()
198 ## finally:
199 ## self.after_execute()
200
201 try:
191 try:
202 try:
192 try:
203 self.history.input_cache[-1] = raw_string.rstrip()
193 self.history.input_cache[-1] = raw_string.rstrip()
@@ -318,9 +308,20 b' class LineFrontEndBase(FrontEndBase):'
318 # Private API
308 # Private API
319 #--------------------------------------------------------------------------
309 #--------------------------------------------------------------------------
320
310
321 def _on_enter(self):
311 def _on_enter(self, new_line_pos=0):
322 """ Called when the return key is pressed in a line editing
312 """ Called when the return key is pressed in a line editing
323 buffer.
313 buffer.
314
315 Parameters
316 ----------
317 new_line_pos : integer, optional
318 Position of the new line to add, starting from the
319 end (0 adds a new line after the last line, -1 before
320 the last line...)
321
322 Returns
323 -------
324 True if execution is triggered
324 """
325 """
325 current_buffer = self.input_buffer
326 current_buffer = self.input_buffer
326 # XXX: This string replace is ugly, but there should be no way it
327 # XXX: This string replace is ugly, but there should be no way it
@@ -331,14 +332,25 b' class LineFrontEndBase(FrontEndBase):'
331 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
332 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
332 if self.is_complete(cleaned_buffer):
333 if self.is_complete(cleaned_buffer):
333 self.execute(cleaned_buffer, raw_string=current_buffer)
334 self.execute(cleaned_buffer, raw_string=current_buffer)
335 return True
334 else:
336 else:
335 self.input_buffer += self.continuation_prompt() + \
337 new_line_pos = -new_line_pos
336 self._get_indent_string(prompt_less_buffer[:-1])
338 lines = current_buffer.split('\n')[:-1]
337 if len(current_buffer.split('\n')) == 2:
339 prompt_less_lines = prompt_less_buffer.split('\n')
338 self.input_buffer += '\t'
340 new_line = self.continuation_prompt() + \
341 self._get_indent_string('\n'.join(
342 prompt_less_lines[:new_line_pos-1]))
343 if len(lines) == 2:
344 new_line += '\t'
339 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
345 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
340 self.input_buffer += '\t'
346 new_line += '\t'
341
347
348 if new_line_pos == 0:
349 lines.append(new_line)
350 else:
351 lines.insert(new_line_pos, new_line)
352 self.input_buffer = '\n'.join(lines)
353
342
354
343 def _get_indent_string(self, string):
355 def _get_indent_string(self, string):
344 """ Return the string of whitespace that prefixes a line. Used to
356 """ Return the string of whitespace that prefixes a line. Used to
@@ -472,6 +472,11 b' class ConsoleWidget(editwindow.EditWindow):'
472 Return True if event as been catched.
472 Return True if event as been catched.
473 """
473 """
474 catched = True
474 catched = True
475 # XXX: Would the right way to do this be to have a
476 # dictionary at the instance level associating keys with
477 # callbacks? How would we deal with inheritance? And Do the
478 # different callbacks share local variables?
479
475 # Intercept some specific keys.
480 # Intercept some specific keys.
476 if event.KeyCode == ord('L') and event.ControlDown() :
481 if event.KeyCode == ord('L') and event.ControlDown() :
477 self.scroll_to_bottom()
482 self.scroll_to_bottom()
@@ -489,6 +494,10 b' class ConsoleWidget(editwindow.EditWindow):'
489 self.ScrollPages(-1)
494 self.ScrollPages(-1)
490 elif event.KeyCode == wx.WXK_PAGEDOWN:
495 elif event.KeyCode == wx.WXK_PAGEDOWN:
491 self.ScrollPages(1)
496 self.ScrollPages(1)
497 elif event.KeyCode == wx.WXK_HOME:
498 self.GotoPos(self.GetLength())
499 elif event.KeyCode == wx.WXK_END:
500 self.GotoPos(self.GetLength())
492 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
501 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
493 self.ScrollLines(-1)
502 self.ScrollLines(-1)
494 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
503 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
@@ -500,17 +509,19 b' class ConsoleWidget(editwindow.EditWindow):'
500 event.Skip()
509 event.Skip()
501 else:
510 else:
502 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
511 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
503 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
512 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
513 wx.MOD_SHIFT):
504 catched = True
514 catched = True
505 if not self.enter_catched:
515 if not self.enter_catched:
506 self.CallTipCancel()
516 self.CallTipCancel()
507 self.write('\n', refresh=False)
517 if event.Modifiers == wx.MOD_SHIFT:
508 # Under windows scintilla seems to be doing funny
518 # Try to force execution
509 # stuff to the line returns here, but the getter for
519 self.GotoPos(self.GetLength())
510 # input_buffer filters this out.
520 self.write('\n' + self.continuation_prompt(),
511 if sys.platform == 'win32':
521 refresh=False)
512 self.input_buffer = self.input_buffer
522 self._on_enter()
513 self._on_enter()
523 else:
524 self._on_enter()
514 self.enter_catched = True
525 self.enter_catched = True
515
526
516 elif event.KeyCode == wx.WXK_HOME:
527 elif event.KeyCode == wx.WXK_HOME:
@@ -284,6 +284,8 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
284 """ Execute a command, not only in the model, but also in the
284 """ Execute a command, not only in the model, but also in the
285 view.
285 view.
286 """
286 """
287 # XXX: This method needs to be integrated in the base fronted
288 # interface
287 if hidden:
289 if hidden:
288 return self.shell.execute(command)
290 return self.shell.execute(command)
289 else:
291 else:
@@ -386,7 +388,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
386 widget handle them, and put our logic afterward.
388 widget handle them, and put our logic afterward.
387 """
389 """
388 # FIXME: This method needs to be broken down in smaller ones.
390 # FIXME: This method needs to be broken down in smaller ones.
389 current_line_number = self.GetCurrentLine()
391 current_line_num = self.GetCurrentLine()
390 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
392 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
391 # Capture Control-C
393 # Capture Control-C
392 if self._input_state == 'subprocess':
394 if self._input_state == 'subprocess':
@@ -432,7 +434,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
432 else:
434 else:
433 # Up history
435 # Up history
434 if event.KeyCode == wx.WXK_UP and (
436 if event.KeyCode == wx.WXK_UP and (
435 ( current_line_number == self.current_prompt_line and
437 ( current_line_num == self.current_prompt_line and
436 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
438 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
437 or event.ControlDown() ):
439 or event.ControlDown() ):
438 new_buffer = self.get_history_previous(
440 new_buffer = self.get_history_previous(
@@ -444,7 +446,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
444 self.GotoPos(self.current_prompt_pos)
446 self.GotoPos(self.current_prompt_pos)
445 # Down history
447 # Down history
446 elif event.KeyCode == wx.WXK_DOWN and (
448 elif event.KeyCode == wx.WXK_DOWN and (
447 ( current_line_number == self.LineCount -1 and
449 ( current_line_num == self.LineCount -1 and
448 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
450 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
449 or event.ControlDown() ):
451 or event.ControlDown() ):
450 new_buffer = self.get_history_next()
452 new_buffer = self.get_history_next()
@@ -452,7 +454,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
452 self.input_buffer = new_buffer
454 self.input_buffer = new_buffer
453 # Tab-completion
455 # Tab-completion
454 elif event.KeyCode == ord('\t'):
456 elif event.KeyCode == ord('\t'):
455 current_line, current_line_number = self.CurLine
457 current_line, current_line_num = self.CurLine
456 if not re.match(r'^\s*$', current_line):
458 if not re.match(r'^\s*$', current_line):
457 self.complete_current_input()
459 self.complete_current_input()
458 if self.AutoCompActive():
460 if self.AutoCompActive():
@@ -467,16 +469,16 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
467 # independant of IPython
469 # independant of IPython
468 current_line, _ = self.CurLine
470 current_line, _ = self.CurLine
469 current_pos = self.GetCurrentPos()
471 current_pos = self.GetCurrentPos()
470 current_line_number = self.LineFromPosition(current_pos)
472 current_line_num = self.LineFromPosition(current_pos)
471 current_col = self.GetColumn(current_pos)
473 current_col = self.GetColumn(current_pos)
472 len_prompt = len(self.continuation_prompt())
474 len_prompt = len(self.continuation_prompt())
473 if ( current_line.startswith(self.continuation_prompt())
475 if ( current_line.startswith(self.continuation_prompt())
474 and current_col == len_prompt):
476 and current_col == len_prompt):
475 new_lines = []
477 new_lines = []
476 for line_num, line in enumerate(
478 for line_num, line in enumerate(
477 self.input_buffer.split('\n')):
479 self.input_buffer.split('\n')):
478 if (line_num + self.current_prompt_line ==
480 if (line_num + self.current_prompt_line ==
479 current_line_number):
481 current_line_num):
480 new_lines.append(line[len_prompt:])
482 new_lines.append(line[len_prompt:])
481 else:
483 else:
482 new_lines.append('\n'+line)
484 new_lines.append('\n'+line)
@@ -515,9 +517,22 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
515 def _on_enter(self):
517 def _on_enter(self):
516 """ Called on return key down, in readline input_state.
518 """ Called on return key down, in readline input_state.
517 """
519 """
520 last_line_num = self.LineFromPosition(self.GetLength())
521 current_line_num = self.LineFromPosition(self.GetCurrentPos())
522 new_line_pos = (last_line_num - current_line_num)
518 if self.debug:
523 if self.debug:
519 print >>sys.__stdout__, repr(self.input_buffer)
524 print >>sys.__stdout__, repr(self.input_buffer)
520 PrefilterFrontEnd._on_enter(self)
525 self.write('\n', refresh=False)
526 # Under windows scintilla seems to be doing funny
527 # stuff to the line returns here, but the getter for
528 # input_buffer filters this out.
529 if sys.platform == 'win32':
530 self.input_buffer = self.input_buffer
531 has_executed = PrefilterFrontEnd._on_enter(self,
532 new_line_pos=new_line_pos)
533 if not has_executed:
534 self.GotoPos(self.GetLineEndPosition(current_line_num + 1))
535 return has_executed
521
536
522
537
523 #--------------------------------------------------------------------------
538 #--------------------------------------------------------------------------
General Comments 0
You need to be logged in to leave comments. Login now