##// 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 # 'ConsoleWidget' public interface
382 # 'ConsoleWidget' public interface
383 #---------------------------------------------------------------------------
383 #---------------------------------------------------------------------------
384
384
385 def execute(self, interactive=False):
385 def execute(self, source=None, hidden=False, interactive=False):
386 """ Execute the text in the input buffer. Returns whether the input
386 """ Executes source or the input buffer, possibly prompting for more
387 buffer was completely processed and a new prompt created.
387 input.
388 """
388
389 self.appendPlainText('\n')
389 Parameters:
390 self._executing_input_buffer = self.input_buffer
390 -----------
391 self._executing = True
391 source : str, optional
392 self._prompt_finished()
392
393 return self._execute(interactive=interactive)
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 def _get_input_buffer(self):
438 def _get_input_buffer(self):
396 """ The text that the user has entered entered at the current prompt.
439 """ The text that the user has entered entered at the current prompt.
@@ -475,11 +518,15 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
475 # 'ConsoleWidget' abstract interface
518 # 'ConsoleWidget' abstract interface
476 #---------------------------------------------------------------------------
519 #---------------------------------------------------------------------------
477
520
478 def _execute(self, interactive):
521 def _is_complete(self, source, interactive):
479 """ Called to execute the input buffer. When triggered by an the enter
522 """ Returns whether 'source' can be executed. When triggered by an
480 key press, 'interactive' is True; otherwise, it is False. Returns
523 Enter/Return key press, 'interactive' is True; otherwise, it is
481 whether the input buffer was completely processed and a new prompt
524 False.
482 created.
525 """
526 raise NotImplementedError
527
528 def _execute(self, source, hidden):
529 """ Execute 'source'. If 'hidden', do not show any output.
483 """
530 """
484 raise NotImplementedError
531 raise NotImplementedError
485
532
@@ -604,7 +651,8 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
604 def _prompt_started(self):
651 def _prompt_started(self):
605 """ Called immediately after a new prompt is displayed.
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 self.setMaximumBlockCount(0)
656 self.setMaximumBlockCount(0)
609 self.setUndoRedoEnabled(True)
657 self.setUndoRedoEnabled(True)
610
658
@@ -619,9 +667,7 b' class ConsoleWidget(QtGui.QPlainTextEdit):'
619 """ Called immediately after a prompt is finished, i.e. when some input
667 """ Called immediately after a prompt is finished, i.e. when some input
620 will be processed and a new prompt displayed.
668 will be processed and a new prompt displayed.
621 """
669 """
622 # This has the (desired) side effect of disabling the undo/redo history.
670 self.setUndoRedoEnabled(False)
623 self.setMaximumBlockCount(self.buffer_size)
624
625 self.setReadOnly(True)
671 self.setReadOnly(True)
626 self._prompt_finished_hook()
672 self._prompt_finished_hook()
627
673
@@ -702,14 +748,19 b' class HistoryConsoleWidget(ConsoleWidget):'
702 # 'ConsoleWidget' public interface
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 """ Reimplemented to the store history.
752 """ Reimplemented to the store history.
707 """
753 """
708 stripped = self.input_buffer.rstrip()
754 if source is None and not hidden:
709 executed = super(HistoryConsoleWidget, self).execute(interactive)
755 history = self.input_buffer.rstrip()
710 if executed:
756
711 self._history.append(stripped)
757 executed = super(HistoryConsoleWidget, self).execute(
758 source, hidden, interactive)
759
760 if executed and not hidden:
761 self._history.append(history)
712 self._history_index = len(self._history)
762 self._history_index = len(self._history)
763
713 return executed
764 return executed
714
765
715 #---------------------------------------------------------------------------
766 #---------------------------------------------------------------------------
@@ -90,26 +90,40 b' class FrontendWidget(HistoryConsoleWidget):'
90 self._control_down(event.modifiers()):
90 self._control_down(event.modifiers()):
91 self._interrupt_kernel()
91 self._interrupt_kernel()
92 else:
92 else:
93 self._call_tip_widget.keyPressEvent(event)
93 if self._call_tip_widget.isVisible():
94 self._call_tip_widget.keyPressEvent(event)
94 super(FrontendWidget, self).keyPressEvent(event)
95 super(FrontendWidget, self).keyPressEvent(event)
95
96
96 #---------------------------------------------------------------------------
97 #---------------------------------------------------------------------------
97 # 'ConsoleWidget' abstract interface
98 # 'ConsoleWidget' abstract interface
98 #---------------------------------------------------------------------------
99 #---------------------------------------------------------------------------
99
100
100 def _execute(self, interactive):
101 def _is_complete(self, source, interactive):
101 """ Called to execute the input buffer. When triggered by an the enter
102 """ Returns whether 'source' can be completely processed and a new
102 key press, 'interactive' is True; otherwise, it is False. Returns
103 prompt created. When triggered by an Enter/Return key press,
103 whether the input buffer was completely processed and a new prompt
104 'interactive' is True; otherwise, it is False.
104 created.
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 def _prompt_started_hook(self):
117 def _prompt_started_hook(self):
109 """ Called immediately after a new prompt is displayed.
118 """ Called immediately after a new prompt is displayed.
110 """
119 """
111 self._highlighter.highlighting_on = True
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 def _prompt_finished_hook(self):
127 def _prompt_finished_hook(self):
114 """ Called immediately after a prompt is finished, i.e. when some input
128 """ Called immediately after a prompt is finished, i.e. when some input
115 will be processed and a new prompt displayed.
129 will be processed and a new prompt displayed.
@@ -130,26 +144,11 b' class FrontendWidget(HistoryConsoleWidget):'
130 # 'FrontendWidget' interface
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 def execute_file(self, path, hidden=False):
147 def execute_file(self, path, hidden=False):
149 """ Attempts to execute file with 'path'. If 'hidden', no output is
148 """ Attempts to execute file with 'path'. If 'hidden', no output is
150 shown.
149 shown.
151 """
150 """
152 self.execute_source('run %s' % path, hidden=hidden)
151 self.execute('execfile("%s")' % path, hidden=hidden)
153
152
154 def _get_kernel_manager(self):
153 def _get_kernel_manager(self):
155 """ Returns the current kernel manager.
154 """ Returns the current kernel manager.
@@ -274,10 +273,11 b' class FrontendWidget(HistoryConsoleWidget):'
274 self._call_tip()
273 self._call_tip()
275
274
276 def _handle_sub(self, omsg):
275 def _handle_sub(self, omsg):
277 if not self._hidden:
276 if self._hidden:
278 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
277 return
279 if handler is not None:
278 handler = getattr(self, '_handle_%s' % omsg['msg_type'], None)
280 handler(omsg)
279 if handler is not None:
280 handler(omsg)
281
281
282 def _handle_pyout(self, omsg):
282 def _handle_pyout(self, omsg):
283 session = omsg['parent_header']['session']
283 session = omsg['parent_header']['session']
@@ -286,8 +286,12 b' class FrontendWidget(HistoryConsoleWidget):'
286
286
287 def _handle_stream(self, omsg):
287 def _handle_stream(self, omsg):
288 self.appendPlainText(omsg['content']['data'])
288 self.appendPlainText(omsg['content']['data'])
289 self.moveCursor(QtGui.QTextCursor.End)
289
290
290 def _handle_execute_reply(self, rep):
291 def _handle_execute_reply(self, rep):
292 if self._hidden:
293 return
294
291 # Make sure that all output from the SUB channel has been processed
295 # Make sure that all output from the SUB channel has been processed
292 # before writing a new prompt.
296 # before writing a new prompt.
293 self.kernel_manager.sub_channel.flush()
297 self.kernel_manager.sub_channel.flush()
@@ -19,10 +19,10 b' class IPythonWidget(FrontendWidget):'
19 self._magic_overrides = {}
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 """ Reimplemented to override magic commands.
26 """ Reimplemented to override magic commands.
27 """
27 """
28 magic_source = source.strip()
28 magic_source = source.strip()
@@ -37,11 +37,18 b' class IPythonWidget(FrontendWidget):'
37 output = callback(arguments)
37 output = callback(arguments)
38 if output:
38 if output:
39 self.appendPlainText(output)
39 self.appendPlainText(output)
40 self._show_prompt('>>> ')
40 self._show_prompt()
41 return True
42 else:
41 else:
43 return super(IPythonWidget, self).execute_source(source, hidden,
42 super(IPythonWidget, self)._execute(source, hidden)
44 interactive)
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 # 'IPythonWidget' interface
54 # 'IPythonWidget' interface
General Comments 0
You need to be logged in to leave comments. Login now