From b2811f0f90edd2242db7a07d6513709b93f57236 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Wed, 9 Nov 2022 19:02:47 +0100 Subject: [PATCH 1/4] Make Goto Diagnostic overlays consistent --- plugin/goto_diagnostic.py | 56 +++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index 10c824a3d..e0a81f20c 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -4,12 +4,14 @@ from .core.sessions import Session from .core.settings import userprefs from .core.types import ClientConfig -from .core.typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union +from .core.typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Union from .core.url import parse_uri, unparse_uri from .core.views import DIAGNOSTIC_KINDS from .core.views import MissingUriError, uri_from_view, get_uri_and_position_from_location, to_encoded_filename from .core.views import format_diagnostic_for_html from .core.views import diagnostic_severity, format_diagnostic_source_and_code, format_severity +from abc import ABCMeta +from abc import abstractmethod from collections import Counter, OrderedDict from pathlib import Path import functools @@ -67,6 +69,7 @@ def input(self, args: dict) -> Optional[sublime_plugin.CommandInputHandler]: if uri == "$view_uri": try: uri = uri_from_view(view) + return DiagnosticUriInputHandler(self.window, view, uri) except MissingUriError: return None if not diagnostic: @@ -77,18 +80,61 @@ def input_description(self) -> str: return "Goto Diagnostic" -class DiagnosticUriInputHandler(sublime_plugin.ListInputHandler): +ListItemsReturn = Union[List[str], Tuple[List[str], int], List[Tuple[str, Any]], Tuple[List[Tuple[str, Any]], int], + List[sublime.ListInputItem], Tuple[List[sublime.ListInputItem], int]] + + +class PreselectedListInputHandler(sublime_plugin.ListInputHandler, metaclass=ABCMeta): + """ + Similar to ListInputHandler, but allows to preselect a value like some of the input overlays in Sublime Merge. + Inspired by https://github.com/sublimehq/sublime_text/issues/5507. + + Subclasses of PreselectedListInputHandler must implement the _list_items() method, i.e. just prepend the regular + list_items() with an underscore. + + When an instance of PreselectedListInputHandler is created, it must be given the window as an argument. + An optional second argument initial_value can be provided to preselect a value. + """ + + _window = None # type: Optional[sublime.Window] + _initial_value = None # type: Optional[Union[str, sublime.ListInputItem]] + _preselect = False + + def __init__( + self, window: sublime.Window, initial_value: Optional[Union[str, sublime.ListInputItem]] = None + ) -> None: + super().__init__() + if initial_value is not None: + self._window = window + self._initial_value = initial_value + self._preselect = True + + def list_items(self) -> ListItemsReturn: + if self._preselect and self._initial_value is not None and self._window is not None: + self._preselect = False + sublime.set_timeout(functools.partial(self._window.run_command, 'select')) + return [self._initial_value], 0 # pyright: ignore[reportGeneralTypeIssues] + else: + return self._list_items() + + @abstractmethod + def _list_items(self) -> ListItemsReturn: + raise NotImplementedError() + + +class DiagnosticUriInputHandler(PreselectedListInputHandler): _preview = None # type: Optional[sublime.View] uri = None # Optional[DocumentUri] - def __init__(self, window: sublime.Window, view: sublime.View) -> None: + def __init__(self, window: sublime.Window, view: sublime.View, initial_value: Optional[DocumentUri] = None) -> None: + super().__init__(window, initial_value) self.window = window self.view = view def name(self) -> str: return "uri" - def list_items(self) -> Tuple[List[sublime.ListInputItem], int]: + def _list_items(self) -> Tuple[List[sublime.ListInputItem], int]: max_severity = userprefs().diagnostics_panel_include_severity_level # collect severities and location of first diagnostic per uri severities_per_path = OrderedDict() # type: OrderedDict[ParsedUri, List[DiagnosticSeverity]] @@ -141,7 +187,7 @@ def cancel(self) -> None: self.window.focus_view(self.view) def preview(self, value: Optional[DocumentUri]) -> str: - if not value: + if not value or not hasattr(self, 'first_locations'): return "" parsed_uri = parse_uri(value) session, location = self.first_locations[parsed_uri] From 76685385497760fe6d03345ae4c9888bc9f2ad5b Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Thu, 10 Nov 2022 16:28:11 +0100 Subject: [PATCH 2/4] Tweak wording in docstring --- plugin/goto_diagnostic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index e0a81f20c..ba8e73e8f 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -89,11 +89,11 @@ class PreselectedListInputHandler(sublime_plugin.ListInputHandler, metaclass=ABC Similar to ListInputHandler, but allows to preselect a value like some of the input overlays in Sublime Merge. Inspired by https://github.com/sublimehq/sublime_text/issues/5507. - Subclasses of PreselectedListInputHandler must implement the _list_items() method, i.e. just prepend the regular - list_items() with an underscore. + Subclasses of PreselectedListInputHandler must not implement the `list_items` method, but instead `_list_items`, + i.e. just prepend an underscore to the regular `list_items`. When an instance of PreselectedListInputHandler is created, it must be given the window as an argument. - An optional second argument initial_value can be provided to preselect a value. + An optional second argument `initial_value` can be provided to preselect a value. """ _window = None # type: Optional[sublime.Window] From 5f4d4c4b0013f835fbaf53504057a695963e119a Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Fri, 11 Nov 2022 22:55:18 +0100 Subject: [PATCH 3/4] Address comments --- plugin/goto_diagnostic.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index ba8e73e8f..9ad644672 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -69,9 +69,9 @@ def input(self, args: dict) -> Optional[sublime_plugin.CommandInputHandler]: if uri == "$view_uri": try: uri = uri_from_view(view) - return DiagnosticUriInputHandler(self.window, view, uri) except MissingUriError: return None + return DiagnosticUriInputHandler(self.window, view, uri) if not diagnostic: return DiagnosticInputHandler(self.window, view, uri) return None @@ -89,36 +89,34 @@ class PreselectedListInputHandler(sublime_plugin.ListInputHandler, metaclass=ABC Similar to ListInputHandler, but allows to preselect a value like some of the input overlays in Sublime Merge. Inspired by https://github.com/sublimehq/sublime_text/issues/5507. - Subclasses of PreselectedListInputHandler must not implement the `list_items` method, but instead `_list_items`, - i.e. just prepend an underscore to the regular `list_items`. + Subclasses of PreselectedListInputHandler must not implement the `list_items` method, but instead `get_list_items`, + i.e. just prepend `get_` to the regular `list_items` method. When an instance of PreselectedListInputHandler is created, it must be given the window as an argument. An optional second argument `initial_value` can be provided to preselect a value. """ - _window = None # type: Optional[sublime.Window] - _initial_value = None # type: Optional[Union[str, sublime.ListInputItem]] - _preselect = False - def __init__( self, window: sublime.Window, initial_value: Optional[Union[str, sublime.ListInputItem]] = None ) -> None: super().__init__() - if initial_value is not None: - self._window = window - self._initial_value = initial_value - self._preselect = True + self._window = window + self._initial_value = initial_value def list_items(self) -> ListItemsReturn: - if self._preselect and self._initial_value is not None and self._window is not None: - self._preselect = False - sublime.set_timeout(functools.partial(self._window.run_command, 'select')) + if self._initial_value is not None: + sublime.set_timeout(self._select_and_reset) return [self._initial_value], 0 # pyright: ignore[reportGeneralTypeIssues] else: - return self._list_items() + return self.get_list_items() + + def _select_and_reset(self) -> None: + self._initial_value = None + if self._window.is_valid(): + self._window.run_command('select') @abstractmethod - def _list_items(self) -> ListItemsReturn: + def get_list_items(self) -> ListItemsReturn: raise NotImplementedError() @@ -134,7 +132,7 @@ def __init__(self, window: sublime.Window, view: sublime.View, initial_value: Op def name(self) -> str: return "uri" - def _list_items(self) -> Tuple[List[sublime.ListInputItem], int]: + def get_list_items(self) -> Tuple[List[sublime.ListInputItem], int]: max_severity = userprefs().diagnostics_panel_include_severity_level # collect severities and location of first diagnostic per uri severities_per_path = OrderedDict() # type: OrderedDict[ParsedUri, List[DiagnosticSeverity]] From 9ef0cffc1d3a7593508d271061f6cbdf4bf3b87e Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Sat, 12 Nov 2022 09:44:04 +0100 Subject: [PATCH 4/4] Improve filename label if there are no window folders --- plugin/goto_diagnostic.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index 9ad644672..a5812cee3 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -15,6 +15,7 @@ from collections import Counter, OrderedDict from pathlib import Path import functools +import os import sublime import sublime_plugin @@ -203,7 +204,8 @@ def _simple_project_path(self, parsed_uri: ParsedUri) -> str: def _project_path(self, parsed_uri: ParsedUri) -> str: scheme, path = parsed_uri if scheme == "file": - path = str(project_path(map(Path, self.window.folders()), Path(path))) or path + relative_path = project_path(map(Path, self.window.folders()), Path(path)) + return str(relative_path) if relative_path else os.path.basename(path) return path