All about styles

Are you familiar with Microsoft Word? In Word you can define styles – each one with different attributes like bold, italic, color, size, … While making your document, you simply select the desired style for the current text you’re typing:

    <<< Click on this button to see an example screenshot.

 

About the QsciStyle object

Syntax highlighting in QScintilla works exactly the same. The options of a style are stored in a QsciStyle-object. To create a new style, you’ve got to make a new instance of this class. Imagine you want to create three different styles: myStyle_0 is black, myStyle_1 is red and myStyle_2 is blue. You’ll need something like this:

 

 

Did you notice on the figure that every style has a number? I’m not referring to the numbers in the names – those are just a coincindence – but the numerical references in the MyLexer class. That’s right, a QsciStyle-object can be identified by either its name or its number :


 

Create QsciStyle objects

How do you create a new QsciStyle-object? It’s a bit weird. Just start giving attributes (like color, bold, italic, …) to a style, and QScintilla internally makes the object. Your handle to the style-object is its ID-number.
Let’s consider an example. Imagine no styles have been created yet. You want to create style 0 – so you just assign a random attribute to it. Internally, QScintilla makes the object:

class MyLexer(QsciLexerCustom):

    def __init__(self, parent):
        super(MyLexer, self).__init__(parent)

        # Assign a random attribute to style 0. QScintilla will
        # internally create style 0 (instantiate the
        # QsciStyle-class) if the object didn't exist yet.
        self.setColor(QColor("#ff7f0000"), 0)

        [...]

    ''''''

That’s really it.

Style
A QsciStyle-object stores the options of a style. Every style is referred by its ID-number.
Don’t create a new QsciStyle-object yourself. Simply start assigning attributes to style nr  n. QScintilla internally creates style nr  n  if it didn’t exist yet.

 
Although you will always use the ID-number to refer to styles, QScintilla requires you to give them names. These descriptive names are “intended to be used in user preference dialogs”. That’s the only clue we can find in the QScintilla docs. Anyway, these descriptive names should be assigned in the description() method. You must implement this method, otherwise QScintilla simply refuses to perform any syntax highlighting!
Just one more thing. What if a piece of text is not (yet) given any style at all? In that case, the lexer falls back on its default style. You can choose the options for the default style easily.

Given everything we know about styles right now, it’s time to analyze an example:

class MyLexer(QsciLexerCustom):

    def __init__(self, parent):
        super(MyLexer, self).__init__(parent)
		
        # Default text settings
        # ----------------------
        self.setDefaultColor(QColor("#ff000000"))
        self.setDefaultPaper(QColor("#ffffffff"))
        self.setDefaultFont(QFont("Consolas", 14))

        # Initialize colors per style
        # ----------------------------
        self.setColor(QColor("#ff000000"), 0)   # Style 0: black
        self.setColor(QColor("#ff7f0000"), 1)   # Style 1: red
        self.setColor(QColor("#ff0000bf"), 2)   # Style 2: blue

        # Initialize paper colors per style
        # ----------------------------------
        self.setPaper(QColor("#ffffffff"), 0)   # Style 0: white
        self.setPaper(QColor("#ffffffff"), 1)   # Style 1: white
        self.setPaper(QColor("#ffffffff"), 2)   # Style 2: white

        # Initialize fonts per style
        # ---------------------------
        self.setFont(QFont("Consolas", 14, weight=QFont.Bold), 0)   # Style 0: 14pt bold
        self.setFont(QFont("Consolas", 14, weight=QFont.Bold), 1)   # Style 1: 14pt bold
        self.setFont(QFont("Consolas", 14, weight=QFont.Bold), 2)   # Style 2: 14pt bold

    ''''''

    # Returns the descriptive name for style number style_nr. For a valid
    # style number for this language a non-empty QString must be returned.
    # If the style number is invalid then an empty QString must be returned.
    # This is intended to be used in user preference dialogs.
    def description(self, style_nr):
        if style == 0:
            return "myStyle_0"
        elif style == 1:
            return "myStyle_1"
        elif style == 2:
            return "myStyle_2"
        ###
        return ""

    ''''''
    
    [...]
	
'''--- end class ---'''

This code created three styles. Style 0 – named myStyle_0 – is black and bold. Style 1 is red and bold. Style 2 is blue and bold. What we need right now is the actual syntax highlighting in action! That’s what the styleText() method will do for us. The next page dives into that.