Created
March 30, 2017 00:12
-
-
Save trishume/c24626e18d163e54addca04710d06f14 to your computer and use it in GitHub Desktop.
Patch to add type inference and definition popups to Sublime Text's Merlin plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Packages/Merlin/sublime-text-merlin.py b/Packages/Merlin/sublime-text-merlin.py | |
--- a/Packages/Merlin/sublime-text-merlin.py | |
+++ b/Packages/Merlin/sublime-text-merlin.py | |
@@ -248,6 +248,57 @@ | |
else: | |
opened_view.run_command("insert_code", { "arg": sig }) | |
+class MerlinInfoPopup: | |
+ """ | |
+ Pop up a menu at a point describing an expression | |
+ """ | |
+ | |
+ def __init__(self, view, point): | |
+ merlin = merlin_view(view) | |
+ merlin.sync() | |
+ | |
+ line, col = view.rowcol(point) | |
+ | |
+ # FIXME: proper integration into sublime-text | |
+ # enclosing is a list of json objects of the form: | |
+ # { 'type': string; | |
+ # 'tail': "no"|"position"|"call" // tailcall information | |
+ # 'start', 'end': {'line': int, 'col': int} | |
+ # } | |
+ self.enclosing = merlin.type_enclosing(line + 1, col) | |
+ self.declaration = merlin.locate(line + 1, col, kind="mli") | |
+ self.definition = merlin.locate(line + 1, col, kind="ml") | |
+ self.view = view | |
+ self.point = point | |
+ | |
+ def _type_str(self): | |
+ if len(self.enclosing) > 0: | |
+ return clean_whitespace(self.enclosing[0]['type']) | |
+ else: | |
+ return "" | |
+ | |
+ def _loc_link(self, loc): | |
+ if isinstance(loc, dict): | |
+ pos = loc['pos'] | |
+ if 'file' in loc: | |
+ short_file = os.path.basename(loc['file']) | |
+ filename = "%s:%d:%d" % (loc.get('file',''), pos['line'], pos['col'] + 1) | |
+ return "<a href=\"{}\">{}:{}</a>".format(filename, short_file,pos['line']) | |
+ else: | |
+ return "[this file]:" + pos['line'] | |
+ else: | |
+ return ""+loc | |
+ | |
+ def show_popup(self): | |
+ print('showing popup') | |
+ content = "<b>Definition:</b> {} <br><b>Declaration:</b> {}<br><b>Type:</b><br> {}".format(self._loc_link(self.definition),self._loc_link(self.declaration), self._type_str()) | |
+ self.view.show_popup(content, | |
+ sublime.HIDE_ON_MOUSE_MOVE_AWAY, self.point, | |
+ 600,150, self.on_navigate) | |
+ | |
+ def on_navigate(self, href): | |
+ self.view.window().open_file(href, sublime.ENCODED_POSITION) | |
+ | |
class InsertCodeCommand(sublime_plugin.TextCommand): | |
def run(self, edit, arg): | |
self.view.insert(edit, self.view.size(), arg) | |
@@ -735,6 +786,11 @@ | |
view.erase_regions('ocaml-underlines-errors') | |
#merlin_error_panel.close() | |
+ @only_ocaml | |
+ def on_hover(self, view, point, hover_zone): | |
+ if hover_zone == sublime.HOVER_TEXT: | |
+ popup = MerlinInfoPopup(view, point) | |
+ popup.show_popup() | |
def _plugin_dir(self): | |
path = os.path.realpath(__file__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment