##// END OF EJS Templates
* Refactored ConsoleWidget execution API for greater flexibility and clarity....
epatters -
Show More
@@ -382,15 +382,58 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
382 382 # 'ConsoleWidget' public interface
383 383 #---------------------------------------------------------------------------
384 384
385 def execute(self, interactive=False):
386 """ Execute the text in the input buffer. Returns whether the input
387 buffer was completely processed and a new prompt created.
388 """
389 self.appendPlainText('\n')
390 self._executing_input_buffer = self.input_buffer
391 self._executing = True
392 self._prompt_finished()
393 return self._execute(interactive=interactive)
385 def execute(self, source=None, hidden=False, interactive=False):
386 """ Executes source or the input buffer, possibly prompting for more
387 input.
388
389 Parameters:
390 -----------
391 source : str, optional
392
393 The source to execute. If not specified, the input buffer will be
394 used. If specified and 'hidden' is False, the input buffer will be
395 replaced with the source before execution.
396
397 hidden : bool, optional (default False)
398
399 If set, no output will be shown and the prompt will not be modified.
400 In other words, it will be completely invisible to the user that
401 an execution has occurred.
402
403 interactive : bool, optional (default False)
404
405 Whether the console is to treat the source as having been manually
406 entered by the user. The effect of this parameter depends on the
407 subclass implementation.
408
409 Returns:
410 --------
411 A boolean indicating whether the source was executed.
412 """
413 if not hidden:
414 if source is not None:
415 self.input_buffer = source
416
417 self.appendPlainText('\n')
418 self._executing_input_buffer = self.input_buffer
419 self._executing = True
420 self._prompt_finished()
421
422 real_source = self.input_buffer if source is None else source
423 complete = self._is_complete(real_source, interactive)
424 if complete:
425 if not hidden:
426 # The maximum block count is only in effect during execution.
427 # This ensures that _prompt_pos does not become invalid due to
428 # text truncation.
429 self.setMaximumBlockCount(self.buffer_size)
430 self._execute(real_source, hidden)
431 elif hidden:
432 raise RuntimeError('Incomplete noninteractive input: "%s"' % source)
433 else:
434 self._show_continuation_prompt()
435
436 return complete
394 437
395 438 def _get_input_buffer(self):
396 439 """ The text that the user has entered entered at the current prompt.
@@ -475,11 +518,15 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
475 518 # 'ConsoleWidget' abstract interface
476 519 #---------------------------------------------------------------------------
477 520
478 def _execute(self, interactive):
479 """ Called to execute the input buffer. When triggered by an the enter
480 key press, 'interactive' is True; otherwise, it is False. Returns
481 whether the input buffer was completely processed and a new prompt
482 created.
521 def _is_complete(self, source, interactive):
522 """ Returns whether 'source' can be executed. When triggered by an
523 Enter/Return key press, 'interactive' is True; otherwise, it is
524 False.
525 """
526 raise NotImplementedError
527
528 def _execute(self, source, hidden):
529 """ Execute 'source'. If 'hidden', do not show any output.
483 530 """
484 531 raise NotImplementedError
485 532
@@ -604,7 +651,8 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
604 651 def _prompt_started(self):
605 652 """ Called immediately after a new prompt is displayed.
606 653 """
607 # Temporarily disable the maximum block count to permit undo/redo.
654 # Temporarily disable the maximum block count to permit undo/redo and
655 # to ensure that the prompt position does not change due to truncation.
608 656 self.setMaximumBlockCount(0)
609 657 self.setUndoRedoEnabled(True)
610 658
@@ -619,9 +667,7 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
619 667 """ Called immediately after a prompt is finished, i.e. when some input
620 668 will be processed and a new prompt displayed.
621 669 """
622 # This has the (desired) side effect of disabling the undo/redo history.
623 self.setMaximumBlockCount(self.buffer_size)
624
670 self.setUndoRedoEnabled(False)
625 671 self.setReadOnly(True)
626 672 self._prompt_finished_hook()
627 673
@@ -702,14 +748,19 b' class HistoryConsoleWidget(ConsoleWidget):'
702 748 # 'ConsoleWidget' public interface
703 749 #---------------------------------------------------------------------------
704 750
705 def execute(self, interactive=False):
751 def execute(self, source=None, hidden=False, interactive=False):
706 752 """ Reimplemented to the store history.
707 753 """
708 stripped = self.input_buffer.rstrip()
709 executed = super(HistoryConsoleWidget, self).execute(interactive)
710 if executed:
711 self._history.append(stripped)
754 if source is None and not hidden:
755 history = self.input_buffer.rstrip()
756
757 executed = super(HistoryConsoleWidget, self).execute(
758 source, hidden, interactive)
759
760 if executed and not hidden:
761 self._history.append(history)
712 762 self._history_index = len(self._history)
763
713 764 return executed
714 765
715 766 #---------------------------------------------------------------------------
@@ -90,26 +90,40 b' class FrontendWidget(HistoryConsoleWidget):'
90 90 self._control_down(event.modifiers()):
91 91 self._interrupt_kernel()
92 92 else:
93 self._call_tip_widget.keyPressEvent(event)
93 if self._call_tip_widget.isVisible():
94 self._call_tip_widget.keyPressEvent(event)
94 95 super(FrontendWidget, self).keyPressEvent(event)
95 96
96 97 #---------------------------------------------------------------------------
97 98 # 'ConsoleWidget' abstract interface
98 99 #---------------------------------------------------------------------------
99 100
100 def _execute(self, interactive):
101 """ Called to execute the input buffer. When triggered by an the enter
102 key press, 'interactive' is True; otherwise, it is False. Returns
103 whether the input buffer was completely processed and a new prompt
104 created.
101 def _is_complete(self, source, interactive):
102 """ Returns whether 'source' can be completely processed and a new
103 prompt created. When triggered by an Enter/Return key press,
104 'interactive' is True; otherwise, it is False.
105 105 """
106 return self.execute_source(self.input_buffer, interactive=interactive)
106 complete = self._input_splitter.push(source)
107 if interactive:
108 complete = not self._input_splitter.push_accepts_more()
109 return complete
110
111 def _execute(self, source, hidden):
112 """ Execute 'source'. If 'hidden', do not show any output.
113 """
114 self.kernel_manager.xreq_channel.execute(source)
115 self._hidden = hidden
107 116
108 117 def _prompt_started_hook(self):
109 118 """ Called immediately after a new prompt is displayed.
110 119 """
111 120 self._highlighter.highlighting_on = True
112 121
122 # Auto-indent if this is a continuation prompt.
123 if self._get_prompt_cursor().blockNumber() != \
124 self._get_end_cursor().blockNumber():
125 self.appendPlainText(' ' * self._input_splitter.indent_spaces)
126
113 127 def _prompt_finished_hook(self):
114 128 """ Called immediately after a prompt is finished, i.e. when some input
115 129 will be processed and a new prompt displayed.
@@ -130,26 +144,11 b' class FrontendWidget(HistoryConsoleWidget):'
130 144 # 'FrontendWidget' interface
131 145 #---------------------------------------------------------------------------
132 146
133 def execute_source(self, source, hidden=False, interactive=False):
134 """ Execute a string containing Python code. If 'hidden', no output is
135 shown. Returns whether the source executed (i.e., returns True only
136 if no more input is necessary).
137 """
138 self._input_splitter.push(source)
139 executed = not self._input_splitter.push_accepts_more()
140 if executed:
141 self.kernel_manager.xreq_channel.execute(source)
142 self._hidden = hidden
143 else:
144 self._show_continuation_prompt()
145 self.appendPlainText(' ' * self._input_splitter.indent_spaces)
146 return executed
147
148 147 def execute_file(self, path, hidden=False):
149 148 """ Attempts to execute file with 'path'. If 'hidden', no output is
150 149 shown.
151 150 """
152 self.execute_source('run %s' % path, hidden=hidden)
151 self.execute('execfile("%s")' % path, hidden=hidden)
153 152
154 153 def _get_kernel_manager(self):
155 154 """ Returns the current kernel manager.
@@ -274,10 +273,11 b' class FrontendWidget(HistoryConsoleWidget):'
274 273 self._call_tip()
275 274
276 275 def _handle_sub(self, omsg):
277 if not self._hidden:
278 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
279 if handler is not None:
280 handler(omsg)
276 if self._hidden:
277 return
278 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
279 if handler is not None:
280 handler(omsg)
281 281
282 282 def _handle_pyout(self, omsg):
283 283 session = omsg['parent_header']['session']
@@ -286,8 +286,12 b' class FrontendWidget(HistoryConsoleWidget):'
286 286
287 287 def _handle_stream(self, omsg):
288 288 self.appendPlainText(omsg['content']['data'])
289 self.moveCursor(QtGui.QTextCursor.End)
289 290
290 291 def _handle_execute_reply(self, rep):
292 if self._hidden:
293 return
294
291 295 # Make sure that all output from the SUB channel has been processed
292 296 # before writing a new prompt.
293 297 self.kernel_manager.sub_channel.flush()
@@ -19,10 +19,10 b' class IPythonWidget(FrontendWidget):'
19 19 self._magic_overrides = {}
20 20
21 21 #---------------------------------------------------------------------------
22 # 'FrontendWidget' interface
22 # 'ConsoleWidget' abstract interface
23 23 #---------------------------------------------------------------------------
24 24
25 def execute_source(self, source, hidden=False, interactive=False):
25 def _execute(self, source, hidden):
26 26 """ Reimplemented to override magic commands.
27 27 """
28 28 magic_source = source.strip()
@@ -37,11 +37,18 b' class IPythonWidget(FrontendWidget):'
37 37 output = callback(arguments)
38 38 if output:
39 39 self.appendPlainText(output)
40 self._show_prompt('>>> ')
41 return True
40 self._show_prompt()
42 41 else:
43 return super(IPythonWidget, self).execute_source(source, hidden,
44 interactive)
42 super(IPythonWidget, self)._execute(source, hidden)
43
44 #---------------------------------------------------------------------------
45 # 'FrontendWidget' interface
46 #---------------------------------------------------------------------------
47
48 def execute_file(self, path, hidden=False):
49 """ Reimplemented to use the 'run' magic.
50 """
51 self.execute('run %s' % path, hidden=hidden)
45 52
46 53 #---------------------------------------------------------------------------
47 54 # 'IPythonWidget' interface
General Comments 0
You need to be logged in to leave comments. Login now