##// END OF EJS Templates
ENH: Documentation for configuring the DefaultFormatter.
ENH: Documentation for configuring the DefaultFormatter.

File last commit:

r2982:f21a128a
r3211:f31dfc45
Show More
bracket_matcher.py
101 lines | 3.7 KiB | text/x-python | PythonLexer
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894 """ Provides bracket matching for Q[Plain]TextEdit widgets.
"""
# System library imports
from PyQt4 import QtCore, QtGui
class BracketMatcher(QtCore.QObject):
""" Matches square brackets, braces, and parentheses based on cursor
position.
"""
# Protected class variables.
_opening_map = { '(':')', '{':'}', '[':']' }
_closing_map = { ')':'(', '}':'{', ']':'[' }
#--------------------------------------------------------------------------
# 'QObject' interface
#--------------------------------------------------------------------------
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 def __init__(self, text_edit):
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894 """ Create a call tip manager that is attached to the specified Qt
text edit widget.
"""
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 assert isinstance(text_edit, (QtGui.QTextEdit, QtGui.QPlainTextEdit))
super(BracketMatcher, self).__init__()
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894
# The format to apply to matching brackets.
self.format = QtGui.QTextCharFormat()
self.format.setBackground(QtGui.QColor('silver'))
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 self._text_edit = text_edit
text_edit.cursorPositionChanged.connect(self._cursor_position_changed)
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894
#--------------------------------------------------------------------------
# Protected interface
#--------------------------------------------------------------------------
def _find_match(self, position):
""" Given a valid position in the text document, try to find the
position of the matching bracket. Returns -1 if unsuccessful.
"""
# Decide what character to search for and what direction to search in.
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 document = self._text_edit.document()
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894 qchar = document.characterAt(position)
start_char = qchar.toAscii()
search_char = self._opening_map.get(start_char)
if search_char:
increment = 1
else:
search_char = self._closing_map.get(start_char)
if search_char:
increment = -1
else:
return -1
# Search for the character.
depth = 0
while position >= 0 and position < document.characterCount():
char = qchar.toAscii()
if char == start_char:
depth += 1
elif char == search_char:
depth -= 1
if depth == 0:
break
position += increment
qchar = document.characterAt(position)
else:
position = -1
return position
def _selection_for_character(self, position):
""" Convenience method for selecting a character.
"""
selection = QtGui.QTextEdit.ExtraSelection()
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 cursor = self._text_edit.textCursor()
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894 cursor.setPosition(position)
cursor.movePosition(QtGui.QTextCursor.NextCharacter,
QtGui.QTextCursor.KeepAnchor)
selection.cursor = cursor
selection.format = self.format
return selection
#------ Signal handlers ----------------------------------------------------
def _cursor_position_changed(self):
""" Updates the document formatting based on the new cursor position.
"""
# Clear out the old formatting.
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 self._text_edit.setExtraSelections([])
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894
# Attempt to match a bracket for the new cursor position.
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 cursor = self._text_edit.textCursor()
epatters
First cut at a generic bracket matcher for Q[Plain]TextEdits.
r2894 if not cursor.hasSelection():
position = cursor.position() - 1
match_position = self._find_match(position)
if match_position != -1:
extra_selections = [ self._selection_for_character(pos)
for pos in (position, match_position) ]
epatters
Fixed the segfaults on application exit. The BracketMatcher, CallTipWidget, and CompletionWidget were using the text control as their parents. This should not be a problem, but for some reason it resulted in problems during shutdown. I suspect that PyQt is bugged and was deleting the C++ objects a second time in the garbage collection phase after they had already been deleted automatically by the C++ layer of Qt.
r2982 self._text_edit.setExtraSelections(extra_selections)