263 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import sublime
 | |
| import sublime_plugin
 | |
| 
 | |
| PACKAGE_SETTINGS = "ExportHtml.sublime-settings"
 | |
| 
 | |
| 
 | |
| def get_highlight_style():
 | |
|     style_flag = 0
 | |
|     settings = sublime.load_settings(PACKAGE_SETTINGS)
 | |
|     scope = settings.get("annotation_highlight_scope", "comment")
 | |
|     style = settings.get("annotation_highlight_style", "outline")
 | |
|     if style == "outline":
 | |
|         style_flag |= sublime.DRAW_OUTLINED
 | |
|     return scope, style_flag
 | |
| 
 | |
| 
 | |
| def clean_invalid_regions(view, annotations):
 | |
|     deletions = 0
 | |
|     for x in range(0, int(annotations["count"])):
 | |
|         key_name = "html_annotation_%d" % x
 | |
|         regions = view.get_regions(key_name)
 | |
|         if len(regions) and not regions[0].empty():
 | |
|             annotations["annotations"]["html_annotation_%d" % x]["region"] = [regions[0].begin(), regions[0].end()]
 | |
|             if deletions:
 | |
|                 new_key = "html_annotation_%d" % (x - deletions)
 | |
|                 annotations["annotations"][new_key] = annotations["annotations"][key_name]
 | |
|                 del annotations["annotations"][key_name]
 | |
|                 new_region = annotations["annotations"][new_key]["region"]
 | |
|                 view.erase_regions(key_name)
 | |
|                 scope, style = get_highlight_style()
 | |
|                 view.add_regions(
 | |
|                     new_key,
 | |
|                     [sublime.Region(new_region[0], new_region[1])],
 | |
|                     scope,
 | |
|                     "",
 | |
|                     style
 | |
|                 )
 | |
|         else:
 | |
|             del annotations["annotations"]["html_annotation_%d" % x]
 | |
|             annotations["count"] -= 1
 | |
|             deletions += 1
 | |
|             if len(regions):
 | |
|                 view.erase_regions(key_name)
 | |
| 
 | |
|     view.settings().set("annotation_comments", annotations)
 | |
| 
 | |
| 
 | |
| def get_annotations(view):
 | |
|     annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|     clean_invalid_regions(view, annotations)
 | |
|     return annotations
 | |
| 
 | |
| 
 | |
| def clear_annotations(view):
 | |
|     annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|     for x in range(0, int(annotations["count"])):
 | |
|         view.erase_regions("html_annotation_%d" % x)
 | |
|     view.settings().set("annotation_comments", {"count": 0, "annotations": {}})
 | |
| 
 | |
| 
 | |
| def delete_annotations(view):
 | |
|     annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|     for sel in view.sel():
 | |
|         for x in range(0, int(annotations["count"])):
 | |
|             region = annotations["annotations"]["html_annotation_%d" % x]["region"]
 | |
|             annotation = sublime.Region(int(region[0]), int(region[1]))
 | |
|             if annotation.contains(sel):
 | |
|                 view.erase_regions("html_annotation_%d" % x)
 | |
|                 break
 | |
|     clean_invalid_regions(view, annotations)
 | |
| 
 | |
| 
 | |
| def get_annotation_comment(view):
 | |
|     comment = None
 | |
|     annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|     if len(view.sel()):
 | |
|         sel = view.sel()[0]
 | |
|         for x in range(0, int(annotations["count"])):
 | |
|             region = annotations["annotations"]["html_annotation_%d" % x]["region"]
 | |
|             annotation = sublime.Region(int(region[0]), int(region[1]))
 | |
|             if annotation.contains(sel):
 | |
|                 comment = annotations["annotations"]["html_annotation_%d" % x]["comment"]
 | |
|     return comment
 | |
| 
 | |
| 
 | |
| def is_selection_in_annotation(view, first_only=False):
 | |
|     mode = view.settings().get("annotation_mode", False)
 | |
|     selection = False
 | |
|     if mode:
 | |
|         annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|         for sel in view.sel():
 | |
|             for x in range(0, int(annotations["count"])):
 | |
|                 region = annotations["annotations"]["html_annotation_%d" % x]["region"]
 | |
|                 annotation = sublime.Region(int(region[0]), int(region[1]))
 | |
|                 if annotation.contains(sel):
 | |
|                     selection = True
 | |
|                     break
 | |
|             if first_only:
 | |
|                 break
 | |
|     return mode and selection
 | |
| 
 | |
| 
 | |
| def annotations_exist(view):
 | |
|     mode = view.settings().get("annotation_mode", False)
 | |
|     found = False
 | |
|     if mode:
 | |
|         annotations = view.settings().get("annotation_comments", {"count": 0, "annotations": {}})
 | |
|         if int(annotations["count"]):
 | |
|             found = True
 | |
|     return mode and found
 | |
| 
 | |
| 
 | |
| def is_selected(view):
 | |
|     mode = view.settings().get("annotation_mode", False)
 | |
|     selected = not view.sel()[0].empty()
 | |
|     return mode and selected
 | |
| 
 | |
| 
 | |
| class ShowAnnotationCommentCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return is_selection_in_annotation(self.view)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         comment = get_annotation_comment(self.view)
 | |
|         if comment != None:
 | |
|             sublime.message_dialog("Annotation Comment:\n\n%s" % comment)
 | |
|             sublime.set_clipboard(comment)
 | |
| 
 | |
| 
 | |
| class ClearAnnotationsCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return annotations_exist(self.view)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         clear_annotations(self.view)
 | |
| 
 | |
| 
 | |
| class DeleteAnnotationsCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return is_selection_in_annotation(self.view)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         delete_annotations(self.view)
 | |
| 
 | |
| 
 | |
| class EnableAnnotationModeCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return not self.view.settings().get("annotation_mode", False)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         self.view.run_command("toggle_annotation_html_mode")
 | |
| 
 | |
| 
 | |
| class DisableAnnotationModeCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return self.view.settings().get("annotation_mode", False)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         self.view.run_command("toggle_annotation_html_mode")
 | |
| 
 | |
| 
 | |
| class ToggleAnnotationHtmlModeCommand(sublime_plugin.TextCommand):
 | |
|     def is_enabled(self):
 | |
|         return not self.view.settings().get('is_widget')
 | |
| 
 | |
|     def run(self, edit):
 | |
|         mode = False if self.view.settings().get("annotation_mode", False) else True
 | |
|         self.view.settings().set("annotation_mode", mode)
 | |
|         if mode:
 | |
|             self.view.settings().set("annotation_read_mode", self.view.is_read_only())
 | |
|             self.view.set_read_only(True)
 | |
|             self.view.set_status("html_annotation_mode", "Annotation Mode: ON")
 | |
|         else:
 | |
|             clear_annotations(self.view)
 | |
|             self.view.set_read_only(self.view.settings().get("annotation_read_mode", False))
 | |
|             self.view.erase_status("html_annotation_mode")
 | |
| 
 | |
| 
 | |
| class AddAnnotationCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return is_selected(self.view)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         AnnotateHtml(self.view).run()
 | |
| 
 | |
| 
 | |
| class EditAnnotationCommand(sublime_plugin.TextCommand):
 | |
|     def is_visible(self):
 | |
|         return is_selection_in_annotation(self.view, first_only=True)
 | |
| 
 | |
|     def run(self, edit):
 | |
|         AnnotateHtml(self.view).run()
 | |
| 
 | |
| 
 | |
| class AnnotateHtml(object):
 | |
|     def __init__(self, view):
 | |
|         self.view = view
 | |
| 
 | |
|     def subset_annotation_adjust(self):
 | |
|         subset = None
 | |
|         comment = ""
 | |
|         parent = None
 | |
|         intersect = False
 | |
|         for k, v in self.annotations["annotations"].items():
 | |
|             region = sublime.Region(int(v["region"][0]), int(v["region"][1]))
 | |
|             if region.contains(self.sel):
 | |
|                 subset = region
 | |
|                 comment = v["comment"]
 | |
|                 parent = k
 | |
|                 break
 | |
|             elif region.intersects(self.sel):
 | |
|                 intersect = True
 | |
|                 break
 | |
|         if subset != None:
 | |
|             self.sel = subset
 | |
|         return comment, parent, intersect
 | |
| 
 | |
|     def add_annotation(self, s, view_id, subset):
 | |
|         window = sublime.active_window()
 | |
|         view = window.active_view() if window != None else None
 | |
|         if s != "" and view != None and view_id == view.id():
 | |
|             if subset == None:
 | |
|                 idx = self.annotations["count"]
 | |
|                 key_name = ("html_annotation_%d" % idx)
 | |
|             else:
 | |
|                 key_name = subset
 | |
| 
 | |
|             self.annotations["annotations"][key_name] = {
 | |
|                 "region": [self.sel.begin(), self.sel.end()],
 | |
|                 "comment": s
 | |
|             }
 | |
|             if subset == None:
 | |
|                 self.annotations["count"] += 1
 | |
|             self.view.settings().set("annotation_comments", self.annotations)
 | |
| 
 | |
|             scope, style = get_highlight_style()
 | |
|             self.view.add_regions(
 | |
|                 key_name,
 | |
|                 [self.sel],
 | |
|                 scope,
 | |
|                 "",
 | |
|                 style
 | |
|             )
 | |
| 
 | |
|     def annotation_panel(self, default_comment, subset):
 | |
|         view_id = self.view.id()
 | |
|         self.view.window().show_input_panel(
 | |
|             ("Annotate region (%d, %d)" % (self.sel.begin(), self.sel.end())),
 | |
|             default_comment,
 | |
|             lambda x: self.add_annotation(x, view_id=view_id, subset=subset),
 | |
|             None,
 | |
|             None
 | |
|         )
 | |
| 
 | |
|     def run(self):
 | |
|         self.sel = self.view.sel()[0]
 | |
|         self.annotations = get_annotations(self.view)
 | |
|         comment, subset, intersects = self.subset_annotation_adjust()
 | |
|         if not intersects:
 | |
|             self.annotation_panel(comment, subset)
 | |
|         else:
 | |
|             sublime.error_message("Cannot have intersecting annotation regions!")
 |