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 menu item to disable/enable hover popups #2316

Merged
merged 7 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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 Main.sublime-menu
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@
{
"caption": "LSP: Show Inlay Hints",
"command": "lsp_toggle_inlay_hints"
},
{
"caption": "LSP: Show Hover Popups",
"command": "lsp_toggle_hover_popups",
"checkbox": true
}
]
},
Expand Down
1 change: 1 addition & 0 deletions boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
from .plugin.hierarchy import LspHierarchyToggleCommand
from .plugin.hierarchy import LspTypeHierarchyCommand
from .plugin.hover import LspHoverCommand
from .plugin.hover import LspToggleHoverPopupsCommand
from .plugin.inlay_hint import LspInlayHintClickCommand
from .plugin.inlay_hint import LspToggleInlayHintsCommand
from .plugin.panels import LspClearLogPanelCommand
Expand Down
4 changes: 4 additions & 0 deletions plugin/core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# TODO: Move all constants into this file, so that all other modules can import them without causing import loops

HOVER_HIGHLIGHT_KEY = "lsp_hover_highlight"
HOVER_PROVIDER_COUNT_KEY = "lsp_hover_provider_count"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I like the idea of having all constants in a single file. I think the constants are easier to manage when they are together with relevant piece of the code.

Maybe there is a place for some global constants but I wouldn't make it a rule.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can mark all local / file-specific constants with a leading underscore and only move constants which are shared between multiple files into a common place like this?

We basically already have a part of this in views.py, but it's questionable to me why that file is named views and I think it would be better to only have imports from .protocol and .typing in the file which collects all the shared constants.

3 changes: 3 additions & 0 deletions plugin/core/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@ def start_code_lenses_async(self) -> None:
def set_code_lenses_pending_refresh(self, needs_refresh: bool = True) -> None:
...

def reset_show_definitions(self) -> None:
...


class SessionBufferProtocol(Protocol):

Expand Down
1 change: 1 addition & 0 deletions plugin/core/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def __init__(self, window: sublime.Window, workspace: ProjectFolders, config_man
self.tree_view_sheets = {} # type: Dict[str, TreeViewSheet]
self.total_error_count = 0
self.total_warning_count = 0
self.hover_enabled = True
sublime.set_timeout(functools.partial(self._update_panel_main_thread, _NO_DIAGNOSTICS_PLACEHOLDER, []))
self.panel_manager.ensure_log_panel()
self._config_manager.add_change_listener(self)
Expand Down
2 changes: 1 addition & 1 deletion plugin/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ def on_query_context(self, key: str, operator: int, operand: Any, match_all: boo
def on_hover(self, point: int, hover_zone: int) -> None:
if self.view.is_popup_visible():
return
if hover_zone == sublime.HOVER_TEXT:
if hover_zone == sublime.HOVER_TEXT and self._manager and self._manager.hover_enabled:
self.view.run_command("lsp_hover", {"point": point})
elif hover_zone == sublime.HOVER_GUTTER:
# Lightbulb must be visible and at the same line
Expand Down
29 changes: 28 additions & 1 deletion plugin/hover.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from .code_actions import actions_manager
from .code_actions import CodeActionOrCommand
from .code_actions import CodeActionsByConfigName
from .core.constants import HOVER_HIGHLIGHT_KEY
from .core.constants import HOVER_PROVIDER_COUNT_KEY
from .core.open import open_file_uri
from .core.open import open_in_browser
from .core.promise import Promise
Expand All @@ -17,6 +19,7 @@
from .core.sessions import SessionBufferProtocol
from .core.settings import userprefs
from .core.typing import List, Optional, Dict, Tuple, Sequence, Union
from .core.typing import cast
from .core.url import parse_uri
from .core.views import diagnostic_severity
from .core.views import first_selection_region
Expand All @@ -34,10 +37,10 @@
from .core.views import text_document_position_params
from .core.views import unpack_href_location
from .core.views import update_lsp_popup
from .session_view import HOVER_HIGHLIGHT_KEY
from functools import partial
import html
import sublime
import sublime_plugin


SUBLIME_WORD_MASK = 515
Expand Down Expand Up @@ -366,3 +369,27 @@ def run_async() -> None:
session.run_code_action_async(actions[index], progress=True, view=self.view)

sublime.set_timeout_async(run_async)


class LspToggleHoverPopupsCommand(sublime_plugin.TextCommand):

def is_enabled(self) -> bool:
return self._has_hover_provider()

def is_checked(self) -> bool:
window_manager = windows.lookup(self.view.window())
return window_manager.hover_enabled if window_manager else False

def run(self, edit: sublime.Edit) -> None:
window_manager = windows.lookup(self.view.window())
if window_manager:
window_manager.hover_enabled = not window_manager.hover_enabled
for session in window_manager.get_sessions():
for session_view in session.session_views_async():
if window_manager.hover_enabled:
session_view.view.settings().set('show_definitions', False)
else:
session_view.reset_show_definitions()

def _has_hover_provider(self) -> bool:
return cast(int, self.view.settings().get(HOVER_PROVIDER_COUNT_KEY, 0)) > 0
23 changes: 15 additions & 8 deletions plugin/session_view.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from .code_lens import CodeLensView
from .core.active_request import ActiveRequest
from .core.constants import HOVER_HIGHLIGHT_KEY
from .core.constants import HOVER_PROVIDER_COUNT_KEY
from .core.promise import Promise
from .core.protocol import CodeLens
from .core.protocol import CodeLensExtended
from .core.protocol import DiagnosticTag
from .core.protocol import DocumentUri
from .core.protocol import Notification
from .core.protocol import Request
from .core.registry import windows
from .core.sessions import AbstractViewListener
from .core.sessions import Session
from .core.settings import globalprefs
from .core.settings import userprefs
from .core.typing import Any, Iterable, List, Tuple, Optional, Dict, Generator
from .core.views import DIAGNOSTIC_SEVERITY
Expand All @@ -22,7 +26,6 @@
import sublime

DIAGNOSTIC_TAG_VALUES = [v for (k, v) in DiagnosticTag.__dict__.items() if not k.startswith('_')] # type: List[int]
HOVER_HIGHLIGHT_KEY = "lsp_hover_highlight"


class TagData:
Expand All @@ -41,7 +44,6 @@ class SessionView:

SHOW_DEFINITIONS_KEY = "show_definitions"
HOVER_PROVIDER_KEY = "hoverProvider"
HOVER_PROVIDER_COUNT_KEY = "lsp_hover_provider_count"
AC_TRIGGERS_KEY = "auto_complete_triggers"
COMPLETION_PROVIDER_KEY = "completionProvider"
TRIGGER_CHARACTERS_KEY = "completionProvider.triggerCharacters"
Expand Down Expand Up @@ -224,20 +226,25 @@ def _apply_auto_complete_triggers(

def _increment_hover_count(self) -> None:
settings = self.view.settings()
count = settings.get(self.HOVER_PROVIDER_COUNT_KEY, 0)
count = settings.get(HOVER_PROVIDER_COUNT_KEY, 0)
if isinstance(count, int):
count += 1
settings.set(self.HOVER_PROVIDER_COUNT_KEY, count)
settings.set(self.SHOW_DEFINITIONS_KEY, False)
settings.set(HOVER_PROVIDER_COUNT_KEY, count)
manager = windows.lookup(self.view.window())
if manager and manager.hover_enabled:
settings.set(self.SHOW_DEFINITIONS_KEY, False)

def _decrement_hover_count(self) -> None:
settings = self.view.settings()
count = settings.get(self.HOVER_PROVIDER_COUNT_KEY)
count = settings.get(HOVER_PROVIDER_COUNT_KEY)
if isinstance(count, int):
count -= 1
if count == 0:
settings.erase(self.HOVER_PROVIDER_COUNT_KEY)
settings.set(self.SHOW_DEFINITIONS_KEY, True)
settings.erase(HOVER_PROVIDER_COUNT_KEY)
self.reset_show_definitions()

def reset_show_definitions(self) -> None:
self.view.settings().set(self.SHOW_DEFINITIONS_KEY, globalprefs().get(self.SHOW_DEFINITIONS_KEY))

def get_uri(self) -> Optional[DocumentUri]:
listener = self.listener()
Expand Down