Commits

Henning Schröder committed b0d7c88

added mode to highlight occurences of words, highlights current word on idle (after 2 seconds)

Comments (0)

Files changed (6)

 import re
 
 from PyQt4.QtCore import (
-    Qt, QString, SIGNAL, QVariant, QThread, QLine, QSize, QRect,
+    Qt, QString, SIGNAL, QVariant, QThread, QLine, QSize, QRect, QTimer,
     QAbstractListModel, QModelIndex)
 from PyQt4.QtGui import (
     QApplication, QWidget, QHBoxLayout, QToolTip,

codeaide/modes/lines.py

             
             self.sel = QTextEdit.ExtraSelection()
             self.sel.cursor = QTextCursor(self.textedit.textCursor())
-            self.sel.cursor.select(QTextCursor.LineUnderCursor)
             self.sel.format.setBackground(self.brush)
             self.sel.format.setProperty(QTextFormat.FullWidthSelection, QVariant(True))
+            self.sel.cursor.select(QTextCursor.LineUnderCursor)
             self.textedit.setExtraSelections([self.sel])
 
     

codeaide/modes/occurences.py

+import re
+from codeaide.base import *
+
+
+is_word = re.compile("^\w+$").match
+
+
+class Occurences(ModeBase):
+
+
+    def init(self, wait_seconds=2):
+        self.old_pos = -1
+        self.brush = QBrush(QColor("yellow"))
+        self.selections = []
+        self.textedit.connect(self.textedit, SIGNAL("idle()"), self.on_idle)
+
+        
+    def highlight_word_in_block(self, word, block):
+        block_pos = block.position()
+        text = unicode(block.text())
+        length = len(word)
+        i = 0
+        while True:
+            found = text.find(word, i)
+            if found == -1:
+                break
+            col = block_pos + found
+            sel = QTextEdit.ExtraSelection()
+            sel.cursor = QTextCursor(block)
+            sel.cursor.setPosition(col)
+            sel.cursor.setPosition(col+length, QTextCursor.KeepAnchor)
+            #sel.cursor.select(QTextCursor.WordUnderCursor)
+            sel.format.setBackground(self.brush)
+            self.selections.append(sel)
+            i += len(word)
+
+
+    def on_idle(self):
+        self.highlight_current_word()
+
+        
+    def highlight_word(self, word):
+        # This maybe also used by a search function
+        self.textedit.remove_extra_selections(self.selections)
+        self.selections = []
+
+        block = self.textedit.firstVisibleBlock()
+        bounding_rect = self.textedit.blockBoundingRect
+        y = 0
+        height = self.textedit.height()
+        while block and block.isValid() and y < height:
+            if not block.isVisible():
+                continue
+            self.highlight_word_in_block(word, block)
+            y += bounding_rect(block).height()
+            block = block.next()
+        self.textedit.add_extra_selections(self.selections)
+
+
+    def highlight_current_word(self):
+        cursor = self.textedit.textCursor()
+        pos = cursor.position()
+        if pos == self.old_pos:
+            return
+        self.old_pos = pos
+
+        cursor.select(QTextCursor.WordUnderCursor)
+        word = unicode(cursor.selectedText())
+        if not word or not is_word(word):
+            return
+        self.highlight_word(word)
+
+        
+    def on_highlight_current_word(self, event, key, modifiers, text):
+        self.highlight_current_word()
+
+
+    keyboard_hooks = {
+        (Qt.Key_O, Qt.ControlModifier): on_highlight_current_word,
+        }

codeaide/widget.py

 
 
 
-
 class CodeAide(QPlainTextEdit):
 
 
         self.paint_hooks = {}
         self.resize_hooks = {}
         self.installed_modes = []
+        self.idle_timer_id = self.startTimer(2000)
+
+
+    def not_idle(self):
+        self.killTimer(self.idle_timer_id)
+        self.idle_timer_id = self.startTimer(2000)
+
+
+    def timerEvent(self, event):
+        self.killTimer(self.idle_timer_id)
+        QTimer.singleShot(0, self._emit_idle)
+        self.idle_timer_id = self.startTimer(2000)
+
+
+    def _emit_idle(self):
+        self.emit(SIGNAL("idle()"))
 
 
     def set_font(self, name="Monospace", size=10):
                 return mode
 
 
-
     def is_installed(self, mode):
         for installed in self.installed_modes:
             if installed.__class__ is mode:
         painter.end()
         return QPlainTextEdit.paintEvent(self, event)
 
+    
+    def mousePressEvent(self, event):
+        self.not_idle()
+        return QPlainTextEdit.mousePressEvent(self, event)
+
 
     def keyPressEvent(self, event):
         key = event.key()
                 h.get((key, -1), []):
             if callback(event, key, modifiers, text):
                 return
+        self.not_idle()
         return QPlainTextEdit.keyPressEvent(self, event)
 
 
 
     
     def mark_unmodified(self):
+        # XXX this should be done inside line status mode
         block = self.document().begin()
         while block and block.isValid():
             user_data = self.user_data(block)
 
     def setText(self, text):
         self.setPlainText(text)
+        #self.emit("newText")
         self.mark_unmodified()
 
 
+    def remove_extra_selections(self, selections):
+        l = []
+        for sel in self.extraSelections():
+            if not sel in selections:
+                l.append(sel)
+        self.setExtraSelections(l)
+            
 
+    def add_extra_selections(self, selections):
+        self.setExtraSelections(self.extraSelections() + selections)
+
+
 snippets: loader for gedit and textmate, integrate with completer
 add syntax highlighter (also load from textmate bundles?)
 flymake-mode with pylint implementation (threading!)
+get inspiration from http://nschum.de/src/emacs/
         "Folding",
         "Snippets",
         "TextCompleter",
+        "Occurences",
         )
     edit.resize(800,600)
     edit.show()