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