Skip to content

Commit

Permalink
Add support for multi-range formatting (#2299)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwortmann authored Aug 6, 2023
1 parent 61ed50b commit 1ac2b3e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
3 changes: 2 additions & 1 deletion plugin/core/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor
"dynamicRegistration": True # exceptional
},
"rangeFormatting": {
"dynamicRegistration": True
"dynamicRegistration": True,
"rangesSupport": True
},
"declaration": {
"dynamicRegistration": True,
Expand Down
8 changes: 8 additions & 0 deletions plugin/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,14 @@ def text_document_range_formatting(view: sublime.View, region: sublime.Region) -
}, view, progress=True)


def text_document_ranges_formatting(view: sublime.View) -> Request:
return Request("textDocument/rangesFormatting", {
"textDocument": text_document_identifier(view),
"options": formatting_options(view.settings()),
"ranges": [region_to_range(view, region) for region in view.sel() if not region.empty()]
}, view, progress=True)


def selection_range_params(view: sublime.View) -> SelectionRangeParams:
return {
"textDocument": text_document_identifier(view),
Expand Down
39 changes: 30 additions & 9 deletions plugin/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .core.views import has_single_nonempty_selection
from .core.views import text_document_formatting
from .core.views import text_document_range_formatting
from .core.views import text_document_ranges_formatting
from .core.views import will_save_wait_until
from .save_command import LspSaveCommand, SaveTask
import sublime
Expand Down Expand Up @@ -115,16 +116,27 @@ class LspFormatDocumentRangeCommand(LspTextCommand):
capability = 'documentRangeFormattingProvider'

def is_enabled(self, event: Optional[dict] = None, point: Optional[int] = None) -> bool:
if super().is_enabled(event, point):
return has_single_nonempty_selection(self.view)
if not super().is_enabled(event, point):
return False
if has_single_nonempty_selection(self.view):
return True
if self.view.has_non_empty_selection_region() and \
bool(self.best_session('documentRangeFormattingProvider.rangesSupport')):
return True
return False

def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
session = self.best_session(self.capability)
selection = first_selection_region(self.view)
if session and selection is not None:
req = text_document_range_formatting(self.view, selection)
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))
if has_single_nonempty_selection(self.view):
session = self.best_session(self.capability)
selection = first_selection_region(self.view)
if session and selection is not None:
req = text_document_range_formatting(self.view, selection)
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))
elif self.view.has_non_empty_selection_region():
session = self.best_session('documentRangeFormattingProvider.rangesSupport')
if session:
req = text_document_ranges_formatting(self.view)
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))


class LspFormatCommand(LspTextCommand):
Expand All @@ -139,11 +151,20 @@ def is_visible(self, event: Optional[dict] = None, point: Optional[int] = None)
return self.is_enabled(event, point)

def description(self, **kwargs) -> str:
return "Format Selection" if self._range_formatting_available() else "Format File"
if self._range_formatting_available():
if has_single_nonempty_selection(self.view):
return "Format Selection"
return "Format Selections"
return "Format File"

def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
command = 'lsp_format_document_range' if self._range_formatting_available() else 'lsp_format_document'
self.view.run_command(command)

def _range_formatting_available(self) -> bool:
return has_single_nonempty_selection(self.view) and bool(self.best_session('documentRangeFormattingProvider'))
if has_single_nonempty_selection(self.view) and bool(self.best_session('documentRangeFormattingProvider')):
return True
if self.view.has_non_empty_selection_region() and \
bool(self.best_session('documentRangeFormattingProvider.rangesSupport')):
return True
return False

0 comments on commit 1ac2b3e

Please sign in to comment.