##// 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 # 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 != 'none':
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 return
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