1""" 
    2    pygments.lexers.wowtoc 
    3    ~~~~~~~~~~~~~~~~~~~~~~ 
    4 
    5    Lexer for World of Warcraft TOC files 
    6 
    7    TOC files describe game addons. 
    8 
    9    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. 
    10    :license: BSD, see LICENSE for details. 
    11""" 
    12 
    13import re 
    14 
    15from pygments.lexer import RegexLexer, bygroups 
    16from pygments.token import Comment, Name, Text, Punctuation, String, Keyword 
    17 
    18__all__ = ["WoWTocLexer"] 
    19 
    20def _create_tag_line_pattern(inner_pattern, ignore_case=False): 
    21    return ((r"(?i)" if ignore_case else r"") 
    22        + r"^(##)( *)"  # groups 1, 2 
    23        + inner_pattern  # group 3 
    24        + r"( *)(:)( *)(.*?)( *)$")  # groups 4, 5, 6, 7, 8 
    25 
    26 
    27def _create_tag_line_token(inner_pattern, inner_token, ignore_case=False): 
    28    # this function template-izes the tag line for a specific type of tag, which will 
    29    # have a different pattern and different token. otherwise, everything about a tag 
    30    # line is the same 
    31    return ( 
    32        _create_tag_line_pattern(inner_pattern, ignore_case=ignore_case), 
    33        bygroups( 
    34            Keyword.Declaration, 
    35            Text.Whitespace, 
    36            inner_token, 
    37            Text.Whitespace, 
    38            Punctuation, 
    39            Text.Whitespace, 
    40            String, 
    41            Text.Whitespace, 
    42        ), 
    43    ) 
    44 
    45 
    46class WoWTocLexer(RegexLexer): 
    47    """ 
    48    Lexer for World of Warcraft TOC files. 
    49    """ 
    50 
    51    name = "World of Warcraft TOC" 
    52    aliases = ["wowtoc"] 
    53    filenames = ["*.toc"] 
    54    url = 'https://wowpedia.fandom.com/wiki/TOC_format' 
    55    version_added = '2.14' 
    56 
    57    tokens = { 
    58        "root": [ 
    59            # official localized tags, Notes and Title 
    60            # (normal part is insensitive, locale part is sensitive) 
    61            _create_tag_line_token( 
    62                r"((?:[nN][oO][tT][eE][sS]|[tT][iI][tT][lL][eE])-(?:ptBR|zhCN|" 
    63                r"enCN|frFR|deDE|itIT|esMX|ptPT|koKR|ruRU|esES|zhTW|enTW|enGB|enUS))", 
    64                Name.Builtin, 
    65            ), 
    66            # other official tags 
    67            _create_tag_line_token( 
    68                r"(Interface|Title|Notes|RequiredDeps|Dep[^: ]*|OptionalDeps|" 
    69                r"LoadOnDemand|LoadWith|LoadManagers|SavedVariablesPerCharacter|" 
    70                r"SavedVariables|DefaultState|Secure|Author|Version)", 
    71                Name.Builtin, 
    72                ignore_case=True, 
    73            ), 
    74            # user-defined tags 
    75            _create_tag_line_token( 
    76                r"(X-[^: ]*)", 
    77                Name.Variable, 
    78                ignore_case=True, 
    79            ), 
    80            # non-conforming tags, but still valid 
    81            _create_tag_line_token( 
    82                r"([^: ]*)", 
    83                Name.Other, 
    84            ), 
    85 
    86            # Comments 
    87            (r"^#.*$", Comment), 
    88 
    89            # Addon Files 
    90            (r"^.+$", Name), 
    91        ] 
    92    } 
    93 
    94    def analyse_text(text): 
    95        # at time of writing, this file suffix conflict's with one of Tex's in 
    96        # markup.py. Tex's anaylse_text() appears to be definitive (binary) and does not 
    97        # share any likeness to WoW TOCs, which means we wont have to compete with it by 
    98        # abitrary increments in score. 
    99 
    100        result = 0 
    101 
    102        # while not required, an almost certain marker of WoW TOC's is the interface tag 
    103        # if this tag is omitted, players will need to opt-in to loading the addon with 
    104        # an options change ("Load out of date addons"). the value is also standardized: 
    105        # `<major><minor><patch>`, with minor and patch being two-digit zero-padded. 
    106        interface_pattern = _create_tag_line_pattern(r"(Interface)", ignore_case=True) 
    107        match = re.search(interface_pattern, text) 
    108        if match and re.match(r"(\d+)(\d{2})(\d{2})", match.group(7)): 
    109            result += 0.8 
    110 
    111        casefolded = text.casefold() 
    112        # Lua file listing is good marker too, but probably conflicts with many other 
    113        # lexers 
    114        if ".lua" in casefolded: 
    115            result += 0.1 
    116        # ditto for XML files, but they're less used in WoW TOCs 
    117        if ".xml" in casefolded: 
    118            result += 0.05 
    119 
    120        return result