Skip to content

Commit 81e4c93

Browse files
authored
Combined hover content (sublimelsp#225)
* show both diagnostic and info hover at the same time * Only use md for server content, style errors like phantoms * Re-add newlines on hover content (also fixes highlighted block offset)
1 parent 2ce9c0f commit 81e4c93

File tree

3 files changed

+58
-40
lines changed

3 files changed

+58
-40
lines changed

plugin/core/popups.py

+7
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@
1616
.lsp_popup li {
1717
font-family: system;
1818
}
19+
.lsp_popup .errors {
20+
border-width: 0;
21+
background-color: color(var(--redish) alpha(0.25));
22+
color: --whitish;
23+
margin-bottom: 0.5rem;
24+
padding: 0.5rem;
25+
}
1926
'''

plugin/hover.py

+41-40
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@ def is_applicable(cls, settings):
2626
def on_hover(self, point, hover_zone):
2727
if hover_zone != sublime.HOVER_TEXT or self.view.is_popup_visible():
2828
return
29+
self.request_symbol_hover(point)
2930
point_diagnostics = get_point_diagnostics(self.view, point)
3031
if point_diagnostics:
31-
self.show_diagnostics_hover(point, point_diagnostics)
32-
else:
33-
self.request_symbol_hover(point)
32+
self.show_hover(point, self.diagnostics_content(point_diagnostics))
3433

3534
def request_symbol_hover(self, point):
3635
if self.view.match_selector(point, NO_HOVER_SCOPES):
@@ -46,43 +45,36 @@ def request_symbol_hover(self, point):
4645
lambda response: self.handle_response(response, point))
4746

4847
def handle_response(self, response, point):
49-
if self.view.is_popup_visible():
50-
return
51-
contents = "No description available."
48+
all_content = ""
49+
50+
point_diagnostics = get_point_diagnostics(self.view, point)
51+
if point_diagnostics:
52+
all_content += self.diagnostics_content(point_diagnostics)
53+
54+
all_content += self.hover_content(point, response)
55+
56+
self.show_hover(point, all_content)
57+
58+
def diagnostics_content(self, diagnostics):
59+
formatted = ["<div class='errors'>"]
60+
formatted.extend("<pre>{}</pre>".format(diagnostic.message) for diagnostic in diagnostics)
61+
formatted.append("<a href='{}'>{}</a>".format('code-actions', 'Code Actions'))
62+
formatted.append("</div>")
63+
return "".join(formatted)
64+
65+
def hover_content(self, point, response):
66+
contents = ["No description available."]
5267
if isinstance(response, dict):
5368
# Flow returns None sometimes
5469
# See: https://github.com/flowtype/flow-language-server/issues/51
55-
contents = response.get('contents') or contents
56-
self.show_hover(point, contents)
70+
response_content = response.get('contents')
71+
if response_content:
72+
if isinstance(response_content, list):
73+
contents = response_content
74+
else:
75+
contents = [response_content]
5776

58-
def show_diagnostics_hover(self, point, diagnostics):
59-
formatted = list("{}: {}".format(diagnostic.source, diagnostic.message) for diagnostic in diagnostics)
60-
formatted.append("[{}]({})".format('Code Actions', 'code-actions'))
61-
mdpopups.show_popup(
62-
self.view,
63-
"\n".join(formatted),
64-
css=popup_css,
65-
md=True,
66-
flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
67-
location=point,
68-
wrapper_class=popup_class,
69-
max_width=800,
70-
on_navigate=lambda href: self.on_diagnostics_navigate(href, point, diagnostics))
71-
72-
def on_diagnostics_navigate(self, href, point, diagnostics):
73-
# TODO: don't mess with the user's cursor.
74-
# Instead, pass code actions requested from phantoms & hovers should call lsp_code_actions with
75-
# diagnostics as args, positioning resulting UI close to the clicked link.
76-
sel = self.view.sel()
77-
sel.clear()
78-
sel.add(sublime.Region(point, point))
79-
self.view.run_command("lsp_code_actions")
80-
81-
def show_hover(self, point, contents):
8277
formatted = []
83-
if not isinstance(contents, list):
84-
contents = [contents]
85-
8678
for item in contents:
8779
value = ""
8880
language = None
@@ -96,16 +88,25 @@ def show_hover(self, point, contents):
9688
else:
9789
formatted.append(value)
9890

91+
return mdpopups.md2html(self.view, "\n".join(formatted))
92+
93+
def show_hover(self, point, contents):
9994
mdpopups.show_popup(
10095
self.view,
101-
"\n".join(formatted),
96+
contents,
10297
css=popup_css,
103-
md=True,
98+
md=False,
10499
flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
105100
location=point,
106101
wrapper_class=popup_class,
107102
max_width=800,
108-
on_navigate=lambda href: self.on_hover_navigate(href))
103+
on_navigate=lambda href: self.on_hover_navigate(href, point))
109104

110-
def on_hover_navigate(self, href):
111-
webbrowser.open_new_tab(href)
105+
def on_hover_navigate(self, href, point):
106+
if href == 'code-actions':
107+
sel = self.view.sel()
108+
sel.clear()
109+
sel.add(sublime.Region(point, point))
110+
self.view.run_command("lsp_code_actions")
111+
else:
112+
webbrowser.open_new_tab(href)

stubs/mdpopups.pyi

+10
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,13 @@ def update_popup(
3434
nl2br=True,
3535
allow_code_wrap=False
3636
): ...
37+
38+
39+
def md2html(
40+
view: sublime.View,
41+
content: str,
42+
template_vars=None, # type: Optional[str]
43+
template_env_options=None, # type: Optional[dict]
44+
nl2br=True,
45+
allow_code_wrap=False
46+
): ...

0 commit comments

Comments
 (0)