Skip to content

Commit 1ac2b3e

Browse files
authored
Add support for multi-range formatting (#2299)
1 parent 61ed50b commit 1ac2b3e

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

plugin/core/sessions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor
334334
"dynamicRegistration": True # exceptional
335335
},
336336
"rangeFormatting": {
337-
"dynamicRegistration": True
337+
"dynamicRegistration": True,
338+
"rangesSupport": True
338339
},
339340
"declaration": {
340341
"dynamicRegistration": True,

plugin/core/views.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,14 @@ def text_document_range_formatting(view: sublime.View, region: sublime.Region) -
592592
}, view, progress=True)
593593

594594

595+
def text_document_ranges_formatting(view: sublime.View) -> Request:
596+
return Request("textDocument/rangesFormatting", {
597+
"textDocument": text_document_identifier(view),
598+
"options": formatting_options(view.settings()),
599+
"ranges": [region_to_range(view, region) for region in view.sel() if not region.empty()]
600+
}, view, progress=True)
601+
602+
595603
def selection_range_params(view: sublime.View) -> SelectionRangeParams:
596604
return {
597605
"textDocument": text_document_identifier(view),

plugin/formatting.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .core.views import has_single_nonempty_selection
1313
from .core.views import text_document_formatting
1414
from .core.views import text_document_range_formatting
15+
from .core.views import text_document_ranges_formatting
1516
from .core.views import will_save_wait_until
1617
from .save_command import LspSaveCommand, SaveTask
1718
import sublime
@@ -115,16 +116,27 @@ class LspFormatDocumentRangeCommand(LspTextCommand):
115116
capability = 'documentRangeFormattingProvider'
116117

117118
def is_enabled(self, event: Optional[dict] = None, point: Optional[int] = None) -> bool:
118-
if super().is_enabled(event, point):
119-
return has_single_nonempty_selection(self.view)
119+
if not super().is_enabled(event, point):
120+
return False
121+
if has_single_nonempty_selection(self.view):
122+
return True
123+
if self.view.has_non_empty_selection_region() and \
124+
bool(self.best_session('documentRangeFormattingProvider.rangesSupport')):
125+
return True
120126
return False
121127

122128
def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
123-
session = self.best_session(self.capability)
124-
selection = first_selection_region(self.view)
125-
if session and selection is not None:
126-
req = text_document_range_formatting(self.view, selection)
127-
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))
129+
if has_single_nonempty_selection(self.view):
130+
session = self.best_session(self.capability)
131+
selection = first_selection_region(self.view)
132+
if session and selection is not None:
133+
req = text_document_range_formatting(self.view, selection)
134+
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))
135+
elif self.view.has_non_empty_selection_region():
136+
session = self.best_session('documentRangeFormattingProvider.rangesSupport')
137+
if session:
138+
req = text_document_ranges_formatting(self.view)
139+
session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view))
128140

129141

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

141153
def description(self, **kwargs) -> str:
142-
return "Format Selection" if self._range_formatting_available() else "Format File"
154+
if self._range_formatting_available():
155+
if has_single_nonempty_selection(self.view):
156+
return "Format Selection"
157+
return "Format Selections"
158+
return "Format File"
143159

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

148164
def _range_formatting_available(self) -> bool:
149-
return has_single_nonempty_selection(self.view) and bool(self.best_session('documentRangeFormattingProvider'))
165+
if has_single_nonempty_selection(self.view) and bool(self.best_session('documentRangeFormattingProvider')):
166+
return True
167+
if self.view.has_non_empty_selection_region() and \
168+
bool(self.best_session('documentRangeFormattingProvider.rangesSupport')):
169+
return True
170+
return False

0 commit comments

Comments
 (0)