Skip to content

add syntax highlight to notesedit

rnons edited this page Dec 3, 2012 · 3 revisions

I lost the chance to record the birth of mikidown, however, I will try to write about every major improvement of mikidown from now on.

I generate the new homepage with the help of github page yesterday. It currently contains only one snapshot. As you can see, the main window of mikidown consists of two major elements: notesEdit (where you edit you notes, in markdown hopefully) and notesView (where mikidown renders your notes). This article explains the recent added syntax highlighting in notesEdit.

Introducing QSyntaxHighlighter Class

We will use the QSyntaxHighlighter Class in PyQt library.

The QSyntaxHighlighter class is a base class for implementing QTextEdit syntax highlighters. A syntax highlighter automatically highlights parts of the text in a QTextEdit, or more generally in a QTextDocument.

To provide your own syntax highlighting, you must subclass QSyntaxHighlighter and reimplement highlightBlock().

QSyntaxHighlighter provides the setFormat() function which applies a given QTextCharFormat on the current text block.

As I understand it, in highlightBlock()we need to

  1. Define several patterns that will be highlighted
  2. Call setFormat() to apply different color and font styles to different patterns

Let's see the type signature (well, I mean the declaration of) setFormat():

QSyntaxHighlighter.setFormat (self, int start, int count, QTextCharFormat format)

We can leave the QTextCharFormat part here, and only concern how we get the start and count. The finditer function from module re is what we need.

re.finditer(pattern, string[, flags])

The return value of finditer is an MatchObject, let's name it match. As it turns out, match.start() and match.end() - match.start() are what we should pass to setFormat().

Apply it to mikidown

First, as suggested by the documentation, we need to subclass QSyntaxHighlighter and reimplement highlightBlock().

class MikiHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super(MikiHighlighter, self).__init__(parent)
        # put definition of patterns here
        # for performance reason, it's better to re.compile your patterns here, rather than in highlightBlock

    def highlightBlock(self, text):
        # for each pattern we defined in __init__,
        # let match = p.finditer(text), and then setFormat
        self.setFormat(match.start(), match.end() - match.start(), p)

Second, we need to pass our notesEdit to MikiHighlighter.

In mikidown/init.py, we have

self.notesEdit = QTextEdit()                           
MikiHighlighter(self.notesEdit.document())     # this is what we added

You see, simply one line will do it. Also note that what we actually passed to MikiHighlighter is notesEdit.document().

You may be interested to see the full code of mikidown/highlighter.py.