Show More
@@ -1,4 +1,5 b'' | |||||
1 | # Standard library imports |
|
1 | # Standard library imports | |
|
2 | from os.path import commonprefix | |||
2 | import re |
|
3 | import re | |
3 | import sys |
|
4 | import sys | |
4 | from textwrap import dedent |
|
5 | from textwrap import dedent | |
@@ -158,6 +159,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
158 | self._reading = False |
|
159 | self._reading = False | |
159 | self._reading_callback = None |
|
160 | self._reading_callback = None | |
160 | self._tab_width = 8 |
|
161 | self._tab_width = 8 | |
|
162 | self._text_completing_pos = 0 | |||
161 |
|
163 | |||
162 | # Set a monospaced font. |
|
164 | # Set a monospaced font. | |
163 | self.reset_font() |
|
165 | self.reset_font() | |
@@ -435,7 +437,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
435 | def reset_font(self): |
|
437 | def reset_font(self): | |
436 | """ Sets the font to the default fixed-width font for this platform. |
|
438 | """ Sets the font to the default fixed-width font for this platform. | |
437 | """ |
|
439 | """ | |
438 | # FIXME: font family and size should be configurable by the user. |
|
|||
439 | if sys.platform == 'win32': |
|
440 | if sys.platform == 'win32': | |
440 | # FIXME: we should test whether Consolas is available and use it |
|
441 | # FIXME: we should test whether Consolas is available and use it | |
441 | # first if it is. Consolas ships by default from Vista onwards, |
|
442 | # first if it is. Consolas ships by default from Vista onwards, | |
@@ -557,18 +558,54 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
557 | self._show_prompt() |
|
558 | self._show_prompt() | |
558 | self.input_buffer = input_buffer |
|
559 | self.input_buffer = input_buffer | |
559 |
|
560 | |||
|
561 | def _clear_temporary_buffer(self): | |||
|
562 | """ Clears the "temporary text" buffer, i.e. all the text following | |||
|
563 | the prompt region. | |||
|
564 | """ | |||
|
565 | cursor = self._get_prompt_cursor() | |||
|
566 | found_block = cursor.movePosition(QtGui.QTextCursor.NextBlock) | |||
|
567 | if found_block: | |||
|
568 | while found_block and \ | |||
|
569 | cursor.block().text().startsWith(self._continuation_prompt): | |||
|
570 | found_block = cursor.movePosition(QtGui.QTextCursor.NextBlock) | |||
|
571 | cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline. | |||
|
572 | cursor.movePosition(QtGui.QTextCursor.End, | |||
|
573 | QtGui.QTextCursor.KeepAnchor) | |||
|
574 | cursor.removeSelectedText() | |||
|
575 | ||||
560 | def _complete_with_items(self, cursor, items): |
|
576 | def _complete_with_items(self, cursor, items): | |
561 | """ Performs completion with 'items' at the specified cursor location. |
|
577 | """ Performs completion with 'items' at the specified cursor location. | |
562 | """ |
|
578 | """ | |
|
579 | if self._text_completing_pos: | |||
|
580 | self._clear_temporary_buffer() | |||
|
581 | self._text_completing_pos = 0 | |||
|
582 | ||||
563 | if len(items) == 1: |
|
583 | if len(items) == 1: | |
564 | cursor.setPosition(self._control.textCursor().position(), |
|
584 | cursor.setPosition(self._control.textCursor().position(), | |
565 | QtGui.QTextCursor.KeepAnchor) |
|
585 | QtGui.QTextCursor.KeepAnchor) | |
566 | cursor.insertText(items[0]) |
|
586 | cursor.insertText(items[0]) | |
|
587 | ||||
567 | elif len(items) > 1: |
|
588 | elif len(items) > 1: | |
|
589 | current_pos = self._control.textCursor().position() | |||
|
590 | prefix = commonprefix(items) | |||
|
591 | if prefix: | |||
|
592 | cursor.setPosition(current_pos, QtGui.QTextCursor.KeepAnchor) | |||
|
593 | cursor.insertText(prefix) | |||
|
594 | current_pos = cursor.position() | |||
|
595 | ||||
568 | if self.gui_completion: |
|
596 | if self.gui_completion: | |
|
597 | cursor.movePosition(QtGui.QTextCursor.Left, n=len(prefix)) | |||
569 | self._completion_widget.show_items(cursor, items) |
|
598 | self._completion_widget.show_items(cursor, items) | |
570 | else: |
|
599 | else: | |
|
600 | cursor.beginEditBlock() | |||
|
601 | self._append_plain_text('\n') | |||
571 | self._page(self._format_as_columns(items)) |
|
602 | self._page(self._format_as_columns(items)) | |
|
603 | cursor.endEditBlock() | |||
|
604 | ||||
|
605 | cursor.setPosition(current_pos) | |||
|
606 | self._control.moveCursor(QtGui.QTextCursor.End) | |||
|
607 | self._control.setTextCursor(cursor) | |||
|
608 | self._text_completing_pos = current_pos | |||
572 |
|
609 | |||
573 | def _control_key_down(self, modifiers): |
|
610 | def _control_key_down(self, modifiers): | |
574 | """ Given a KeyboardModifiers flags object, return whether the Control |
|
611 | """ Given a KeyboardModifiers flags object, return whether the Control | |
@@ -594,6 +631,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
594 | control.setAcceptRichText(False) |
|
631 | control.setAcceptRichText(False) | |
595 | control.installEventFilter(self) |
|
632 | control.installEventFilter(self) | |
596 | control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) |
|
633 | control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) | |
|
634 | control.cursorPositionChanged.connect(self._cursor_position_changed) | |||
597 | control.customContextMenuRequested.connect(self._show_context_menu) |
|
635 | control.customContextMenuRequested.connect(self._show_context_menu) | |
598 | control.copyAvailable.connect(self.copy_available) |
|
636 | control.copyAvailable.connect(self.copy_available) | |
599 | control.redoAvailable.connect(self.redo_available) |
|
637 | control.redoAvailable.connect(self.redo_available) | |
@@ -625,6 +663,13 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
625 | alt_down = event.modifiers() & QtCore.Qt.AltModifier |
|
663 | alt_down = event.modifiers() & QtCore.Qt.AltModifier | |
626 | shift_down = event.modifiers() & QtCore.Qt.ShiftModifier |
|
664 | shift_down = event.modifiers() & QtCore.Qt.ShiftModifier | |
627 |
|
665 | |||
|
666 | # Special handling when tab completing in text mode: | |||
|
667 | if self._text_completing_pos: | |||
|
668 | if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return, | |||
|
669 | QtCore.Qt.Key_Escape): | |||
|
670 | self._clear_temporary_buffer() | |||
|
671 | self._text_completing_pos = 0 | |||
|
672 | ||||
628 | if event.matches(QtGui.QKeySequence.Paste): |
|
673 | if event.matches(QtGui.QKeySequence.Paste): | |
629 | # Call our paste instead of the underlying text widget's. |
|
674 | # Call our paste instead of the underlying text widget's. | |
630 | self.paste() |
|
675 | self.paste() | |
@@ -1159,7 +1204,9 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1159 | """ Displays text using the pager if it exceeds the height of the |
|
1204 | """ Displays text using the pager if it exceeds the height of the | |
1160 | visible area. |
|
1205 | visible area. | |
1161 | """ |
|
1206 | """ | |
1162 |
if self.paging |
|
1207 | if self.paging == 'none': | |
|
1208 | self._append_plain_text(text) | |||
|
1209 | else: | |||
1163 | line_height = QtGui.QFontMetrics(self.font).height() |
|
1210 | line_height = QtGui.QFontMetrics(self.font).height() | |
1164 | minlines = self._control.viewport().height() / line_height |
|
1211 | minlines = self._control.viewport().height() / line_height | |
1165 | if re.match("(?:[^\n]*\n){%i}" % minlines, text): |
|
1212 | if re.match("(?:[^\n]*\n){%i}" % minlines, text): | |
@@ -1177,11 +1224,8 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1177 | self._page_control.setFocus() |
|
1224 | self._page_control.setFocus() | |
1178 | else: |
|
1225 | else: | |
1179 | self.layout().setCurrentWidget(self._page_control) |
|
1226 | self.layout().setCurrentWidget(self._page_control) | |
1180 |
|
|
1227 | else: | |
1181 | if self._executing: |
|
1228 | self._append_plain_text(text) | |
1182 | self._append_plain_text(text) |
|
|||
1183 | else: |
|
|||
1184 | self._append_plain_text_keeping_prompt(text) |
|
|||
1185 |
|
1229 | |||
1186 | def _prompt_started(self): |
|
1230 | def _prompt_started(self): | |
1187 | """ Called immediately after a new prompt is displayed. |
|
1231 | """ Called immediately after a new prompt is displayed. | |
@@ -1333,6 +1377,26 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1333 | self._prompt_pos = self._get_end_cursor().position() |
|
1377 | self._prompt_pos = self._get_end_cursor().position() | |
1334 | self._prompt_started() |
|
1378 | self._prompt_started() | |
1335 |
|
1379 | |||
|
1380 | #------ Signal handlers ---------------------------------------------------- | |||
|
1381 | ||||
|
1382 | def _cursor_position_changed(self): | |||
|
1383 | """ Clears the temporary buffer based on the cursor position. | |||
|
1384 | """ | |||
|
1385 | if self._text_completing_pos: | |||
|
1386 | document = self._control.document() | |||
|
1387 | if self._text_completing_pos < document.characterCount(): | |||
|
1388 | cursor = self._control.textCursor() | |||
|
1389 | pos = cursor.position() | |||
|
1390 | text_cursor = self._control.textCursor() | |||
|
1391 | text_cursor.setPosition(self._text_completing_pos) | |||
|
1392 | if pos < self._text_completing_pos or \ | |||
|
1393 | cursor.blockNumber() > text_cursor.blockNumber(): | |||
|
1394 | self._clear_temporary_buffer() | |||
|
1395 | self._text_completing_pos = 0 | |||
|
1396 | else: | |||
|
1397 | self._clear_temporary_buffer() | |||
|
1398 | self._text_completing_pos = 0 | |||
|
1399 | ||||
1336 |
|
1400 | |||
1337 | class HistoryConsoleWidget(ConsoleWidget): |
|
1401 | class HistoryConsoleWidget(ConsoleWidget): | |
1338 | """ A ConsoleWidget that keeps a history of the commands that have been |
|
1402 | """ A ConsoleWidget that keeps a history of the commands that have been |
General Comments 0
You need to be logged in to leave comments.
Login now