##// END OF EJS Templates
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
epatters -
Show More
@@ -192,7 +192,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
192 elif etype == QtCore.QEvent.MouseButtonRelease and \
192 elif etype == QtCore.QEvent.MouseButtonRelease and \
193 event.button() == QtCore.Qt.MidButton and \
193 event.button() == QtCore.Qt.MidButton and \
194 obj == self._control.viewport():
194 obj == self._control.viewport():
195 cursor = self._control.cursorForPosition(event.pos());
195 cursor = self._control.cursorForPosition(event.pos())
196 self._control.setTextCursor(cursor)
196 self._control.setTextCursor(cursor)
197 self.paste(QtGui.QClipboard.Selection)
197 self.paste(QtGui.QClipboard.Selection)
198 return True
198 return True
@@ -578,31 +578,46 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
578 self._show_prompt()
578 self._show_prompt()
579 self.input_buffer = input_buffer
579 self.input_buffer = input_buffer
580
580
581 def _cancel_text_completion(self):
582 """ If text completion is progress, cancel it.
583 """
584 if self._text_completing_pos:
585 self._clear_temporary_buffer()
586 self._text_completing_pos = 0
587
581 def _clear_temporary_buffer(self):
588 def _clear_temporary_buffer(self):
582 """ Clears the "temporary text" buffer, i.e. all the text following
589 """ Clears the "temporary text" buffer, i.e. all the text following
583 the prompt region.
590 the prompt region.
584 """
591 """
592 # Select and remove all text below the input buffer.
585 cursor = self._get_prompt_cursor()
593 cursor = self._get_prompt_cursor()
586 if cursor.movePosition(QtGui.QTextCursor.NextBlock):
594 prompt = self._continuation_prompt.lstrip()
587 prompt = self._continuation_prompt.lstrip()
595 while cursor.movePosition(QtGui.QTextCursor.NextBlock):
588 while True:
596 temp_cursor = QtGui.QTextCursor(cursor)
589 temp_cursor = QtGui.QTextCursor(cursor)
597 temp_cursor.select(QtGui.QTextCursor.BlockUnderCursor)
590 temp_cursor.select(QtGui.QTextCursor.BlockUnderCursor)
598 text = str(temp_cursor.selection().toPlainText()).lstrip()
591 text = str(temp_cursor.selection().toPlainText()).lstrip()
599 if not text.startswith(prompt):
592 if not text.startswith(prompt) or \
600 break
593 not cursor.movePosition(QtGui.QTextCursor.NextBlock):
601 else:
594 break
602 # We've reached the end of the input buffer and no text follows.
595 cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline.
603 return
596 cursor.movePosition(QtGui.QTextCursor.End,
604 cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline.
597 QtGui.QTextCursor.KeepAnchor)
605 cursor.movePosition(QtGui.QTextCursor.End,
598 cursor.removeSelectedText()
606 QtGui.QTextCursor.KeepAnchor)
607 cursor.removeSelectedText()
608
609 # After doing this, we have no choice but to clear the undo/redo
610 # history. Otherwise, the text is not "temporary" at all, because it
611 # can be recalled with undo/redo. Unfortunately, Qt does not expose
612 # fine-grained control to the undo/redo system.
613 if self._control.isUndoRedoEnabled():
614 self._control.setUndoRedoEnabled(False)
615 self._control.setUndoRedoEnabled(True)
599
616
600 def _complete_with_items(self, cursor, items):
617 def _complete_with_items(self, cursor, items):
601 """ Performs completion with 'items' at the specified cursor location.
618 """ Performs completion with 'items' at the specified cursor location.
602 """
619 """
603 if self._text_completing_pos:
620 self._cancel_text_completion()
604 self._clear_temporary_buffer()
605 self._text_completing_pos = 0
606
621
607 if len(items) == 1:
622 if len(items) == 1:
608 cursor.setPosition(self._control.textCursor().position(),
623 cursor.setPosition(self._control.textCursor().position(),
@@ -785,9 +800,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
785 intercepted = True
800 intercepted = True
786
801
787 # Special handling when tab completing in text mode.
802 # Special handling when tab completing in text mode.
788 if self._text_completing_pos:
803 self._cancel_text_completion()
789 self._clear_temporary_buffer()
790 self._text_completing_pos = 0
791
804
792 if self._in_buffer(position):
805 if self._in_buffer(position):
793 if self._reading:
806 if self._reading:
@@ -1251,8 +1264,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
1251 """ Cancels the current editing task ala Ctrl-G in Emacs.
1264 """ Cancels the current editing task ala Ctrl-G in Emacs.
1252 """
1265 """
1253 if self._text_completing_pos:
1266 if self._text_completing_pos:
1254 self._clear_temporary_buffer()
1267 self._cancel_text_completion()
1255 self._text_completing_pos = 0
1256 else:
1268 else:
1257 self.input_buffer = ''
1269 self.input_buffer = ''
1258
1270
@@ -138,17 +138,22 b' class IPythonWidget(FrontendWidget):'
138 info.pos == cursor.position():
138 info.pos == cursor.position():
139 matches = rep['content']['matches']
139 matches = rep['content']['matches']
140 text = rep['content']['matched_text']
140 text = rep['content']['matched_text']
141
141 offset = len(text)
142 # Clean up matches with '.'s and path separators.
142
143 parts = re.split(r'[./\\]', text)
143 # Clean up matches with period and path separators if the matched
144 sep_count = len(parts) - 1
144 # text has not been transformed. This is done by truncating all
145 if sep_count:
145 # but the last component and then suitably decreasing the offset
146 chop_length = sum(map(len, parts[:sep_count])) + sep_count
146 # between the current cursor position and the start of completion.
147 matches = [ match[chop_length:] for match in matches ]
147 if len(matches) > 1 and matches[0][:offset] == text:
148 text = text[chop_length:]
148 parts = re.split(r'[./\\]', text)
149 sep_count = len(parts) - 1
150 if sep_count:
151 chop_length = sum(map(len, parts[:sep_count])) + sep_count
152 matches = [ match[chop_length:] for match in matches ]
153 offset -= chop_length
149
154
150 # Move the cursor to the start of the match and complete.
155 # Move the cursor to the start of the match and complete.
151 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
156 cursor.movePosition(QtGui.QTextCursor.Left, n=offset)
152 self._complete_with_items(cursor, matches)
157 self._complete_with_items(cursor, matches)
153
158
154 def _handle_execute_reply(self, msg):
159 def _handle_execute_reply(self, msg):
General Comments 0
You need to be logged in to leave comments. Login now