Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
formatter.py696 linesDownload Raw Back to scintilla
1# Does Python source formatting for Scintilla controls.2import array3import string4 5import win32api6import win32con7import win32ui8 9from . import scintillacon10 11WM_KICKIDLE = 0x036A12 13# Used to indicate that style should use default color14from win32con import CLR_INVALID15 16debugging = 017if debugging:18    # Output must go to another process else the result of19    # the printing itself will trigger again trigger a trace.20 21    import win32trace22    import win32traceutil23 24    def trace(*args):25        win32trace.write(" ".join(map(str, args)) + "\n")26 27else:28    trace = lambda *args: None29 30 31class Style:32    """Represents a single format"""33 34    def __init__(self, name, format, background=CLR_INVALID):35        self.name = name  # Name the format representes eg, "String", "Class"36        # Default background for each style is only used when there are no37        # saved settings (generally on first startup)38        self.background = self.default_background = background39        if type(format) == type(""):40            self.aliased = format41            self.format = None42        else:43            self.format = format44            self.aliased = None45        self.stylenum = None  # Not yet registered.46 47    def IsBasedOnDefault(self):48        return len(self.format) == 549 50    # If the currently extended font defintion matches the51    # default format, restore the format to the "simple" format.52    def NormalizeAgainstDefault(self, defaultFormat):53        if self.IsBasedOnDefault():54            return 0  # No more to do, and not changed.55        bIsDefault = (56            self.format[7] == defaultFormat[7] and self.format[2] == defaultFormat[2]57        )58        if bIsDefault:59            self.ForceAgainstDefault()60        return bIsDefault61 62    def ForceAgainstDefault(self):63        self.format = self.format[:5]64 65    def GetCompleteFormat(self, defaultFormat):66        # Get the complete style after applying any relevant defaults.67        if len(self.format) == 5:  # It is a default one68            fmt = self.format + defaultFormat[5:]69        else:70            fmt = self.format71        flags = (72            win32con.CFM_BOLD73            | win32con.CFM_CHARSET74            | win32con.CFM_COLOR75            | win32con.CFM_FACE76            | win32con.CFM_ITALIC77            | win32con.CFM_SIZE78        )79        return (flags,) + fmt[1:]80 81 82# The Formatter interface83# used primarily when the actual formatting is done by Scintilla!84class FormatterBase:85    def __init__(self, scintilla):86        self.scintilla = scintilla87        self.baseFormatFixed = (-402653169, 0, 200, 0, 0, 0, 49, "Courier New")88        self.baseFormatProp = (-402653169, 0, 200, 0, 0, 0, 49, "Arial")89        self.bUseFixed = 190        self.styles = {}  # Indexed by name91        self.styles_by_id = {}  # Indexed by allocated ID.92        self.SetStyles()93 94    def HookFormatter(self, parent=None):95        raise NotImplementedError()96 97    # Used by the IDLE extensions to quickly determine if a character is a string.98    def GetStringStyle(self, pos):99        try:100            style = self.styles_by_id[self.scintilla.SCIGetStyleAt(pos)]101        except KeyError:102            # A style we dont know about - probably not even a .py file - can't be a string103            return None104        if style.name in self.string_style_names:105            return style106        return None107 108    def RegisterStyle(self, style, stylenum):109        assert stylenum is not None, "We must have a style number"110        assert style.stylenum is None, "Style has already been registered"111        assert stylenum not in self.styles, "We are reusing a style number!"112        style.stylenum = stylenum113        self.styles[style.name] = style114        self.styles_by_id[stylenum] = style115 116    def SetStyles(self):117        raise NotImplementedError()118 119    def GetSampleText(self):120        return "Sample Text for the Format Dialog"121 122    def GetDefaultFormat(self):123        if self.bUseFixed:124            return self.baseFormatFixed125        return self.baseFormatProp126 127    # Update the control with the new style format.128    def _ReformatStyle(self, style):129        ## Selection (background only for now)130        ## Passing False for WPARAM to SCI_SETSELBACK is documented as resetting to scintilla default,131        ## but does not work - selection background is not visible at all.132        ## Default value in SPECIAL_STYLES taken from scintilla source.133        if style.name == STYLE_SELECTION:134            clr = style.background135            self.scintilla.SendScintilla(scintillacon.SCI_SETSELBACK, True, clr)136 137            ## Can't change font for selection, but could set color138            ## However, the font color dropbox has no option for default, and thus would139            ## always override syntax coloring140            ## clr = style.format[4]141            ## self.scintilla.SendScintilla(scintillacon.SCI_SETSELFORE, clr != CLR_INVALID, clr)142            return143 144        assert style.stylenum is not None, "Unregistered style."145        # print "Reformat style", style.name, style.stylenum146        scintilla = self.scintilla147        stylenum = style.stylenum148        # Now we have the style number, indirect for the actual style.149        if style.aliased is not None:150            style = self.styles[style.aliased]151        f = style.format152        if style.IsBasedOnDefault():153            baseFormat = self.GetDefaultFormat()154        else:155            baseFormat = f156        scintilla.SCIStyleSetFore(stylenum, f[4])157        scintilla.SCIStyleSetFont(stylenum, baseFormat[7], baseFormat[5])158        if f[1] & 1:159            scintilla.SCIStyleSetBold(stylenum, 1)160        else:161            scintilla.SCIStyleSetBold(stylenum, 0)162        if f[1] & 2:163            scintilla.SCIStyleSetItalic(stylenum, 1)164        else:165            scintilla.SCIStyleSetItalic(stylenum, 0)166        scintilla.SCIStyleSetSize(stylenum, int(baseFormat[2] / 20))167        scintilla.SCIStyleSetEOLFilled(stylenum, 1)  # Only needed for unclosed strings.168 169        ## Default style background to whitespace background if set,170        ##	otherwise use system window color171        bg = style.background172        if bg == CLR_INVALID:173            bg = self.styles[STYLE_DEFAULT].background174        if bg == CLR_INVALID:175            bg = win32api.GetSysColor(win32con.COLOR_WINDOW)176        scintilla.SCIStyleSetBack(stylenum, bg)177 178    def GetStyleByNum(self, stylenum):179        return self.styles_by_id[stylenum]180 181    def ApplyFormattingStyles(self, bReload=1):182        if bReload:183            self.LoadPreferences()184        baseFormat = self.GetDefaultFormat()185        defaultStyle = Style("default", baseFormat)186        defaultStyle.stylenum = scintillacon.STYLE_DEFAULT187        self._ReformatStyle(defaultStyle)188        for style in list(self.styles.values()):189            if style.aliased is None:190                style.NormalizeAgainstDefault(baseFormat)191            self._ReformatStyle(style)192        self.scintilla.InvalidateRect()193 194    # Some functions for loading and saving preferences.  By default195    # an INI file (well, MFC maps this to the registry) is used.196    def LoadPreferences(self):197        self.baseFormatFixed = eval(198            self.LoadPreference("Base Format Fixed", str(self.baseFormatFixed))199        )200        self.baseFormatProp = eval(201            self.LoadPreference("Base Format Proportional", str(self.baseFormatProp))202        )203        self.bUseFixed = int(self.LoadPreference("Use Fixed", 1))204 205        for style in list(self.styles.values()):206            new = self.LoadPreference(style.name, str(style.format))207            try:208                style.format = eval(new)209            except:210                print("Error loading style data for", style.name)211            # Use "vanilla" background hardcoded in PYTHON_STYLES if no settings in registry212            style.background = int(213                self.LoadPreference(214                    style.name + " background", style.default_background215                )216            )217 218    def LoadPreference(self, name, default):219        return win32ui.GetProfileVal("Format", name, default)220 221    def SavePreferences(self):222        self.SavePreference("Base Format Fixed", str(self.baseFormatFixed))223        self.SavePreference("Base Format Proportional", str(self.baseFormatProp))224        self.SavePreference("Use Fixed", self.bUseFixed)225        for style in list(self.styles.values()):226            if style.aliased is None:227                self.SavePreference(style.name, str(style.format))228                bg_name = style.name + " background"229                self.SavePreference(bg_name, style.background)230 231    def SavePreference(self, name, value):232        win32ui.WriteProfileVal("Format", name, value)233 234 235# An abstract formatter236# For all formatters we actually implement here.237# (as opposed to those formatters built in to Scintilla)238class Formatter(FormatterBase):239    def __init__(self, scintilla):240        self.bCompleteWhileIdle = 0241        self.bHaveIdleHandler = 0  # Dont currently have an idle handle242        self.nextstylenum = 0243        FormatterBase.__init__(self, scintilla)244 245    def HookFormatter(self, parent=None):246        if parent is None:247            parent = self.scintilla.GetParent()  # was GetParentFrame()!?248        parent.HookNotify(self.OnStyleNeeded, scintillacon.SCN_STYLENEEDED)249 250    def OnStyleNeeded(self, std, extra):251        notify = self.scintilla.SCIUnpackNotifyMessage(extra)252        endStyledChar = self.scintilla.SendScintilla(scintillacon.SCI_GETENDSTYLED)253        lineEndStyled = self.scintilla.LineFromChar(endStyledChar)254        endStyled = self.scintilla.LineIndex(lineEndStyled)255        # print "enPosPaint %d endStyledChar %d lineEndStyled %d endStyled %d" % (endPosPaint, endStyledChar, lineEndStyled, endStyled)256        self.Colorize(endStyled, notify.position)257 258    def ColorSeg(self, start, end, styleName):259        end = end + 1260        # 		assert end-start>=0, "Can't have negative styling"261        stylenum = self.styles[styleName].stylenum262        while start < end:263            self.style_buffer[start] = stylenum264            start = start + 1265        # self.scintilla.SCISetStyling(end - start + 1, stylenum)266 267    def RegisterStyle(self, style, stylenum=None):268        if stylenum is None:269            stylenum = self.nextstylenum270            self.nextstylenum = self.nextstylenum + 1271        FormatterBase.RegisterStyle(self, style, stylenum)272 273    def ColorizeString(self, str, charStart, styleStart):274        raise RuntimeError("You must override this method")275 276    def Colorize(self, start=0, end=-1):277        scintilla = self.scintilla278        # scintilla's formatting is all done in terms of utf, so279        # we work with utf8 bytes instead of unicode.  This magically280        # works as any extended chars found in the utf8 don't change281        # the semantics.282        stringVal = scintilla.GetTextRange(start, end, decode=False)283        if start > 0:284            stylenum = scintilla.SCIGetStyleAt(start - 1)285            styleStart = self.GetStyleByNum(stylenum).name286        else:287            styleStart = None288        # 		trace("Coloring", start, end, end-start, len(stringVal), styleStart, self.scintilla.SCIGetCharAt(start))289        scintilla.SCIStartStyling(start, 31)290        self.style_buffer = array.array("b", (0,) * len(stringVal))291        self.ColorizeString(stringVal, styleStart)292        scintilla.SCISetStylingEx(self.style_buffer)293        self.style_buffer = None294        # 		trace("After styling, end styled is", self.scintilla.SCIGetEndStyled())295        if (296            self.bCompleteWhileIdle297            and not self.bHaveIdleHandler298            and end != -1299            and end < scintilla.GetTextLength()300        ):301            self.bHaveIdleHandler = 1302            win32ui.GetApp().AddIdleHandler(self.DoMoreColoring)303            # Kicking idle makes the app seem slower when initially repainting!304 305    # 			win32ui.GetMainFrame().PostMessage(WM_KICKIDLE, 0, 0)306 307    def DoMoreColoring(self, handler, count):308        try:309            scintilla = self.scintilla310            endStyled = scintilla.SCIGetEndStyled()311            lineStartStyled = scintilla.LineFromChar(endStyled)312            start = scintilla.LineIndex(lineStartStyled)313            end = scintilla.LineIndex(lineStartStyled + 1)314            textlen = scintilla.GetTextLength()315            if end < 0:316                end = textlen317 318            finished = end >= textlen319            self.Colorize(start, end)320        except (win32ui.error, AttributeError):321            # Window may have closed before we finished - no big deal!322            finished = 1323 324        if finished:325            self.bHaveIdleHandler = 0326            win32ui.GetApp().DeleteIdleHandler(handler)327        return not finished328 329 330# A Formatter that knows how to format Python source331from keyword import iskeyword, kwlist332 333wordstarts = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"334wordchars = "._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"335operators = "%^&*()-+=|{}[]:;<>,/?!.~"336 337STYLE_DEFAULT = "Whitespace"338STYLE_COMMENT = "Comment"339STYLE_COMMENT_BLOCK = "Comment Blocks"340STYLE_NUMBER = "Number"341STYLE_STRING = "String"342STYLE_SQSTRING = "SQ String"343STYLE_TQSSTRING = "TQS String"344STYLE_TQDSTRING = "TQD String"345STYLE_KEYWORD = "Keyword"346STYLE_CLASS = "Class"347STYLE_METHOD = "Method"348STYLE_OPERATOR = "Operator"349STYLE_IDENTIFIER = "Identifier"350STYLE_BRACE = "Brace/Paren - matching"351STYLE_BRACEBAD = "Brace/Paren - unmatched"352STYLE_STRINGEOL = "String with no terminator"353STYLE_LINENUMBER = "Line numbers"354STYLE_INDENTGUIDE = "Indent guide"355STYLE_SELECTION = "Selection"356 357STRING_STYLES = [358    STYLE_STRING,359    STYLE_SQSTRING,360    STYLE_TQSSTRING,361    STYLE_TQDSTRING,362    STYLE_STRINGEOL,363]364 365# These styles can have any ID - they are not special to scintilla itself.366# However, if we use the built-in lexer, then we must use its style numbers367# so in that case, they _are_ special.368# (name, format, background, scintilla id)369PYTHON_STYLES = [370    (STYLE_DEFAULT, (0, 0, 200, 0, 0x808080), CLR_INVALID, scintillacon.SCE_P_DEFAULT),371    (372        STYLE_COMMENT,373        (0, 2, 200, 0, 0x008000),374        CLR_INVALID,375        scintillacon.SCE_P_COMMENTLINE,376    ),377    (378        STYLE_COMMENT_BLOCK,379        (0, 2, 200, 0, 0x808080),380        CLR_INVALID,381        scintillacon.SCE_P_COMMENTBLOCK,382    ),383    (STYLE_NUMBER, (0, 0, 200, 0, 0x808000), CLR_INVALID, scintillacon.SCE_P_NUMBER),384    (STYLE_STRING, (0, 0, 200, 0, 0x008080), CLR_INVALID, scintillacon.SCE_P_STRING),385    (STYLE_SQSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_CHARACTER),386    (STYLE_TQSSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_TRIPLE),387    (STYLE_TQDSTRING, STYLE_STRING, CLR_INVALID, scintillacon.SCE_P_TRIPLEDOUBLE),388    (STYLE_STRINGEOL, (0, 0, 200, 0, 0x000000), 0x008080, scintillacon.SCE_P_STRINGEOL),389    (STYLE_KEYWORD, (0, 1, 200, 0, 0x800000), CLR_INVALID, scintillacon.SCE_P_WORD),390    (STYLE_CLASS, (0, 1, 200, 0, 0xFF0000), CLR_INVALID, scintillacon.SCE_P_CLASSNAME),391    (STYLE_METHOD, (0, 1, 200, 0, 0x808000), CLR_INVALID, scintillacon.SCE_P_DEFNAME),392    (393        STYLE_OPERATOR,394        (0, 0, 200, 0, 0x000000),395        CLR_INVALID,396        scintillacon.SCE_P_OPERATOR,397    ),398    (399        STYLE_IDENTIFIER,400        (0, 0, 200, 0, 0x000000),401        CLR_INVALID,402        scintillacon.SCE_P_IDENTIFIER,403    ),404]405 406# These styles _always_ have this specific style number, regardless of407# internal or external formatter.408SPECIAL_STYLES = [409    (STYLE_BRACE, (0, 0, 200, 0, 0x000000), 0xFFFF80, scintillacon.STYLE_BRACELIGHT),410    (STYLE_BRACEBAD, (0, 0, 200, 0, 0x000000), 0x8EA5F2, scintillacon.STYLE_BRACEBAD),411    (412        STYLE_LINENUMBER,413        (0, 0, 200, 0, 0x000000),414        win32api.GetSysColor(win32con.COLOR_3DFACE),415        scintillacon.STYLE_LINENUMBER,416    ),417    (418        STYLE_INDENTGUIDE,419        (0, 0, 200, 0, 0x000000),420        CLR_INVALID,421        scintillacon.STYLE_INDENTGUIDE,422    ),423    ## Not actually a style; requires special handling to send appropriate messages to scintilla424    (425        STYLE_SELECTION,426        (0, 0, 200, 0, CLR_INVALID),427        win32api.RGB(0xC0, 0xC0, 0xC0),428        999999,429    ),430]431 432PythonSampleCode = """\433# Some Python434class Sample(Super):435  def Fn(self):436\tself.v = 1024437dest = 'dest.html'438x = func(a + 1)|)439s = "I forget...440## A large441## comment block"""442 443 444class PythonSourceFormatter(Formatter):445    string_style_names = STRING_STYLES446 447    def GetSampleText(self):448        return PythonSampleCode449 450    def LoadStyles(self):451        pass452 453    def SetStyles(self):454        for name, format, bg, ignore in PYTHON_STYLES:455            self.RegisterStyle(Style(name, format, bg))456        for name, format, bg, sc_id in SPECIAL_STYLES:457            self.RegisterStyle(Style(name, format, bg), sc_id)458 459    def ClassifyWord(self, cdoc, start, end, prevWord):460        word = cdoc[start : end + 1].decode("latin-1")461        attr = STYLE_IDENTIFIER462        if prevWord == "class":463            attr = STYLE_CLASS464        elif prevWord == "def":465            attr = STYLE_METHOD466        elif word[0] in string.digits:467            attr = STYLE_NUMBER468        elif iskeyword(word):469            attr = STYLE_KEYWORD470        self.ColorSeg(start, end, attr)471        return word472 473    def ColorizeString(self, str, styleStart):474        if styleStart is None:475            styleStart = STYLE_DEFAULT476        return self.ColorizePythonCode(str, 0, styleStart)477 478    def ColorizePythonCode(self, cdoc, charStart, styleStart):479        # Straight translation of C++, should do better480        lengthDoc = len(cdoc)481        if lengthDoc <= charStart:482            return483        prevWord = ""484        state = styleStart485        chPrev = chPrev2 = chPrev3 = " "486        chNext2 = chNext = cdoc[charStart : charStart + 1].decode("latin-1")487        startSeg = i = charStart488        while i < lengthDoc:489            ch = chNext490            chNext = " "491            if i + 1 < lengthDoc:492                chNext = cdoc[i + 1 : i + 2].decode("latin-1")493            chNext2 = " "494            if i + 2 < lengthDoc:495                chNext2 = cdoc[i + 2 : i + 3].decode("latin-1")496            if state == STYLE_DEFAULT:497                if ch in wordstarts:498                    self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT)499                    state = STYLE_KEYWORD500                    startSeg = i501                elif ch == "#":502                    self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT)503                    if chNext == "#":504                        state = STYLE_COMMENT_BLOCK505                    else:506                        state = STYLE_COMMENT507                    startSeg = i508                elif ch == '"':509                    self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT)510                    startSeg = i511                    state = STYLE_COMMENT512                    if chNext == '"' and chNext2 == '"':513                        i = i + 2514                        state = STYLE_TQDSTRING515                        ch = " "516                        chPrev = " "517                        chNext = " "518                        if i + 1 < lengthDoc:519                            chNext = cdoc[i + 1]520                    else:521                        state = STYLE_STRING522                elif ch == "'":523                    self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT)524                    startSeg = i525                    state = STYLE_COMMENT526                    if chNext == "'" and chNext2 == "'":527                        i = i + 2528                        state = STYLE_TQSSTRING529                        ch = " "530                        chPrev = " "531                        chNext = " "532                        if i + 1 < lengthDoc:533                            chNext = cdoc[i + 1]534                    else:535                        state = STYLE_SQSTRING536                elif ch in operators:537                    self.ColorSeg(startSeg, i - 1, STYLE_DEFAULT)538                    self.ColorSeg(i, i, STYLE_OPERATOR)539                    startSeg = i + 1540            elif state == STYLE_KEYWORD:541                if ch not in wordchars:542                    prevWord = self.ClassifyWord(cdoc, startSeg, i - 1, prevWord)543                    state = STYLE_DEFAULT544                    startSeg = i545                    if ch == "#":546                        if chNext == "#":547                            state = STYLE_COMMENT_BLOCK548                        else:549                            state = STYLE_COMMENT550                    elif ch == '"':551                        if chNext == '"' and chNext2 == '"':552                            i = i + 2553                            state = STYLE_TQDSTRING554                            ch = " "555                            chPrev = " "556                            chNext = " "557                            if i + 1 < lengthDoc:558                                chNext = cdoc[i + 1]559                        else:560                            state = STYLE_STRING561                    elif ch == "'":562                        if chNext == "'" and chNext2 == "'":563                            i = i + 2564                            state = STYLE_TQSSTRING565                            ch = " "566                            chPrev = " "567                            chNext = " "568                            if i + 1 < lengthDoc:569                                chNext = cdoc[i + 1]570                        else:571                            state = STYLE_SQSTRING572                    elif ch in operators:573                        self.ColorSeg(startSeg, i, STYLE_OPERATOR)574                        startSeg = i + 1575            elif state == STYLE_COMMENT or state == STYLE_COMMENT_BLOCK:576                if ch == "\r" or ch == "\n":577                    self.ColorSeg(startSeg, i - 1, state)578                    state = STYLE_DEFAULT579                    startSeg = i580            elif state == STYLE_STRING:581                if ch == "\\":582                    if chNext == '"' or chNext == "'" or chNext == "\\":583                        i = i + 1584                        ch = chNext585                        chNext = " "586                        if i + 1 < lengthDoc:587                            chNext = cdoc[i + 1]588                elif ch == '"':589                    self.ColorSeg(startSeg, i, STYLE_STRING)590                    state = STYLE_DEFAULT591                    startSeg = i + 1592            elif state == STYLE_SQSTRING:593                if ch == "\\":594                    if chNext == '"' or chNext == "'" or chNext == "\\":595                        i = i + 1596                        ch = chNext597                        chNext = " "598                        if i + 1 < lengthDoc:599                            chNext = cdoc[i + 1]600                elif ch == "'":601                    self.ColorSeg(startSeg, i, STYLE_SQSTRING)602                    state = STYLE_DEFAULT603                    startSeg = i + 1604            elif state == STYLE_TQSSTRING:605                if ch == "'" and chPrev == "'" and chPrev2 == "'" and chPrev3 != "\\":606                    self.ColorSeg(startSeg, i, STYLE_TQSSTRING)607                    state = STYLE_DEFAULT608                    startSeg = i + 1609            elif (610                state == STYLE_TQDSTRING611                and ch == '"'612                and chPrev == '"'613                and chPrev2 == '"'614                and chPrev3 != "\\"615            ):616                self.ColorSeg(startSeg, i, STYLE_TQDSTRING)617                state = STYLE_DEFAULT618                startSeg = i + 1619            chPrev3 = chPrev2620            chPrev2 = chPrev621            chPrev = ch622            i = i + 1623        if startSeg < lengthDoc:624            if state == STYLE_KEYWORD:625                self.ClassifyWord(cdoc, startSeg, lengthDoc - 1, prevWord)626            else:627                self.ColorSeg(startSeg, lengthDoc - 1, state)628 629 630# These taken from the SciTE properties file.631source_formatter_extensions = [632    (".py .pys .pyw".split(), scintillacon.SCLEX_PYTHON),633    (".html .htm .asp .shtml".split(), scintillacon.SCLEX_HTML),634    (635        "c .cc .cpp .cxx .h .hh .hpp .hxx .idl .odl .php3 .phtml .inc .js".split(),636        scintillacon.SCLEX_CPP,637    ),638    (".vbs .frm .ctl .cls".split(), scintillacon.SCLEX_VB),639    (".pl .pm .cgi .pod".split(), scintillacon.SCLEX_PERL),640    (".sql .spec .body .sps .spb .sf .sp".split(), scintillacon.SCLEX_SQL),641    (".tex .sty".split(), scintillacon.SCLEX_LATEX),642    (".xml .xul".split(), scintillacon.SCLEX_XML),643    (".err".split(), scintillacon.SCLEX_ERRORLIST),644    (".mak".split(), scintillacon.SCLEX_MAKEFILE),645    (".bat .cmd".split(), scintillacon.SCLEX_BATCH),646]647 648 649class BuiltinSourceFormatter(FormatterBase):650    # A class that represents a formatter built-in to Scintilla651    def __init__(self, scintilla, ext):652        self.ext = ext653        FormatterBase.__init__(self, scintilla)654 655    def Colorize(self, start=0, end=-1):656        self.scintilla.SendScintilla(scintillacon.SCI_COLOURISE, start, end)657 658    def RegisterStyle(self, style, stylenum=None):659        assert style.stylenum is None, "Style has already been registered"660        if stylenum is None:661            stylenum = self.nextstylenum662            self.nextstylenum = self.nextstylenum + 1663        assert self.styles.get(stylenum) is None, "We are reusing a style number!"664        style.stylenum = stylenum665        self.styles[style.name] = style666        self.styles_by_id[stylenum] = style667 668    def HookFormatter(self, parent=None):669        sc = self.scintilla670        for exts, formatter in source_formatter_extensions:671            if self.ext in exts:672                formatter_use = formatter673                break674        else:675            formatter_use = scintillacon.SCLEX_PYTHON676        sc.SendScintilla(scintillacon.SCI_SETLEXER, formatter_use)677        keywords = " ".join(kwlist)678        sc.SCISetKeywords(keywords)679 680 681class BuiltinPythonSourceFormatter(BuiltinSourceFormatter):682    sci_lexer_name = scintillacon.SCLEX_PYTHON683    string_style_names = STRING_STYLES684 685    def __init__(self, sc, ext=".py"):686        BuiltinSourceFormatter.__init__(self, sc, ext)687 688    def SetStyles(self):689        for name, format, bg, sc_id in PYTHON_STYLES:690            self.RegisterStyle(Style(name, format, bg), sc_id)691        for name, format, bg, sc_id in SPECIAL_STYLES:692            self.RegisterStyle(Style(name, format, bg), sc_id)693 694    def GetSampleText(self):695        return PythonSampleCode696 
codekingpro/portable-devtools · Team Ai