From 409817aa820bbd1165d3544a5432071e802ccdb1 Mon Sep 17 00:00:00 2001 From: Justin Lam <4069123+ninth-dev@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:20:36 +1000 Subject: [PATCH 01/10] Add group support --- plugin/core/open.py | 28 ++++++++++++++++++++++++---- plugin/goto.py | 16 +++++++++++----- plugin/locationpicker.py | 12 ++++++++---- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/plugin/core/open.py b/plugin/core/open.py index acec50673..301d844f2 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -15,6 +15,25 @@ opening_files = {} # type: Dict[str, Tuple[Promise[Optional[sublime.View]], ResolveFunc[Optional[sublime.View]]]] +def _return_existing_view(flags: int, open_file_group: int, active_group: int, specified_group: int ) -> bool: + open_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) + file_in_active_group = open_file_group == active_group + + # true if DONT want to force it to open in the active group + # i.e. just jump to the file + select_file = not bool(flags & sublime.FORCE_GROUP) + + if specified_group > -1: + return False + if open_side_by_side: + # default is -1... and is ignored + # always open in the specific group if pass in + return False + elif file_in_active_group: + return True + else: + return select_file + def open_file( window: sublime.Window, uri: DocumentUri, flags: int = 0, group: int = -1 ) -> Promise[Optional[sublime.View]]: @@ -27,11 +46,12 @@ def open_file( # window.open_file brings the file to focus if it's already opened, which we don't want (unless it's supposed # to open as a separate view). view = window.find_open_file(file) + if view: - opens_in_desired_group = not bool(flags & sublime.FORCE_GROUP) or \ - window.get_view_index(view)[0] == window.active_group() - opens_in_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) - return_existing_view = opens_in_desired_group and not opens_in_side_by_side + return_existing_view = _return_existing_view( + flags, window.get_view_index(view)[0], window.active_group(), group + ) + if return_existing_view: return Promise.resolve(view) diff --git a/plugin/goto.py b/plugin/goto.py index d6c974502..6306b9041 100644 --- a/plugin/goto.py +++ b/plugin/goto.py @@ -34,7 +34,8 @@ def run( point: Optional[int] = None, side_by_side: bool = False, force_group: bool = True, - fallback: bool = False + fallback: bool = False, + group: int = -1 ) -> None: session = self.best_session(self.capability) position = get_position(self.view, event, point) @@ -42,7 +43,11 @@ def run( params = text_document_position_params(self.view, position) request = Request(self.method, params, self.view, progress=True) session.send_request( - request, functools.partial(self._handle_response_async, session, side_by_side, force_group, fallback)) + request, + functools.partial( + self._handle_response_async, session, side_by_side, force_group, fallback, group + ), + ) else: self._handle_no_results(fallback, side_by_side) @@ -52,20 +57,21 @@ def _handle_response_async( side_by_side: bool, force_group: bool, fallback: bool, + group: int, response: Union[None, Location, List[Location], List[LocationLink]] ) -> None: if isinstance(response, dict): self.view.run_command("add_jump_record", {"selection": [(r.a, r.b) for r in self.view.sel()]}) - open_location_async(session, response, side_by_side, force_group) + open_location_async(session, response, side_by_side, force_group, group) elif isinstance(response, list): if len(response) == 0: self._handle_no_results(fallback, side_by_side) elif len(response) == 1: self.view.run_command("add_jump_record", {"selection": [(r.a, r.b) for r in self.view.sel()]}) - open_location_async(session, response[0], side_by_side, force_group) + open_location_async(session, response[0], side_by_side, force_group, group) else: self.view.run_command("add_jump_record", {"selection": [(r.a, r.b) for r in self.view.sel()]}) - sublime.set_timeout(functools.partial(LocationPicker, self.view, session, response, side_by_side)) + sublime.set_timeout(functools.partial(LocationPicker, self.view, session, response, side_by_side, group)) else: self._handle_no_results(fallback, side_by_side) diff --git a/plugin/locationpicker.py b/plugin/locationpicker.py index dda13839c..159871c46 100644 --- a/plugin/locationpicker.py +++ b/plugin/locationpicker.py @@ -16,7 +16,8 @@ def open_location_async( session: Session, location: Union[Location, LocationLink], side_by_side: bool, - force_group: bool + force_group: bool, + group: int = -1 ) -> None: flags = sublime.ENCODED_POSITION if force_group: @@ -28,7 +29,7 @@ def check_success_async(view: Optional[sublime.View]) -> None: if not view: sublime.error_message("Unable to open URI") - session.open_location_async(location, flags).then(check_success_async) + session.open_location_async(location, flags, group).then(check_success_async) def open_basic_file( @@ -59,7 +60,8 @@ def __init__( view: sublime.View, session: Session, locations: Union[List[Location], List[LocationLink]], - side_by_side: bool + side_by_side: bool, + group: int = -1 ) -> None: self._view = view self._view_states = ([r.to_tuple() for r in view.sel()], view.viewport_position()) @@ -69,10 +71,12 @@ def __init__( self._window = window self._weaksession = weakref.ref(session) self._side_by_side = side_by_side + self._group = group self._items = locations self._highlighted_view = None # type: Optional[sublime.View] manager = session.manager() base_dir = manager.get_project_path(view.file_name() or "") if manager else None + self._window.focus_group(group) self._window.show_quick_panel( items=[location_to_human_readable(session.config, base_dir, location) for location in locations], on_select=self._select_entry, @@ -103,7 +107,7 @@ def _select_entry(self, index: int) -> None: self._window.status_message("Unable to open {}".format(uri)) else: sublime.set_timeout_async( - functools.partial(open_location_async, session, location, self._side_by_side, True)) + functools.partial(open_location_async, session, location, self._side_by_side, True, self._group)) else: self._window.focus_view(self._view) # When in side-by-side mode close the current highlighted From 49a1221f0e6984d86f1b7ecbd0c2f78290df085f Mon Sep 17 00:00:00 2001 From: Justin Lam <4069123+ninth-dev@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:26:44 +1000 Subject: [PATCH 02/10] Update docs --- Default.sublime-keymap | 3 ++- docs/src/features.md | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index edac87844..a03ca0719 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -174,7 +174,8 @@ // "args": { // "side_by_side": false, // "force_group": true, - // "fallback": false + // "fallback": false, + // "group": -1 // }, // "keys": [ // "f12" diff --git a/docs/src/features.md b/docs/src/features.md index 73d1dc51e..74230c1cd 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -34,6 +34,8 @@ In addition to the basic "Goto Definition", the protocol also provides further r Additionally, the LSP's "Goto Definition" command can fall back to the built-in Sublime's "Goto Definition" if the `fallback` argument is set to `true`. This way, when there are no results found the built-in "Goto Definition" command will be triggered. +To always open the results in a certain group, you can pass the `group` argument. + ## Find References [Example GIF 1](https://user-images.githubusercontent.com/6579999/128551752-b37fe407-148c-41cf-b1e4-6fe96ed0f77c.gif) From 5cbff47eba0acacb0ed0edc43f1eb598dcf8f5a0 Mon Sep 17 00:00:00 2001 From: Justin Lam <4069123+ninth-dev@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:29:22 +1000 Subject: [PATCH 03/10] Fix style issues --- plugin/core/open.py | 3 ++- plugin/goto.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugin/core/open.py b/plugin/core/open.py index 301d844f2..1f4d7be34 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -15,7 +15,7 @@ opening_files = {} # type: Dict[str, Tuple[Promise[Optional[sublime.View]], ResolveFunc[Optional[sublime.View]]]] -def _return_existing_view(flags: int, open_file_group: int, active_group: int, specified_group: int ) -> bool: +def _return_existing_view(flags: int, open_file_group: int, active_group: int, specified_group: int) -> bool: open_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) file_in_active_group = open_file_group == active_group @@ -34,6 +34,7 @@ def _return_existing_view(flags: int, open_file_group: int, active_group: int, s else: return select_file + def open_file( window: sublime.Window, uri: DocumentUri, flags: int = 0, group: int = -1 ) -> Promise[Optional[sublime.View]]: diff --git a/plugin/goto.py b/plugin/goto.py index 6306b9041..9661a081c 100644 --- a/plugin/goto.py +++ b/plugin/goto.py @@ -71,7 +71,9 @@ def _handle_response_async( open_location_async(session, response[0], side_by_side, force_group, group) else: self.view.run_command("add_jump_record", {"selection": [(r.a, r.b) for r in self.view.sel()]}) - sublime.set_timeout(functools.partial(LocationPicker, self.view, session, response, side_by_side, group)) + sublime.set_timeout( + functools.partial(LocationPicker, self.view, session, response, side_by_side, group) + ) else: self._handle_no_results(fallback, side_by_side) From 20e51fd277a52ad464d8e7498412cfc3f86b0939 Mon Sep 17 00:00:00 2001 From: Justin Lam <4069123+ninth-dev@users.noreply.github.com> Date: Wed, 24 Aug 2022 20:02:52 +1000 Subject: [PATCH 04/10] Address PR comments --- Default.sublime-keymap | 9 ++++++--- docs/src/features.md | 2 +- plugin/core/open.py | 19 +++++-------------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index a03ca0719..0c17f8203 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -198,7 +198,8 @@ // "command": "lsp_symbol_type_definition", // "args": { // "side_by_side": false, - // "force_group": true + // "force_group": true, + // "group": -1 // }, // "keys": [ // "UNBOUND" @@ -221,7 +222,8 @@ // "command": "lsp_symbol_declaration", // "args": { // "side_by_side": false, - // "force_group": true + // "force_group": true, + // "group": -1 // }, // "keys": [ // "UNBOUND" @@ -244,7 +246,8 @@ // "command": "lsp_symbol_implementation", // "args": { // "side_by_side": false, - // "force_group": true + // "force_group": true, + // "group": -1 // }, // "keys": [ // "UNBOUND" diff --git a/docs/src/features.md b/docs/src/features.md index 74230c1cd..8fe43f626 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -34,7 +34,7 @@ In addition to the basic "Goto Definition", the protocol also provides further r Additionally, the LSP's "Goto Definition" command can fall back to the built-in Sublime's "Goto Definition" if the `fallback` argument is set to `true`. This way, when there are no results found the built-in "Goto Definition" command will be triggered. -To always open the results in a certain group, you can pass the `group` argument. +To always open the results in a certain group, you can use the `group` argument. ## Find References diff --git a/plugin/core/open.py b/plugin/core/open.py index 1f4d7be34..ced06a306 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -16,23 +16,16 @@ def _return_existing_view(flags: int, open_file_group: int, active_group: int, specified_group: int) -> bool: - open_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) - file_in_active_group = open_file_group == active_group - - # true if DONT want to force it to open in the active group - # i.e. just jump to the file - select_file = not bool(flags & sublime.FORCE_GROUP) - if specified_group > -1: return False + open_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) if open_side_by_side: - # default is -1... and is ignored - # always open in the specific group if pass in return False - elif file_in_active_group: + file_in_active_group = open_file_group == active_group + if file_in_active_group: return True - else: - return select_file + # Jump to the file if sublime.FORCE_GROUP is set + return not bool(flags & sublime.FORCE_GROUP) def open_file( @@ -47,12 +40,10 @@ def open_file( # window.open_file brings the file to focus if it's already opened, which we don't want (unless it's supposed # to open as a separate view). view = window.find_open_file(file) - if view: return_existing_view = _return_existing_view( flags, window.get_view_index(view)[0], window.active_group(), group ) - if return_existing_view: return Promise.resolve(view) From 9bc4a04fe63074821d2c36e7444a250e6939eaf8 Mon Sep 17 00:00:00 2001 From: Justin Lam <4069123+ninth-dev@users.noreply.github.com> Date: Thu, 25 Aug 2022 16:04:53 +1000 Subject: [PATCH 05/10] Address PR comments --- plugin/core/open.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/plugin/core/open.py b/plugin/core/open.py index ced06a306..5fb8eea9f 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -15,16 +15,18 @@ opening_files = {} # type: Dict[str, Tuple[Promise[Optional[sublime.View]], ResolveFunc[Optional[sublime.View]]]] -def _return_existing_view(flags: int, open_file_group: int, active_group: int, specified_group: int) -> bool: +def _return_existing_view(flags: int, existing_view_group: int, active_group: int, specified_group: int) -> bool: + # the specified_group is supplied if specified_group > -1: + # use existing_view_group if it is in the active group + return existing_view_group == active_group + # open side by side + if bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)): return False - open_side_by_side = bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) - if open_side_by_side: - return False - file_in_active_group = open_file_group == active_group - if file_in_active_group: + # existing view is in active group ( no group is specified and not side by side ) + if existing_view_group == active_group: return True - # Jump to the file if sublime.FORCE_GROUP is set + # Jump to the file if sublime.FORCE_GROUP is not set return not bool(flags & sublime.FORCE_GROUP) From d3261062a0c34e16f98bcd5fcd081571bc512632 Mon Sep 17 00:00:00 2001 From: ninth-dev <4069123+ninth-dev@users.noreply.github.com> Date: Fri, 26 Aug 2022 21:43:13 +1000 Subject: [PATCH 06/10] Focus group before opening new scratch buffer --- plugin/core/sessions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 12cbf4556..28647c062 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1518,6 +1518,8 @@ def _open_uri_with_plugin_async( result = Promise.packaged_task() # type: PackagedTask[Optional[sublime.View]] def open_scratch_buffer(title: str, content: str, syntax: str) -> None: + if group > -1: + self.window.focus_group(group) v = self.window.new_file(syntax=syntax, flags=flags) # Note: the __init__ of ViewEventListeners is invoked in the next UI frame, so we can fill in the # settings object here at our leisure. From a9f736e729ab80aca3cfcac8d5ea7d3457e79135 Mon Sep 17 00:00:00 2001 From: ninth-dev <4069123+ninth-dev@users.noreply.github.com> Date: Tue, 30 Aug 2022 17:41:23 +1000 Subject: [PATCH 07/10] Address PR comments - Update the feature documentation - remove redundant variables - add group in is_enabled --- docs/src/features.md | 2 +- plugin/core/open.py | 17 ++++++----------- plugin/goto.py | 3 ++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/src/features.md b/docs/src/features.md index 8fe43f626..545383ba1 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -34,7 +34,7 @@ In addition to the basic "Goto Definition", the protocol also provides further r Additionally, the LSP's "Goto Definition" command can fall back to the built-in Sublime's "Goto Definition" if the `fallback` argument is set to `true`. This way, when there are no results found the built-in "Goto Definition" command will be triggered. -To always open the results in a certain group, you can use the `group` argument. +To attempt to open the results in a certain group, you can use the `group` argument. If the specified `group` does not exist, then it will be ignored. ## Find References diff --git a/plugin/core/open.py b/plugin/core/open.py index 5fb8eea9f..058463665 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -15,16 +15,15 @@ opening_files = {} # type: Dict[str, Tuple[Promise[Optional[sublime.View]], ResolveFunc[Optional[sublime.View]]]] -def _return_existing_view(flags: int, existing_view_group: int, active_group: int, specified_group: int) -> bool: +def _return_existing_view(flags: int, is_view_in_active_group: bool, specified_group: int) -> bool: # the specified_group is supplied if specified_group > -1: - # use existing_view_group if it is in the active group - return existing_view_group == active_group + return is_view_in_active_group # open side by side if bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)): return False - # existing view is in active group ( no group is specified and not side by side ) - if existing_view_group == active_group: + # view is in active group ( no group is specified and not side by side ) + if is_view_in_active_group: return True # Jump to the file if sublime.FORCE_GROUP is not set return not bool(flags & sublime.FORCE_GROUP) @@ -42,12 +41,8 @@ def open_file( # window.open_file brings the file to focus if it's already opened, which we don't want (unless it's supposed # to open as a separate view). view = window.find_open_file(file) - if view: - return_existing_view = _return_existing_view( - flags, window.get_view_index(view)[0], window.active_group(), group - ) - if return_existing_view: - return Promise.resolve(view) + if view and _return_existing_view(flags, window.get_view_index(view)[0] == window.active_group(), group): + return Promise.resolve(view) view = window.open_file(file, flags, group) if not view.is_loading(): diff --git a/plugin/goto.py b/plugin/goto.py index 9661a081c..52743a779 100644 --- a/plugin/goto.py +++ b/plugin/goto.py @@ -23,7 +23,8 @@ def is_enabled( point: Optional[int] = None, side_by_side: bool = False, force_group: bool = True, - fallback: bool = False + fallback: bool = False, + group: int = -1 ) -> bool: return fallback or super().is_enabled(event, point) From 60d96cee558a5649ddb46adbbcdb4fb6461661ef Mon Sep 17 00:00:00 2001 From: ninth-dev <4069123+ninth-dev@users.noreply.github.com> Date: Tue, 30 Aug 2022 18:24:50 +1000 Subject: [PATCH 08/10] Fix logic error in _return_existing_view --- plugin/core/open.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/core/open.py b/plugin/core/open.py index 058463665..dfc050dc3 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -15,15 +15,16 @@ opening_files = {} # type: Dict[str, Tuple[Promise[Optional[sublime.View]], ResolveFunc[Optional[sublime.View]]]] -def _return_existing_view(flags: int, is_view_in_active_group: bool, specified_group: int) -> bool: +def _return_existing_view(flags: int, existing_view_group: int, active_group: int, specified_group: int) -> bool: # the specified_group is supplied if specified_group > -1: - return is_view_in_active_group + # use existing_view_group if it is in the specified group + return existing_view_group == specified_group # open side by side if bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)): return False - # view is in active group ( no group is specified and not side by side ) - if is_view_in_active_group: + # existing view is in active group ( no group is specified and not side by side ) + if existing_view_group == active_group: return True # Jump to the file if sublime.FORCE_GROUP is not set return not bool(flags & sublime.FORCE_GROUP) @@ -41,7 +42,7 @@ def open_file( # window.open_file brings the file to focus if it's already opened, which we don't want (unless it's supposed # to open as a separate view). view = window.find_open_file(file) - if view and _return_existing_view(flags, window.get_view_index(view)[0] == window.active_group(), group): + if view and _return_existing_view(flags, window.get_view_index(view)[0], window.active_group(), group): return Promise.resolve(view) view = window.open_file(file, flags, group) From af7d508728a6f6b398dc4b721351a7ddddc1f35a Mon Sep 17 00:00:00 2001 From: ninth-dev <4069123+ninth-dev@users.noreply.github.com> Date: Fri, 9 Sep 2022 09:22:13 +1000 Subject: [PATCH 09/10] Remove redundant comments --- plugin/core/open.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugin/core/open.py b/plugin/core/open.py index dfc050dc3..1c3a179d1 100644 --- a/plugin/core/open.py +++ b/plugin/core/open.py @@ -16,17 +16,12 @@ def _return_existing_view(flags: int, existing_view_group: int, active_group: int, specified_group: int) -> bool: - # the specified_group is supplied if specified_group > -1: - # use existing_view_group if it is in the specified group return existing_view_group == specified_group - # open side by side if bool(flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)): return False - # existing view is in active group ( no group is specified and not side by side ) if existing_view_group == active_group: return True - # Jump to the file if sublime.FORCE_GROUP is not set return not bool(flags & sublime.FORCE_GROUP) From 669108ec1e91123534bf4814ddd78d7640653316 Mon Sep 17 00:00:00 2001 From: ninth-dev <4069123+ninth-dev@users.noreply.github.com> Date: Fri, 9 Sep 2022 13:19:06 +1000 Subject: [PATCH 10/10] Close sheet preview if group is passed in --- plugin/locationpicker.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin/locationpicker.py b/plugin/locationpicker.py index 159871c46..213b56714 100644 --- a/plugin/locationpicker.py +++ b/plugin/locationpicker.py @@ -110,6 +110,12 @@ def _select_entry(self, index: int) -> None: functools.partial(open_location_async, session, location, self._side_by_side, True, self._group)) else: self._window.focus_view(self._view) + # When a group was specified close the current highlighted + # sheet upon canceling if the sheet is transient + if self._group > -1 and self._highlighted_view: + sheet = self._highlighted_view.sheet() + if sheet and sheet.is_transient(): + self._highlighted_view.close() # When in side-by-side mode close the current highlighted # sheet upon canceling if the sheet is semi-transient if self._side_by_side and self._highlighted_view: