##// END OF EJS Templates
Major improvements to terminal-style tab completion. Still work to be done, but a decent start.
epatters -
Show More
@@ -1,4 +1,5 b''
1 1 # Standard library imports
2 from os.path import commonprefix
2 3 import re
3 4 import sys
4 5 from textwrap import dedent
@@ -158,6 +159,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
158 159 self._reading = False
159 160 self._reading_callback = None
160 161 self._tab_width = 8
162 self._text_completing_pos = 0
161 163
162 164 # Set a monospaced font.
163 165 self.reset_font()
@@ -435,7 +437,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
435 437 def reset_font(self):
436 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 440 if sys.platform == 'win32':
440 441 # FIXME: we should test whether Consolas is available and use it
441 442 # first if it is. Consolas ships by default from Vista onwards,
@@ -557,18 +558,54 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
557 558 self._show_prompt()
558 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 576 def _complete_with_items(self, cursor, items):
561 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 583 if len(items) == 1:
564 584 cursor.setPosition(self._control.textCursor().position(),
565 585 QtGui.QTextCursor.KeepAnchor)
566 586 cursor.insertText(items[0])
587
567 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 596 if self.gui_completion:
597 cursor.movePosition(QtGui.QTextCursor.Left, n=len(prefix))
569 598 self._completion_widget.show_items(cursor, items)
570 599 else:
600 cursor.beginEditBlock()
601 self._append_plain_text('\n')
571 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 610 def _control_key_down(self, modifiers):
574 611 """ Given a KeyboardModifiers flags object, return whether the Control
@@ -594,6 +631,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
594 631 control.setAcceptRichText(False)
595 632 control.installEventFilter(self)
596 633 control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
634 control.cursorPositionChanged.connect(self._cursor_position_changed)
597 635 control.customContextMenuRequested.connect(self._show_context_menu)
598 636 control.copyAvailable.connect(self.copy_available)
599 637 control.redoAvailable.connect(self.redo_available)
@@ -625,6 +663,13 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
625 663 alt_down = event.modifiers() & QtCore.Qt.AltModifier
626 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 673 if event.matches(QtGui.QKeySequence.Paste):
629 674 # Call our paste instead of the underlying text widget's.
630 675 self.paste()
@@ -1159,7 +1204,9 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
1159 1204 """ Displays text using the pager if it exceeds the height of the
1160 1205 visible area.
1161 1206 """
1162 if self.paging != 'none':
1207 if self.paging == 'none':
1208 self._append_plain_text(text)
1209 else:
1163 1210 line_height = QtGui.QFontMetrics(self.font).height()
1164 1211 minlines = self._control.viewport().height() / line_height
1165 1212 if re.match("(?:[^\n]*\n){%i}" % minlines, text):
@@ -1177,11 +1224,8 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
1177 1224 self._page_control.setFocus()
1178 1225 else:
1179 1226 self.layout().setCurrentWidget(self._page_control)
1180 return
1181 if self._executing:
1182 self._append_plain_text(text)
1183 1227 else:
1184 self._append_plain_text_keeping_prompt(text)
1228 self._append_plain_text(text)
1185 1229
1186 1230 def _prompt_started(self):
1187 1231 """ Called immediately after a new prompt is displayed.
@@ -1333,6 +1377,26 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
1333 1377 self._prompt_pos = self._get_end_cursor().position()
1334 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 1401 class HistoryConsoleWidget(ConsoleWidget):
1338 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