/bh_plugin.py

https://github.com/facelessuser/BracketHighlighter · Python · 198 lines · 152 code · 24 blank · 22 comment · 10 complexity · 624791e0c97215ea18c1e82b34fee52b MD5 · raw file

  1. """
  2. BracketHighlighter.
  3. Copyright (c) 2013 - 2016 Isaac Muse <isaacmuse@gmail.com>
  4. License: MIT
  5. """
  6. import sublime
  7. import sublime_plugin
  8. from os.path import normpath, join
  9. import imp
  10. from collections import namedtuple
  11. import sys
  12. import traceback
  13. import re
  14. from .bh_logging import log
  15. class Payload(object):
  16. """Plugin payload."""
  17. status = False
  18. plugin = None
  19. args = None
  20. @classmethod
  21. def clear(cls):
  22. """Clear payload."""
  23. cls.status = False
  24. cls.plugin = None
  25. cls.args = None
  26. class BracketRegion (namedtuple('BracketRegion', ['begin', 'end'], verbose=False)):
  27. """Bracket regions for plugins."""
  28. def move(self, begin, end):
  29. """Move bracket region to different points."""
  30. return self._replace(begin=begin, end=end)
  31. def size(self):
  32. """Get the size of the region."""
  33. return abs(self.begin - self.end)
  34. def toregion(self):
  35. """Convert to sublime region."""
  36. return sublime.Region(self.begin, self.end)
  37. def is_bracket_region(obj):
  38. """Check if object is a `BracketRegion`."""
  39. return isinstance(obj, BracketRegion)
  40. def sublime_format_path(pth):
  41. """Format path for Sublime internally."""
  42. m = re.match(r"^([A-Za-z]{1}):(?:/|\\)(.*)", pth)
  43. if sublime.platform() == "windows" and m is not None:
  44. pth = m.group(1) + "/" + m.group(2)
  45. return pth.replace("\\", "/")
  46. def load_modules(obj, loaded):
  47. """Load bracket plugin modules."""
  48. plib = obj.get("plugin_library")
  49. if plib is None:
  50. return
  51. try:
  52. module = _import_module(plib, loaded)
  53. obj["compare"] = getattr(module, "compare", None)
  54. obj["post_match"] = getattr(module, "post_match", None)
  55. obj["validate"] = getattr(module, "validate", None)
  56. obj["highlighting"] = getattr(module, "highlighting", None)
  57. loaded.add(plib)
  58. except Exception:
  59. log("Could not load module %s\n%s" % (plib, str(traceback.format_exc())))
  60. raise
  61. def _import_module(module_name, loaded=None):
  62. """
  63. Import the module.
  64. Import the module and track which modules have been loaded
  65. so we don't load already loaded modules.
  66. """
  67. # Pull in built-in and custom plugin directory
  68. if module_name.startswith("bh_modules."):
  69. path_name = join("Packages", "BracketHighlighter", normpath(module_name.replace('.', '/')))
  70. else:
  71. path_name = join("Packages", normpath(module_name.replace('.', '/')))
  72. path_name += ".py"
  73. if loaded is not None and module_name in loaded:
  74. module = sys.modules[module_name]
  75. else:
  76. module = imp.new_module(module_name)
  77. sys.modules[module_name] = module
  78. exec(
  79. compile(
  80. sublime.load_resource(sublime_format_path(path_name)),
  81. module_name,
  82. 'exec'
  83. ),
  84. sys.modules[module_name].__dict__
  85. )
  86. return module
  87. def import_module(module, attribute=None):
  88. """Import module or module attribute."""
  89. mod = _import_module(module)
  90. return getattr(mod, attribute) if attribute is not None else mod
  91. class BracketPluginRunCommand(sublime_plugin.TextCommand):
  92. """Sublime run command to run BH plugins."""
  93. def run(self, edit):
  94. """Run the plugin."""
  95. try:
  96. Payload.args["edit"] = edit
  97. Payload.plugin.run(**Payload.args)
  98. Payload.status = True
  99. except Exception:
  100. print("BracketHighlighter: Plugin Run Error:\n%s" % str(traceback.format_exc()))
  101. class BracketPlugin(object):
  102. """Class for preparing and running plugins."""
  103. def __init__(self, plugin, loaded):
  104. """Load plugin module."""
  105. self.enabled = False
  106. self.args = plugin['args'] if ("args" in plugin) else {}
  107. self.plugin = None
  108. if 'command' in plugin:
  109. plib = plugin['command']
  110. try:
  111. module = _import_module(plib, loaded)
  112. self.plugin = getattr(module, 'plugin')()
  113. loaded.add(plib)
  114. self.enabled = True
  115. except Exception:
  116. print('BracketHighlighter: Load Plugin Error: %s\n%s' % (plugin['command'], traceback.format_exc()))
  117. def is_enabled(self):
  118. """Check if plugin is enabled."""
  119. return self.enabled
  120. def run_command(self, view, name, left, right, selection):
  121. """Load arguments into plugin and run."""
  122. nobracket = False
  123. refresh_match = False
  124. Payload.status = False
  125. Payload.plugin = self.plugin()
  126. setattr(Payload.plugin, "left", left)
  127. setattr(Payload.plugin, "right", right)
  128. setattr(Payload.plugin, "view", view)
  129. setattr(Payload.plugin, "selection", selection)
  130. setattr(Payload.plugin, "nobracket", False)
  131. setattr(Payload.plugin, "refresh_match", False)
  132. self.args["edit"] = None
  133. self.args["name"] = name
  134. Payload.args = self.args
  135. # Call a `TextCommand` to run the plugin so it can feed in the `Edit` object
  136. view.run_command("bracket_plugin_run")
  137. if Payload.status:
  138. left = Payload.plugin.left
  139. right = Payload.plugin.right
  140. selection = Payload.plugin.selection
  141. nobracket = Payload.plugin.nobracket
  142. refresh_match = Payload.plugin.refresh_match
  143. Payload.clear()
  144. return left, right, selection, nobracket, refresh_match
  145. class BracketPluginCommand(object):
  146. """Bracket Plugin base class."""
  147. def run(self, bracket, content, selection):
  148. """Run the plugin class."""
  149. pass