QScintilla/Lexers/SubstyledLexer.py

Sat, 09 Mar 2019 17:36:44 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 09 Mar 2019 17:36:44 +0100
branch
sub_styles
changeset 6845
4680adb641e0
child 6846
6ca9ef2c0907
permissions
-rw-r--r--

Lexer: implemented basic support for sub-styles.

# -*- coding: utf-8 -*-

# Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the lexer mixin class.
"""

from __future__ import unicode_literals

import copy

from PyQt5.QtGui import QColor

from .Lexer import Lexer

import Preferences


class SubstyledLexer(Lexer):
    """
    Class to implement the sub-styled lexer mixin class.
    """
    def __init__(self):
        """
        Constructor
        """
        super(SubstyledLexer, self).__init__()
        
        self.baseStyles = []            # list of style numbers, that support
                                        # sub-styling
        self.defaultSubStyles = {}
        # dictionary with sub-styling data
        # main key: base style number, value : dictionary with
        #   'SubStyleLength': int
        #   'SubStyles': list of dict with
        #       'Description': string containing a short description
        #       'Words': string of whitespace separated words to be styled
        #       'Style': dictionary with styling data (only difference to the
        #                base style is required
        #           'fore': foreground color (int containing RGB values)
        #           'paper': background color (int containing RGB values)
        #           'eolfill': fill to eol (bool)
        #           'font_family': font family (str)
        #           'font_size: point size (int)
        #           'font_bold: bold font (bool)
        #           'font_italic: italic font (bool)
        #           'font_underline: underlined font (bool)
        
        self.subStyles = {}
        self.__subStylesInitialized = False
    
    def loadSubstyles(self):
        """
        Public method to load the sub-styles from the settings file
        """
        settings = Preferences.Prefs.settings
        
        self.loadDefaultSubStyles()
        
        for baseStyle in self.baseStyles:
            key = "Scintilla/{0}/style{1}/SubStyleLength".format(
                self.language(), baseStyle)
            if settings.contains(key):
                subStyleLength = int(settings.value(key), 0)
                self.subStyles[baseStyle] = {}
                self.subStyles[baseStyle]["SubStyleLength"] = subStyleLength
                if subStyleLength:
                    self.subStyles[baseStyle]["SubStyles"] = []
                    for subStyle in range(subStyleLength):
                        baseKey = "Scintilla/{0}/style{1}/substyle{2}/".format(
                            self.language(), baseStyle, subStyle)
                        subStyleData = {}
                        subStyleData["Description"] = settings.value(
                            baseKey + "Description", "")
                        subStyleData["Words"] = settings.value(
                            baseKey + "Words", "")
                        style = {}
                        
                        key = baseKey + "fore"
                        if settings.contains(key):
                            style["fore"] = int(settings.value(key))
                        key = baseKey + "paper"
                        if settings.contains(key):
                            style["paper"] = int(settings.value(key))
                        key = baseKey + "eolfill"
                        if settings.contains(key):
                            style["eolfill"] = Preferences.toBool(
                                settings.value(key))
                        key = baseKey + "font_family"
                        if settings.contains(key):
                            style["font_family"] = settings.value(key)
                        key = baseKey + "font_size"
                        if settings.contains(key):
                            style["font_size"] = int(settings.value(key))
                        key = baseKey + "font_bold"
                        if settings.contains(key):
                            style["font_bold"] = Preferences.toBool(
                                settings.value(key))
                        key = baseKey + "font_italic"
                        if settings.contains(key):
                            style["font_italic"] = Preferences.toBool(
                                settings.value(key))
                        key = baseKey + "font_underline"
                        if settings.contains(key):
                            style["font_underline"] = Preferences.toBool(
                                settings.value(key))
                        
                        subStyleData["Style"] = style
    
    def loadDefaultSubStyles(self):
        """
        Public method to load the default sub-style definitions.
        """
        self.subStyles = copy.deepcopy(self.defaultSubStyles)
    
    def readSubstyles(self, editor):
        """
        Public method to load the sub-styles and configure the editor.
        
        @param editor reference to the editor object
        @type QsciScintilla
        """
        subStyleBasesLength = editor.SendScintilla(
            editor.SCI_GETSUBSTYLEBASES, 0, None)
        if not subStyleBasesLength:
            # lexer does not support sub-styling
            return
        
        self.loadSubstyles()
        
        # free existing sub-styles first
        editor.SendScintilla(editor.SCI_FREESUBSTYLES)
        subStyleBases = b"\00" * (subStyleBasesLength + 1)
        editor.SendScintilla(editor.SCI_GETSUBSTYLEBASES, 0, subStyleBases)
        distanceToSecondary = editor.SendScintilla(
            editor.SCI_DISTANCETOSECONDARYSTYLES)
        
        subStyleBases = [b for b in bytearray(subStyleBases[:-1])]
        if distanceToSecondary:
            subStyleBases.extend(b + distanceToSecondary for b in subStyleBases[:])
        for baseStyleNo in subStyleBases:
            if baseStyleNo in self.subStyles:
                subStylesData = self.subStyles[baseStyleNo]
                subStyleLength = subStylesData["SubStyleLength"]
                subStyleStart = editor.SendScintilla(
                    editor.SCI_ALLOCATESUBSTYLES, baseStyleNo, subStyleLength)
                if subStyleStart < 0:
                    subStyleLength = 0
                for subStyleIndex in range(subStyleLength):
                    subStyle = subStylesData["SubStyles"][subStyleIndex]
                    # set the words
                    editor.SendScintilla(
                        editor.SCI_SETIDENTIFIERS,
                        subStyleStart + subStyleIndex,
                        subStyle["Words"].encode())
                    
                    # set the style
                    styleNo = subStyleStart + subStyleIndex
                    style = subStyle["Style"]
                    if "fore" in style:
                        color = QColor(
                            style["fore"] >> 16 & 0xff,
                            style["fore"] >> 8 & 0xff,
                            style["fore"] & 0xff,
                        )
                    else:
                        color = self.color(baseStyleNo)
                    self.setColor(color, styleNo)
                    if "paper" in style:
                        color = QColor(
                            style["paper"] >> 16 & 0xff,
                            style["paper"] >> 8 & 0xff,
                            style["paper"] & 0xff,
                        )
                    else:
                        color = self.paper(baseStyleNo)
                    self.setPaper(color, styleNo)
                    if "eolfill" in style:
                        eolFill = style["eolFill"]
                    else:
                        eolFill = self.eolFill(baseStyleNo)
                    self.setEolFill(eolFill, styleNo)
                    font = self.font(baseStyleNo)
                    if "font_family" in style:
                        font.setFamily(style["font_family"])
                    if "font_size" in style:
                        font.setPointSize(style["font_size"])
                    if "font_bold" in style:
                        font.setBold(style["font_bold"])
                    if "font_italic" in style:
                        font.setItalic(style["font_italic"])
                    if "font_underline" in style:
                        font.setUnderline(style["font_underline"])
                    self.setFont(font, styleNo)
    
    def writeSubstyles(self):
        """
        Public method to save the sub-styles.
        """
    
    def hasSubStyles(self):
        """
        Public method to indicate the support of sub-styles.
        
        @return flag indicating sub-styling support
        @rtype bool
        """
        return True
    
    def setSubstyleDescription(self, description, style, substyle):
        """
        
        """
    
    def substyleDescription(self, style, substyle):
        """
        
        """
    
    def setSubstyleColor(self, color, style, substyle):
        """
        
        """
    
    def substyleColor(self, style, substyle):
        """
        
        """
    
    def setSubstylePaper(self, color, style, substyle):
        """
        
        """
    
    def substylePaper(self, style, substyle):
        """
        
        """
    
    def setSubstyleEolFill(self, eolFill, style, substyle):
        """
        
        """
    
    def substyleEolFill(self, style, substyle):
        """
        
        """
    
    def setSubstyleFont(self, font, style, substyle):
        """
        
        """
    
    def substyleFont(self, style, substyle):
        """
        
        """
    
    def substyleDefaultDescription(self, style, substyle):
        """
        
        """
    
    def substyleDefaultColor(self, style, substyle):
        """
        
        """
    
    def substyleDefaultPaper(self, style, substyle):
        """
        
        """
    
    def substyleDefaultEolFill(self, style, substyle):
        """
        
        """
    
    def substyleDefaultFont(self, style, substyle):
        """
        
        """

eric ide

mercurial