wowtoc.py 4.0 KB

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