##// 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):
587 prompt = self._continuation_prompt.lstrip()
594 prompt = self._continuation_prompt.lstrip()
588 while True:
595 while cursor.movePosition(QtGui.QTextCursor.NextBlock):
589 temp_cursor = QtGui.QTextCursor(cursor)
596 temp_cursor = QtGui.QTextCursor(cursor)
590 temp_cursor.select(QtGui.QTextCursor.BlockUnderCursor)
597 temp_cursor.select(QtGui.QTextCursor.BlockUnderCursor)
591 text = str(temp_cursor.selection().toPlainText()).lstrip()
598 text = str(temp_cursor.selection().toPlainText()).lstrip()
592 if not text.startswith(prompt) or \
599 if not text.startswith(prompt):
593 not cursor.movePosition(QtGui.QTextCursor.NextBlock):
594 break
600 break
601 else:
602 # We've reached the end of the input buffer and no text follows.
603 return
595 cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline.
604 cursor.movePosition(QtGui.QTextCursor.Left) # Grab the newline.
596 cursor.movePosition(QtGui.QTextCursor.End,
605 cursor.movePosition(QtGui.QTextCursor.End,
597 QtGui.QTextCursor.KeepAnchor)
606 QtGui.QTextCursor.KeepAnchor)
598 cursor.removeSelectedText()
607 cursor.removeSelectedText()
599
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)
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 offset = len(text)
141
142
142 # Clean up matches with '.'s and path separators.
143 # Clean up matches with period and path separators if the matched
144 # text has not been transformed. This is done by truncating all
145 # but the last component and then suitably decreasing the offset
146 # between the current cursor position and the start of completion.
147 if len(matches) > 1 and matches[0][:offset] == text:
143 parts = re.split(r'[./\\]', text)
148 parts = re.split(r'[./\\]', text)
144 sep_count = len(parts) - 1
149 sep_count = len(parts) - 1
145 if sep_count:
150 if sep_count:
146 chop_length = sum(map(len, parts[:sep_count])) + sep_count
151 chop_length = sum(map(len, parts[:sep_count])) + sep_count
147 matches = [ match[chop_length:] for match in matches ]
152 matches = [ match[chop_length:] for match in matches ]
148 text = text[chop_length:]
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