Show More
@@ -268,6 +268,11 b' class ConsoleWidget(QtGui.QWidget):' | |||||
268 | A boolean indicating whether the source was executed. |
|
268 | A boolean indicating whether the source was executed. | |
269 | """ |
|
269 | """ | |
270 | if not hidden: |
|
270 | if not hidden: | |
|
271 | # Do everything here inside an edit block so continuation prompts | |||
|
272 | # are removed seamlessly via undo/redo. | |||
|
273 | cursor = self._control.textCursor() | |||
|
274 | cursor.beginEditBlock() | |||
|
275 | ||||
271 | if source is not None: |
|
276 | if source is not None: | |
272 | self.input_buffer = source |
|
277 | self.input_buffer = source | |
273 |
|
278 | |||
@@ -284,12 +289,20 b' class ConsoleWidget(QtGui.QWidget):' | |||||
284 | # This ensures that _prompt_pos does not become invalid due to |
|
289 | # This ensures that _prompt_pos does not become invalid due to | |
285 | # text truncation. |
|
290 | # text truncation. | |
286 | self._control.document().setMaximumBlockCount(self.buffer_size) |
|
291 | self._control.document().setMaximumBlockCount(self.buffer_size) | |
|
292 | ||||
|
293 | # Setting a positive maximum block count will automatically | |||
|
294 | # disable the undo/redo history, but just to be safe: | |||
|
295 | self._control.setUndoRedoEnabled(False) | |||
|
296 | ||||
287 | self._execute(real_source, hidden) |
|
297 | self._execute(real_source, hidden) | |
288 | elif hidden: |
|
298 | elif hidden: | |
289 | raise RuntimeError('Incomplete noninteractive input: "%s"' % source) |
|
299 | raise RuntimeError('Incomplete noninteractive input: "%s"' % source) | |
290 | else: |
|
300 | else: | |
291 | self._show_continuation_prompt() |
|
301 | self._show_continuation_prompt() | |
292 |
|
302 | |||
|
303 | if not hidden: | |||
|
304 | cursor.endEditBlock() | |||
|
305 | ||||
293 | return complete |
|
306 | return complete | |
294 |
|
307 | |||
295 | def _get_input_buffer(self): |
|
308 | def _get_input_buffer(self): | |
@@ -546,6 +559,7 b' class ConsoleWidget(QtGui.QWidget):' | |||||
546 | control.redoAvailable.connect(self.redo_available) |
|
559 | control.redoAvailable.connect(self.redo_available) | |
547 | control.undoAvailable.connect(self.undo_available) |
|
560 | control.undoAvailable.connect(self.undo_available) | |
548 | control.setReadOnly(True) |
|
561 | control.setReadOnly(True) | |
|
562 | control.setUndoRedoEnabled(False) | |||
549 | control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) |
|
563 | control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) | |
550 | return control |
|
564 | return control | |
551 |
|
565 | |||
@@ -555,6 +569,7 b' class ConsoleWidget(QtGui.QWidget):' | |||||
555 | control = QtGui.QPlainTextEdit() |
|
569 | control = QtGui.QPlainTextEdit() | |
556 | control.installEventFilter(self) |
|
570 | control.installEventFilter(self) | |
557 | control.setReadOnly(True) |
|
571 | control.setReadOnly(True) | |
|
572 | control.setUndoRedoEnabled(False) | |||
558 | control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) |
|
573 | control.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) | |
559 | return control |
|
574 | return control | |
560 |
|
575 | |||
@@ -664,10 +679,12 b' class ConsoleWidget(QtGui.QWidget):' | |||||
664 | if not self._reading and \ |
|
679 | if not self._reading and \ | |
665 | cursor.columnNumber() == len_prompt and \ |
|
680 | cursor.columnNumber() == len_prompt and \ | |
666 | position != self._prompt_pos: |
|
681 | position != self._prompt_pos: | |
|
682 | cursor.beginEditBlock() | |||
667 | cursor.movePosition(QtGui.QTextCursor.StartOfBlock, |
|
683 | cursor.movePosition(QtGui.QTextCursor.StartOfBlock, | |
668 | QtGui.QTextCursor.KeepAnchor) |
|
684 | QtGui.QTextCursor.KeepAnchor) | |
669 | cursor.removeSelectedText() |
|
685 | cursor.removeSelectedText() | |
670 | cursor.deletePreviousChar() |
|
686 | cursor.deletePreviousChar() | |
|
687 | cursor.endEditBlock() | |||
671 | intercepted = True |
|
688 | intercepted = True | |
672 |
|
689 | |||
673 | # Regular backwards deletion |
|
690 | # Regular backwards deletion | |
@@ -679,8 +696,23 b' class ConsoleWidget(QtGui.QWidget):' | |||||
679 | intercepted = not self._in_buffer(min(anchor, position)) |
|
696 | intercepted = not self._in_buffer(min(anchor, position)) | |
680 |
|
697 | |||
681 | elif key == QtCore.Qt.Key_Delete: |
|
698 | elif key == QtCore.Qt.Key_Delete: | |
682 | anchor = cursor.anchor() |
|
699 | ||
683 | intercepted = not self._in_buffer(min(anchor, position)) |
|
700 | # Line deletion (remove continuation prompt) | |
|
701 | if not self._reading and cursor.atBlockEnd() and not \ | |||
|
702 | cursor.hasSelection(): | |||
|
703 | cursor.movePosition(QtGui.QTextCursor.NextBlock, | |||
|
704 | QtGui.QTextCursor.KeepAnchor) | |||
|
705 | cursor.movePosition(QtGui.QTextCursor.Right, | |||
|
706 | QtGui.QTextCursor.KeepAnchor, | |||
|
707 | len(self._continuation_prompt)) | |||
|
708 | cursor.removeSelectedText() | |||
|
709 | intercepted = True | |||
|
710 | ||||
|
711 | # Regular forwards deletion: | |||
|
712 | else: | |||
|
713 | anchor = cursor.anchor() | |||
|
714 | intercepted = (not self._in_buffer(anchor) or | |||
|
715 | not self._in_buffer(position)) | |||
684 |
|
716 | |||
685 | # Don't move the cursor if control is down to allow copy-paste using |
|
717 | # Don't move the cursor if control is down to allow copy-paste using | |
686 | # the keyboard in any part of the buffer. |
|
718 | # the keyboard in any part of the buffer. | |
@@ -1026,7 +1058,10 b' class ConsoleWidget(QtGui.QWidget):' | |||||
1026 | """ |
|
1058 | """ | |
1027 | # Temporarily disable the maximum block count to permit undo/redo and |
|
1059 | # Temporarily disable the maximum block count to permit undo/redo and | |
1028 | # to ensure that the prompt position does not change due to truncation. |
|
1060 | # to ensure that the prompt position does not change due to truncation. | |
1029 | self._control.document().setMaximumBlockCount(0) |
|
1061 | # Because setting this property clears the undo/redo history, we only | |
|
1062 | # set it if we have to. | |||
|
1063 | if self._control.document().maximumBlockCount() > 0: | |||
|
1064 | self._control.document().setMaximumBlockCount(0) | |||
1030 | self._control.setUndoRedoEnabled(True) |
|
1065 | self._control.setUndoRedoEnabled(True) | |
1031 |
|
1066 | |||
1032 | self._control.setReadOnly(False) |
|
1067 | self._control.setReadOnly(False) | |
@@ -1039,7 +1074,6 b' class ConsoleWidget(QtGui.QWidget):' | |||||
1039 | """ Called immediately after a prompt is finished, i.e. when some input |
|
1074 | """ Called immediately after a prompt is finished, i.e. when some input | |
1040 | will be processed and a new prompt displayed. |
|
1075 | will be processed and a new prompt displayed. | |
1041 | """ |
|
1076 | """ | |
1042 | self._control.setUndoRedoEnabled(False) |
|
|||
1043 | self._control.setReadOnly(True) |
|
1077 | self._control.setReadOnly(True) | |
1044 | self._prompt_finished_hook() |
|
1078 | self._prompt_finished_hook() | |
1045 |
|
1079 |
@@ -296,8 +296,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
296 | # Decide if it makes sense to show a call tip |
|
296 | # Decide if it makes sense to show a call tip | |
297 | cursor = self._get_cursor() |
|
297 | cursor = self._get_cursor() | |
298 | cursor.movePosition(QtGui.QTextCursor.Left) |
|
298 | cursor.movePosition(QtGui.QTextCursor.Left) | |
299 | document = self._control.document() |
|
299 | if cursor.document().characterAt(cursor.position()).toAscii() != '(': | |
300 | if document.characterAt(cursor.position()).toAscii() != '(': |
|
|||
301 | return False |
|
300 | return False | |
302 | context = self._get_context(cursor) |
|
301 | context = self._get_context(cursor) | |
303 | if not context: |
|
302 | if not context: | |
@@ -312,14 +311,6 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
312 | def _complete(self): |
|
311 | def _complete(self): | |
313 | """ Performs completion at the current cursor location. |
|
312 | """ Performs completion at the current cursor location. | |
314 | """ |
|
313 | """ | |
315 | # Decide if it makes sense to do completion |
|
|||
316 |
|
||||
317 | # We should return only if the line is empty. Otherwise, let the |
|
|||
318 | # kernel split the line up. |
|
|||
319 | line = self._get_input_buffer_cursor_line() |
|
|||
320 | if not line: |
|
|||
321 | return False |
|
|||
322 |
|
||||
323 | # We let the kernel split the input line, so we *always* send an empty |
|
314 | # We let the kernel split the input line, so we *always* send an empty | |
324 | # text field. Readline-based frontends do get a real text field which |
|
315 | # text field. Readline-based frontends do get a real text field which | |
325 | # they can use. |
|
316 | # they can use. | |
@@ -327,12 +318,11 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
327 |
|
318 | |||
328 | # Send the completion request to the kernel |
|
319 | # Send the completion request to the kernel | |
329 | self._complete_id = self.kernel_manager.xreq_channel.complete( |
|
320 | self._complete_id = self.kernel_manager.xreq_channel.complete( | |
330 |
text, |
|
321 | text, # text | |
331 | line, # line |
|
322 | self._get_input_buffer_cursor_line(), # line | |
332 | self._get_input_buffer_cursor_column(), # cursor_pos |
|
323 | self._get_input_buffer_cursor_column(), # cursor_pos | |
333 | self.input_buffer) # block |
|
324 | self.input_buffer) # block | |
334 | self._complete_pos = self._get_cursor().position() |
|
325 | self._complete_pos = self._get_cursor().position() | |
335 | return True |
|
|||
336 |
|
326 | |||
337 | def _get_banner(self): |
|
327 | def _get_banner(self): | |
338 | """ Gets a banner to display at the beginning of a session. |
|
328 | """ Gets a banner to display at the beginning of a session. | |
@@ -342,7 +332,8 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
342 | return banner % (sys.version, sys.platform) |
|
332 | return banner % (sys.version, sys.platform) | |
343 |
|
333 | |||
344 | def _get_context(self, cursor=None): |
|
334 | def _get_context(self, cursor=None): | |
345 |
""" Gets the context |
|
335 | """ Gets the context for the specified cursor (or the current cursor | |
|
336 | if none is specified). | |||
346 | """ |
|
337 | """ | |
347 | if cursor is None: |
|
338 | if cursor is None: | |
348 | cursor = self._get_cursor() |
|
339 | cursor = self._get_cursor() |
General Comments 0
You need to be logged in to leave comments.
Login now