Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setting to render code lenses as a phantom #1750

Merged
merged 5 commits into from
Jul 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions LSP.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@
// using a keyboard shortcut or the context menu.
"show_code_actions": "annotation",

// Show code lens:
// "annotation" - show an annotation on the right when code actions are available
// "phantom" - show a phantom on the top when code actions are available
"show_code_lens": "annotation",

// Show code actions in hover popup if available
"show_code_actions_in_hover": true,

Expand Down
37 changes: 27 additions & 10 deletions plugin/code_lens.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class CodeLensView:
def __init__(self, view: sublime.View) -> None:
self.view = view
self._init = False
self._phantom = sublime.PhantomSet(view, self.CODE_LENS_KEY)
self._code_lenses = {} # type: Dict[Tuple[int, int], List[CodeLensData]]

def clear(self) -> None:
Expand All @@ -86,6 +87,7 @@ def _region_key(self, index: int) -> str:
return '{0}.{1}'.format(self.CODE_LENS_KEY, index)

def clear_view(self) -> None:
self._phantom.update([])
self.clear_annotations()
rchl marked this conversation as resolved.
Show resolved Hide resolved

def handle_response(self, session_name: str, response: List[CodeLens]) -> None:
Expand Down Expand Up @@ -126,20 +128,35 @@ def _flat_iteration(self) -> Iterable[CodeLensData]:
for group in self._code_lenses.values():
yield from group

def unresolved_visible_code_lens(self, visible: sublime.Region) -> Iterable[CodeLensData]:
def unresolved_visible_code_lenses(self, visible: sublime.Region) -> Iterable[CodeLensData]:
for lens in self._flat_iteration():
if not lens.is_resolved() and visible.intersects(lens.region):
yield lens

def resolved_code_lens(self) -> Iterable[CodeLensData]:
for lens in self._flat_iteration():
if lens.is_resolved():
yield lens

def render(self) -> None:
accent = self.view.style_for_scope("region.greenish markup.accent.codelens.lsp")["foreground"]
for index, lens in enumerate(self._flat_iteration()):
self.view.add_regions(self._region_key(index), [lens.region], "", "", 0, [lens.small_html], accent)
def _get_phantom_region(self, region: sublime.Region) -> sublime.Region:
line = self.view.line(region)
code = self.view.substr(line)
offset = 0
for ch in code:
if ch.isspace():
offset += 1
else:
break
return sublime.Region(line.a + offset, line.b)

def render(self, mode: str) -> None:
if mode == 'phantom':
phantoms = []
for key, group in self._code_lenses.items():
region = sublime.Region(*key)
phantom_region = self._get_phantom_region(region)
html = '\n<small style="font-family: system">|</small>\n'.join(lens.small_html for lens in group)
phantoms.append(sublime.Phantom(phantom_region, html, sublime.LAYOUT_BELOW))
self._phantom.update(phantoms)
else: # 'annotation'
accent = self.view.style_for_scope("region.greenish markup.accent.codelens.lsp")["foreground"]
for index, lens in enumerate(self._flat_iteration()):
self.view.add_regions(self._region_key(index), [lens.region], "", "", 0, [lens.small_html], accent)

def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLens, None, None]:
region = self.view.line(region)
Expand Down
4 changes: 3 additions & 1 deletion plugin/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ class Settings:
only_show_lsp_completions = None # type: bool
popup_max_characters_height = None # type: int
popup_max_characters_width = None # type: int
show_code_actions = None # type: bool
show_code_actions = None # type: str
show_code_lens = None # type: str
show_code_actions_in_hover = None # type: bool
show_diagnostics_count_in_view_status = None # type: bool
show_diagnostics_highlights = None # type: bool
Expand Down Expand Up @@ -184,6 +185,7 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None:
r("popup_max_characters_height", 1000)
r("popup_max_characters_width", 120)
r("show_code_actions", "annotation")
r("show_code_lens", "annotation")
r("show_code_actions_in_hover", True)
r("show_diagnostics_count_in_view_status", False)
r("show_diagnostics_in_view_status", True)
Expand Down
6 changes: 4 additions & 2 deletions plugin/session_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,15 @@ def resolve_visible_code_lenses_async(self) -> None:
if self._code_lenses.is_empty():
return
promises = [] # type: List[Promise[None]]
for code_lens in self._code_lenses.unresolved_visible_code_lens(self.view.visible_region()):
for code_lens in self._code_lenses.unresolved_visible_code_lenses(self.view.visible_region()):
callback = functools.partial(code_lens.resolve, self.view)
promise = self.session.send_request_task(
Request("codeLens/resolve", code_lens.data, self.view)
).then(callback)
promises.append(promise)
Promise.all(promises).then(lambda _: self._code_lenses.render())
mode = userprefs().show_code_lens
render = functools.partial(self._code_lenses.render, mode)
Promise.all(promises).then(lambda _: sublime.set_timeout(render))

def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLens, None, None]:
yield from self._code_lenses.get_resolved_code_lenses_for_region(region)
Expand Down
12 changes: 12 additions & 0 deletions sublime-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,18 @@
"default": "annotation",
"markdownDescription": "Where to show `\"code actions\"`. Due to API limitations, the `\"bulb\"` icon can not be clicked so the code actions can only be triggered using a keyboard shortcut or the context menu."
},
"show_code_lens": {
"enum": [
"annotation",
"phantom"
],
"enumDescriptions": [
"Show code lens to right as a clickable greenish annotation.",
"Show code lens as a phantom."
],
"default": "annotation",
"markdownDescription": "Where to show `\"code lens\"`."
},
"show_code_actions_in_hover": {
"type": "boolean",
"default": true,
Expand Down