Skip to content

Commit

Permalink
Extracted arghint render logic to new classes, one for each strategy …
Browse files Browse the repository at this point in the history
…(tooltip, status, panel) and added style to tooltip HTML
  • Loading branch information
atabel authored and marijnh committed Jun 1, 2015
1 parent 075eaa7 commit be8eb96
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 65 deletions.
82 changes: 17 additions & 65 deletions tern.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import sublime, sublime_plugin
import os, sys, platform, subprocess, webbrowser, json, re, time, atexit
try:
# python 2
from utils.renderer import create_arghints_renderer
except:
from .utils.renderer import create_arghints_renderer

windows = platform.system() == "Windows"
python3 = sys.version_info[0] > 2
Expand All @@ -12,11 +17,10 @@ def is_js_file(view):

files = {}
arghints_enabled = False
arghints_type = "status"
arghints_renderer = None
arg_completion_enabled = False
tern_command = None
tern_arguments = []
tern_arghint = ""

def on_deactivated(view):
pfile = files.get(view.file_name(), None)
Expand Down Expand Up @@ -460,65 +464,10 @@ def show_argument_hints(pfile, view):
render_argument_hints(pfile, view, parsed, argpos)

def render_argument_hints(pfile, view, ftype, argpos):
global tern_arghint
if ftype is None:
if pfile.showing_arguments:
if arghints_type == "panel":
panel = view.window().get_output_panel("tern_arghint")
tern_arghint = ""
panel.run_command("tern_arghint")
elif arghints_type == "status":
sublime.status_message("")
pfile.showing_arguments = False
return

msg = ftype["name"] + "("
i = 0
for name, type in ftype["args"]:
if i > 0: msg += ", "
if i == argpos: msg += "*"
msg += name + ("" if type == "?" else ": " + type)
i += 1
msg += ")"
if ftype["retval"] is not None:
msg += " -> " + ftype["retval"]

if arghints_type == "panel":
panel = view.window().get_output_panel("tern_arghint")
tern_arghint = msg
panel.run_command("tern_arghint")
view.window().run_command("show_panel", {"panel": "output.tern_arghint"})
elif arghints_type == "status":
sublime.status_message(msg)
elif arghints_type == "tooltip":
view.show_popup(render_tooltip(ftype, msg), sublime.COOPERATE_WITH_AUTO_COMPLETE, max_width=600, on_navigate=go_to_url)
pfile.showing_arguments = True

def go_to_url(url=None):
if url:
import webbrowser
webbrowser.open(url)

def render_tooltip(ftype, msg):
output = '''
<style>
div {
font-size: 14px;
}
.bold{
font-weight: bold
}
</style>
'''
output = output + '<div class="bold">{}</div>'.format(msg)
url = '<div><a href={url}>{url}</a></div>'
doc = '<div>{doc}</div>'

if ftype['url']:
output += url.format(url=ftype['url'])
if ftype['doc']:
output += doc.format(doc=ftype['doc'])
return output
arghints_renderer.clean(pfile, view)
else:
arghints_renderer.render(pfile, view, ftype, argpos)

def parse_function_type(data):
type = data["type"]
Expand Down Expand Up @@ -555,8 +504,8 @@ def parse_function_type(data):
jump_stack = []

class TernArghintCommand(sublime_plugin.TextCommand):
def run(self, edit):
self.view.insert(edit, 0, tern_arghint)
def run(self, edit, **args):
self.view.insert(edit, 0, args.get('msg', ''))

class TernJumpToDef(sublime_plugin.TextCommand):
def run(self, edit, **args):
Expand Down Expand Up @@ -604,15 +553,18 @@ def run(self, edit, **args):
plugin_dir = os.path.abspath(os.path.dirname(__file__))

def plugin_loaded():
global arghints_enabled, arghints_type, tern_command, tern_arguments
global arghints_enabled, arghints_renderer, tern_command, tern_arguments
global arg_completion_enabled
settings = sublime.load_settings("Preferences.sublime-settings")
arghints_enabled = settings.get("tern_argument_hints", False)
arg_completion_enabled = settings.get("tern_argument_completion", False)
if arghints_enabled:
if "show_popup" in dir(sublime.View):
arghints_type = "tooltip"
arghints_type = settings.get("tern_argument_hints_type", arghints_type)
default_arghints_type = "tooltip"
else:
default_arghints_type = "status"
arghints_type = settings.get("tern_argument_hints_type", default_arghints_type)
arghints_renderer = create_arghints_renderer(arghints_type)
tern_arguments = settings.get("tern_arguments", [])
if not isinstance(tern_arguments, list):
tern_arguments = [tern_arguments]
Expand Down
1 change: 1 addition & 0 deletions utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

138 changes: 138 additions & 0 deletions utils/renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import sublime

def get_message_from_ftype(ftype, argpos):
msg = ftype["name"] + "("
i = 0
for name, type in ftype["args"]:
if i > 0: msg += ", "
if i == argpos: msg += "*"
msg += name + ("" if type == "?" else ": " + type)
i += 1
msg += ")"
if ftype["retval"] is not None:
msg += " -> " + ftype["retval"]
return msg

def get_html_message_from_ftype(ftype, argpos):
style = '''
<style>
.hint-popup {
padding-top: 10px;
font-size: 14px;
}
.hint-line-content {
padding-bottom: 10px;
}
.func-arrow {
font-size: 16px;
}
.arg-name {
color: #70a;
}
.current-arg {
font-weight: bold;
text-decoration: underline;
}
.doc {
font-style: italic;
}
.type {
color: #07c;
}
</style>
'''

func_signature = '<span class="func-name">{func_name}</span>('.format(func_name=ftype["name"])
i = 0
for name, type in ftype["args"]:
if i > 0: func_signature += ", "
if i == argpos:
func_signature += '<span class="arg-name current-arg">{name}</span>'.format(name=name)
else:
func_signature += '<span class="arg-name">{name}</span>'.format(name=name)
if type != "?":
func_signature += ': <span class="type">{type}</span>'.format(type=type)
i += 1
func_signature += ")"
if ftype["retval"] is not None:
func_signature += '<span class="func-arrow"> ➜ </span><span class="type">{type}</span>'.format(type=ftype["retval"])

template = '''
{style}
<div class="hint-popup">
<div class="hint-line func-signature">{func_signature}</div>
<div class="hint-line doc-link">{doc_link}</div>
<div class="hint-line doc">{doc}</div>
</div>
'''

template_data = {
'style': style,
'func_signature': hint_line(func_signature),
'doc_link': hint_line(link(ftype['url'])),
'doc': hint_line(ftype['doc'])
}

return template.format(**template_data)

def maybe(fn):
def maybe_fn(arg):
return fn(arg) if arg else ''
return maybe_fn

@maybe
def link(url):
return '<a href={url}>{url}</a>'.format(url=url)

@maybe
def hint_line(txt):
return '<div class="hint-line-content">{txt}</div>'.format(txt=txt)

def go_to_url(url=None):
if url:
import webbrowser
webbrowser.open(url)

class TooltipArghintsRenderer(object):
def render(self, pfile, view, ftype, argpos):
view.show_popup(get_html_message_from_ftype(ftype, argpos), sublime.COOPERATE_WITH_AUTO_COMPLETE, max_width=600, on_navigate=go_to_url)
pfile.showing_arguments = True

def clean(self, pfile, view):
pfile.showing_arguments = False


class StatusArghintsRenderer(object):
def render(self, pfile, view, ftype, argpos):
msg = get_message_from_ftype(ftype, argpos)
sublime.status_message(msg)
pfile.showing_arguments = True

def clean(self, pfile, view):
if pfile.showing_arguments:
sublime.status_message("")
pfile.showing_arguments = False


class PanelArghintsRenderer(object):
def render(self, pfile, view, ftype, argpos):
msg = get_message_from_ftype(ftype, argpos)
panel = view.window().get_output_panel("tern_arghint")
panel.run_command("tern_arghint", {"msg": msg})
view.window().run_command("show_panel", {"panel": "output.tern_arghint"})
pfile.showing_arguments = True

def clean(self, pfile, view):
if pfile.showing_arguments:
panel = view.window().get_output_panel("tern_arghint")
panel.run_command("tern_arghint", {"msg": ""})
pfile.showing_arguments = False


def create_arghints_renderer(arghints_type):
if arghints_type == "tooltip":
return TooltipArghintsRenderer()
elif arghints_type == "status":
return StatusArghintsRenderer()
elif arghints_type == "panel":
return PanelArghintsRenderer()

0 comments on commit be8eb96

Please sign in to comment.