diff --git a/boot.py b/boot.py index cabd05037..f2c088e0e 100644 --- a/boot.py +++ b/boot.py @@ -5,6 +5,7 @@ # Please keep this list sorted (Edit -> Sort Lines) from .plugin.code_actions import LspCodeActionsCommand from .plugin.code_lens import LspCodeLensCommand +from .plugin.color import LspColorPresentationCommand from .plugin.completion import LspCommitCompletionWithOppositeInsertMode from .plugin.completion import LspResolveDocsCommand from .plugin.completion import LspSelectCompletionItemCommand diff --git a/plugin/color.py b/plugin/color.py new file mode 100644 index 000000000..a450df633 --- /dev/null +++ b/plugin/color.py @@ -0,0 +1,61 @@ +from .core.edit import parse_text_edit +from .core.protocol import ColorInformation +from .core.protocol import ColorPresentation +from .core.protocol import ColorPresentationParams +from .core.protocol import Request +from .core.registry import LspTextCommand +from .core.typing import List +from .core.views import range_to_region +from .core.views import text_document_identifier +import sublime + + +class LspColorPresentationCommand(LspTextCommand): + + capability = 'colorProvider' + + def run(self, edit: sublime.Edit, color_information: ColorInformation) -> None: + session = self.best_session(self.capability) + if session: + self._version = self.view.change_count() + self._range = color_information['range'] + params = { + 'textDocument': text_document_identifier(self.view), + 'color': color_information['color'], + 'range': self._range + } # type: ColorPresentationParams + session.send_request_async(Request.colorPresentation(params, self.view), self._handle_response_async) + + def want_event(self) -> bool: + return False + + def _handle_response_async(self, response: List[ColorPresentation]) -> None: + if not response: + return + window = self.view.window() + if not window: + return + if self._version != self.view.change_count(): + return + old_text = self.view.substr(range_to_region(self._range, self.view)) + self._filtered_response = [] # type: List[ColorPresentation] + for item in response: + # Filter out items that would apply no change + text_edit = item.get('textEdit') + if text_edit: + if text_edit['range'] == self._range and text_edit['newText'] == old_text: + continue + elif item['label'] == old_text: + continue + self._filtered_response.append(item) + if self._filtered_response: + window.show_quick_panel( + [sublime.QuickPanelItem(item['label']) for item in self._filtered_response], + self._on_select, + placeholder="Change color format") + + def _on_select(self, index: int) -> None: + if index > -1: + color_pres = self._filtered_response[index] + text_edit = color_pres.get('textEdit') or {'range': self._range, 'newText': color_pres['label']} + self.view.run_command('lsp_apply_document_edit', {'changes': [parse_text_edit(text_edit, self._version)]}) diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index ab9995969..a744a119c 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -5880,6 +5880,10 @@ def codeAction(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request': def documentColor(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request': return Request('textDocument/documentColor', params, view) + @classmethod + def colorPresentation(cls, params: ColorPresentationParams, view: sublime.View) -> 'Request': + return Request('textDocument/colorPresentation', params, view) + @classmethod def willSaveWaitUntil(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request': return Request("textDocument/willSaveWaitUntil", params, view) diff --git a/plugin/core/views.py b/plugin/core/views.py index 23c77c044..91f068c67 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -4,6 +4,8 @@ from .protocol import CodeActionContext from .protocol import CodeActionParams from .protocol import CodeActionTriggerKind +from .protocol import Color +from .protocol import ColorInformation from .protocol import Command from .protocol import CompletionItem from .protocol import CompletionItemKind @@ -781,28 +783,44 @@ def run(self, view_id: int, command: str, args: Optional[Dict[str, Any]] = None) COLOR_BOX_HTML = """ - +
-