import sublime import sublime_plugin import threading import mdpopups from .view_mixin import RBoxViewMixin from .namespace import namespace_manager from .utils import preference_temporary_settings from .settings import r_box_settings POPUP_TEMPLATE = """{}[Help](help:{}:::{}) [Paste](paste:)""" POPUP_CSS = """ a { font-size: 0.9rem; } .mdpopups .highlight{ font-size: 1.1rem; } """ class RBoxShowPopup(RBoxViewMixin, sublime_plugin.TextCommand): def run(self, edit, pkg, funct, point=-1): sublime.set_timeout_async(lambda: self.run_async(pkg, funct, point)) def run_async(self, pkg, funct, point=-1): if not funct: pkg, funct = self.function_name_at_point(self.view, point) if not pkg: pkg = namespace_manager.find_object_in_packages(funct) funct_call = namespace_manager.get_function_call(pkg, funct) if not funct_call: return with preference_temporary_settings("mdpopups.use_sublime_highlighter", True): with preference_temporary_settings( "mdpopups.sublime_user_lang_map", {"s": [["r"], ["R/R.sublime-syntax"]]}): text = POPUP_TEMPLATE.format( mdpopups.syntax_highlight( self.view, funct_call.strip(), language="r"), pkg, funct) mdpopups.show_popup( self.view, text, css=POPUP_CSS, flags=sublime.COOPERATE_WITH_AUTO_COMPLETE | sublime.HIDE_ON_MOUSE_MOVE_AWAY, location=point, max_width=800, on_navigate=lambda x: self.on_navigate(x, pkg, funct, point)) def on_navigate(self, link, pkg, funct, point): command, option = link.split(":", 1) if command == "help": pkg, funct = option.split(":::") self.view.window().run_command("open_url", { "url": "http://www.rdocumentation.org/packages/{}/topics/{}".format( pkg, funct) }) elif command == "paste": self.replace_function_at_point(self.view, point) self.view.run_command("hide_popup") class RBoxPopupListener(RBoxViewMixin, sublime_plugin.EventListener): thread = None def should_show_popup(self, view): if view.settings().get('is_widget'): return False try: pt = view.sel()[0].end() except Exception: pt = 0 if not view.match_selector(pt, "source.r, source.r-console"): return False return r_box_settings.get("show_popup_hints", True) def on_hover(self, view, point, hover_zone): sublime.set_timeout_async( lambda: self.on_hover_async(view, point, hover_zone)) def on_hover_async(self, view, point, hover_zone): if not self.should_show_popup(view): return if hover_zone != sublime.HOVER_TEXT: return view.run_command("r_box_show_popup", {"pkg": None, "funct": None, "point": point}) def on_modified_async(self, view): if not self.should_show_popup(view): return if self.thread: self.thread.cancel() self.thread = None try: pt = view.sel()[0].end() except Exception: return if view.substr(sublime.Region(pt - 1, pt)) is not "(": return if not view.match_selector(pt - 2, "meta.function-call.r"): return self.thread = threading.Timer( 2, lambda: view.run_command( "r_box_show_popup", { "pkg": None, "funct": None, "point": pt - 1 }) ) self.thread.start()