From ba7a991f3dbd2c0a67285a2e81c847b41de6e023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ch=C5=82odnicki?= Date: Thu, 4 Jan 2024 20:57:09 +0100 Subject: [PATCH] feat: implement custom join lines command/keybinding (#110) --- Default.sublime-keymap | 9 +++++ LSP-rust-analyzer.sublime-commands | 4 +++ README.md | 6 ++++ plugin_commands.py | 56 ++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 Default.sublime-keymap create mode 100644 plugin_commands.py diff --git a/Default.sublime-keymap b/Default.sublime-keymap new file mode 100644 index 0000000..8a03987 --- /dev/null +++ b/Default.sublime-keymap @@ -0,0 +1,9 @@ +[ + { + "keys": ["primary+shift+j"], + "command": "rust_analyzer_join_lines", + "context": [ + {"key": "lsp.session_with_name", "operand": "rust-analyzer"} + ] + }, +] diff --git a/LSP-rust-analyzer.sublime-commands b/LSP-rust-analyzer.sublime-commands index 008ec9b..2569b93 100644 --- a/LSP-rust-analyzer.sublime-commands +++ b/LSP-rust-analyzer.sublime-commands @@ -7,6 +7,10 @@ "default": "// Settings in here override those in \"LSP-rust-analyzer/LSP-rust-analyzer.sublime-settings\"\n{\n\t$0\n}\n" } }, + { + "caption": "LSP-rust-analyzer: Join Lines", + "command": "rust_analyzer_join_lines" + }, { "caption": "LSP-rust-analyzer: Open Docs Under Cursor", "command": "rust_analyzer_open_docs" diff --git a/README.md b/README.md index 98a525e..c7f595c 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,12 @@ Select a cargo command from the submenu. This spawns a shell with [Terminus](htt ![Example](./images/commands.gif) +### LSP-rust-analyzer: Join Lines + +Joins lines accounting for rust-specific logic. + +Also bound to the default join-lines key binding (ctrlshiftj or commandshiftj on Windows/Linux and Mac respectively). + ### LSP-rust-analyzer: Open Docs Under Cursor Opens the URL to documentation for the symbol under the cursor, if available. diff --git a/plugin_commands.py b/plugin_commands.py new file mode 100644 index 0000000..b6ead16 --- /dev/null +++ b/plugin_commands.py @@ -0,0 +1,56 @@ +from .plugin import RustAnalyzerCommand +from LSP.plugin import Request +from LSP.plugin.core.protocol import Error +from LSP.plugin.core.protocol import Range +from LSP.plugin.core.protocol import TextDocumentIdentifier +from LSP.plugin.core.protocol import TextEdit +from LSP.plugin.core.typing import List, TypedDict, Union +from LSP.plugin.core.views import region_to_range +from LSP.plugin.core.views import text_document_identifier +from LSP.plugin.formatting import apply_text_edits_to_view +import sublime + + +class JoinLinesRequest: + Type = 'experimental/joinLines' + ParamsType = TypedDict('ParamsType', { + 'textDocument': TextDocumentIdentifier, + 'ranges': List[Range], + }) + ReturnType = List[TextEdit] + + +class RustAnalyzerJoinLinesCommand(RustAnalyzerCommand): + + def run(self, edit: sublime.Edit) -> None: + sublime.set_timeout_async(self.make_request_async) + + def make_request_async(self) -> None: + session = self.session_by_name(self.session_name) + if session is None: + return + session_view = session.session_view_for_view_async(self.view) + if not session_view: + return + view_listener = session_view.listener() + if not view_listener: + return + params = { + 'textDocument': text_document_identifier(self.view), + 'ranges': [region_to_range(self.view, region) for region in self.view.sel()], + } # type: JoinLinesRequest.ParamsType + request = Request(JoinLinesRequest.Type, params) # type: Request[JoinLinesRequest.ReturnType] + document_version = self.view.change_count() + view_listener.purge_changes_async() + session.send_request_task(request).then(lambda result: self.on_result_async(result, document_version)) + + def on_result_async(self, edits: Union[JoinLinesRequest.ReturnType, Error], document_version: int) -> None: + if document_version != self.view.change_count(): + return + if isinstance(edits, Error): + print('[{}] Error handling the "{}" request. Falling back to native join.'.format( + self.session_name, JoinLinesRequest.Type)) + self.view.run_command('join_lines') + return + if edits: + apply_text_edits_to_view(edits, self.view)