diff --git a/plugin/code_lens.py b/plugin/code_lens.py index 778d3b7f5..af006b299 100644 --- a/plugin/code_lens.py +++ b/plugin/code_lens.py @@ -196,10 +196,11 @@ def render(self, mode: str) -> None: self._phantom.update(phantoms) else: # 'annotation' self._clear_annotations() + flags = sublime.NO_UNDO accent = self.view.style_for_scope("region.greenish markup.accent.codelens.lsp")["foreground"] for index, lens in enumerate(self._flat_iteration()): self.view.add_regions( - self._region_key(lens.session_name, index), [lens.region], "", "", 0, [lens.small_html], accent) + self._region_key(lens.session_name, index), [lens.region], "", "", flags, [lens.small_html], accent) def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLensExtended, None, None]: region = self.view.line(region) diff --git a/plugin/core/constants.py b/plugin/core/constants.py index efe2753b8..2a1fa9dec 100644 --- a/plugin/core/constants.py +++ b/plugin/core/constants.py @@ -19,6 +19,11 @@ HOVER_PROVIDER_COUNT_KEY = 'lsp_hover_provider_count' SHOW_DEFINITIONS_KEY = 'show_definitions' +# Region flags +DOCUMENT_LINK_FLAGS = sublime.HIDE_ON_MINIMAP | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE | sublime.NO_UNDO # noqa: E501 +REGIONS_INITIALIZE_FLAGS = sublime.HIDDEN | sublime.NO_UNDO +SEMANTIC_TOKEN_FLAGS = sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO + # sublime.Kind tuples for sublime.CompletionItem, sublime.QuickPanelItem, sublime.ListInputItem # https://www.sublimetext.com/docs/api_reference.html#sublime.Kind KIND_ARRAY = (sublime.KIND_ID_TYPE, "a", "Array") diff --git a/plugin/core/types.py b/plugin/core/types.py index 555e68b7f..7fac717c2 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -320,31 +320,33 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None: set_debug_logging(self.log_debug) def highlight_style_region_flags(self, style_str: str) -> Tuple[int, int]: + default = sublime.NO_UNDO if style_str in ("background", "fill"): # Backwards-compatible with "fill" - return sublime.DRAW_NO_OUTLINE, sublime.DRAW_NO_OUTLINE - elif style_str == "outline": - return sublime.DRAW_NO_FILL, sublime.DRAW_NO_FILL - elif style_str == "stippled": - return sublime.DRAW_NO_FILL, sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_STIPPLED_UNDERLINE # noqa: E501 - else: - return sublime.DRAW_NO_FILL, sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE # noqa: E501 + style = default | sublime.DRAW_NO_OUTLINE + return style, style + if style_str == "outline": + style = default | sublime.DRAW_NO_FILL + return style, style + if style_str == "stippled": + return default | sublime.DRAW_NO_FILL, default | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_STIPPLED_UNDERLINE # noqa: E501 + return default | sublime.DRAW_NO_FILL, default | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE # noqa: E501 @staticmethod def _style_str_to_flag(style_str: str) -> Optional[int]: + default = sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL | sublime.NO_UNDO # This method could be a dict or lru_cache if style_str == "": - return sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE - elif style_str == "box": - return sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL - elif style_str == "underline": - return sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE # noqa: E501 - elif style_str == "stippled": - return sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_STIPPLED_UNDERLINE # noqa: E501 - elif style_str == "squiggly": - return sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SQUIGGLY_UNDERLINE # noqa: E501 - else: - # default style - return None + return default | sublime.DRAW_NO_OUTLINE + if style_str == "box": + return default + if style_str == "underline": + return default | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE + if style_str == "stippled": + return default | sublime.DRAW_NO_OUTLINE | sublime.DRAW_STIPPLED_UNDERLINE + if style_str == "squiggly": + return default | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SQUIGGLY_UNDERLINE + # default style (includes NO_UNDO) + return None def diagnostics_highlight_style_flags(self) -> List[Optional[int]]: """Returns flags for highlighting diagnostics on single lines per severity""" diff --git a/plugin/core/views.py b/plugin/core/views.py index 5ad99163e..060de4264 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -53,16 +53,15 @@ MarkdownLangMap = Dict[str, Tuple[Tuple[str, ...], Tuple[str, ...]]] -DOCUMENT_LINK_FLAGS = sublime.HIDE_ON_MINIMAP | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE # noqa: E501 - -_baseflags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_EMPTY_AS_OVERWRITE +_baseflags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.NO_UNDO +_multilineflags = sublime.DRAW_NO_FILL | sublime.NO_UNDO DIAGNOSTIC_SEVERITY = [ # Kind CSS class Scope for color Icon resource add_regions flags for single-line diagnostic multi-line diagnostic # noqa: E501 - ("error", "errors", "region.redish markup.error.lsp", "Packages/LSP/icons/error.png", _baseflags | sublime.DRAW_SQUIGGLY_UNDERLINE, sublime.DRAW_NO_FILL), # noqa: E501 - ("warning", "warnings", "region.yellowish markup.warning.lsp", "Packages/LSP/icons/warning.png", _baseflags | sublime.DRAW_SQUIGGLY_UNDERLINE, sublime.DRAW_NO_FILL), # noqa: E501 - ("info", "info", "region.bluish markup.info.lsp", "Packages/LSP/icons/info.png", _baseflags | sublime.DRAW_STIPPLED_UNDERLINE, sublime.DRAW_NO_FILL), # noqa: E501 - ("hint", "hints", "region.bluish markup.info.hint.lsp", "", _baseflags | sublime.DRAW_STIPPLED_UNDERLINE, sublime.DRAW_NO_FILL), # noqa: E501 + ("error", "errors", "region.redish markup.error.lsp", "Packages/LSP/icons/error.png", _baseflags | sublime.DRAW_SQUIGGLY_UNDERLINE, _multilineflags), # noqa: E501 + ("warning", "warnings", "region.yellowish markup.warning.lsp", "Packages/LSP/icons/warning.png", _baseflags | sublime.DRAW_SQUIGGLY_UNDERLINE, _multilineflags), # noqa: E501 + ("info", "info", "region.bluish markup.info.lsp", "Packages/LSP/icons/info.png", _baseflags | sublime.DRAW_STIPPLED_UNDERLINE, _multilineflags), # noqa: E501 + ("hint", "hints", "region.bluish markup.info.hint.lsp", "", _baseflags | sublime.DRAW_STIPPLED_UNDERLINE, _multilineflags), # noqa: E501 ] # type: List[Tuple[str, str, str, str, int, int]] diff --git a/plugin/diagnostics.py b/plugin/diagnostics.py index 0e0ea5831..8b6448a3a 100644 --- a/plugin/diagnostics.py +++ b/plugin/diagnostics.py @@ -1,4 +1,5 @@ from .core.constants import DIAGNOSTIC_KINDS +from .core.constants import REGIONS_INITIALIZE_FLAGS from .core.protocol import Diagnostic from .core.protocol import DiagnosticSeverity from .core.settings import userprefs @@ -17,13 +18,13 @@ def __init__(self, view: sublime.View, config_name: str) -> None: def initialize_region_keys(self) -> None: r = [sublime.Region(0, 0)] for severity in DIAGNOSTIC_KINDS.keys(): - self._view.add_regions(self._annotation_region_key(severity), r) + self._view.add_regions(self._annotation_region_key(severity), r, flags=REGIONS_INITIALIZE_FLAGS) def _annotation_region_key(self, severity: DiagnosticSeverity) -> str: return 'lsp_da-{}-{}'.format(severity, self._config_name) def draw(self, diagnostics: List[Tuple[Diagnostic, sublime.Region]]) -> None: - flags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE + flags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO max_severity_level = userprefs().show_diagnostics_annotations_severity_level # To achieve the correct order of annotations (most severe having priority) we have to add regions from the # most to the least severe. diff --git a/plugin/documents.py b/plugin/documents.py index a3b3188fb..49653a875 100644 --- a/plugin/documents.py +++ b/plugin/documents.py @@ -695,7 +695,7 @@ def _on_code_actions(self, responses: List[CodeActionsByConfigName]) -> None: regions = [sublime.Region(region.b, region.a)] scope = "" icon = "" - flags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE + flags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO annotations = [] annotation_color = "" if userprefs().show_code_actions == 'bulb': diff --git a/plugin/references.py b/plugin/references.py index ecae586a5..df6073c79 100644 --- a/plugin/references.py +++ b/plugin/references.py @@ -190,7 +190,7 @@ def _show_references_in_output_panel(self, word: str, session: Session, location }) # highlight all word occurrences regions = panel.find_all(r"\b{}\b".format(word)) - panel.add_regions('ReferenceHighlight', regions, 'comment', flags=sublime.DRAW_NO_FILL) + panel.add_regions('ReferenceHighlight', regions, 'comment', flags=sublime.DRAW_NO_FILL | sublime.NO_UNDO) def _get_relative_path(base_dir: Optional[str], file_path: str) -> str: diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 2012b97c7..be61df511 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -1,3 +1,5 @@ +from .core.constants import DOCUMENT_LINK_FLAGS +from .core.constants import SEMANTIC_TOKEN_FLAGS from .core.protocol import ColorInformation from .core.protocol import Diagnostic from .core.protocol import DocumentDiagnosticParams @@ -34,7 +36,6 @@ from .core.views import did_open from .core.views import did_save from .core.views import document_color_params -from .core.views import DOCUMENT_LINK_FLAGS from .core.views import entire_content_range from .core.views import lsp_color_to_phantom from .core.views import MissingUriError @@ -668,7 +669,7 @@ def _draw_semantic_tokens_async(self) -> None: if region_key not in self.semantic_tokens.active_region_keys: self.semantic_tokens.active_region_keys.add(region_key) for sv in self.session_views: - sv.view.add_regions("lsp_semantic_{}".format(region_key), regions, scope, flags=sublime.DRAW_NO_OUTLINE) + sv.view.add_regions("lsp_semantic_{}".format(region_key), regions, scope, flags=SEMANTIC_TOKEN_FLAGS) def _get_semantic_region_key_for_scope(self, scope: str) -> int: if scope not in self._semantic_region_keys: diff --git a/plugin/session_view.py b/plugin/session_view.py index addfd68ae..2db34f094 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -5,6 +5,7 @@ from .core.constants import HOVER_ENABLED_KEY from .core.constants import HOVER_HIGHLIGHT_KEY from .core.constants import HOVER_PROVIDER_COUNT_KEY +from .core.constants import REGIONS_INITIALIZE_FLAGS from .core.constants import SHOW_DEFINITIONS_KEY from .core.promise import Promise from .core.protocol import CodeLens @@ -133,36 +134,39 @@ def _initialize_region_keys(self) -> None: - gutter icons from region keys which were initialized _first_ are drawn For more context, see https://github.com/sublimelsp/LSP/issues/1593. """ + keys = [] # type: List[str] r = [sublime.Region(0, 0)] document_highlight_style = userprefs().document_highlight_style hover_highlight_style = userprefs().hover_highlight_style line_modes = ["m", "s"] self.view.add_regions(self.CODE_ACTIONS_KEY, r) # code actions lightbulb icon should always be on top for key in range(1, 100): - self.view.add_regions("lsp_semantic_{}".format(key), r) + keys.append("lsp_semantic_{}".format(key)) if document_highlight_style in ("background", "fill"): for kind in DOCUMENT_HIGHLIGHT_KIND_NAMES.values(): for mode in line_modes: - self.view.add_regions("lsp_highlight_{}{}".format(kind, mode), r) + keys.append("lsp_highlight_{}{}".format(kind, mode)) if hover_highlight_style in ("background", "fill"): - self.view.add_regions(HOVER_HIGHLIGHT_KEY, r) + keys.append(HOVER_HIGHLIGHT_KEY) for severity in range(1, 5): for mode in line_modes: for tag in range(1, 3): - self.view.add_regions("lsp{}d{}{}_tags_{}".format(self.session.config.name, mode, severity, tag), r) - self.view.add_regions("lsp_document_link", r) + keys.append("lsp{}d{}{}_tags_{}".format(self.session.config.name, mode, severity, tag)) + keys.append("lsp_document_link") for severity in range(1, 5): for mode in line_modes: - self.view.add_regions("lsp{}d{}{}_icon".format(self.session.config.name, mode, severity), r) + keys.append("lsp{}d{}{}_icon".format(self.session.config.name, mode, severity)) for severity in range(4, 0, -1): for mode in line_modes: - self.view.add_regions("lsp{}d{}{}_underline".format(self.session.config.name, mode, severity), r) + keys.append("lsp{}d{}{}_underline".format(self.session.config.name, mode, severity)) if document_highlight_style in ("underline", "stippled"): for kind in DOCUMENT_HIGHLIGHT_KIND_NAMES.values(): for mode in line_modes: - self.view.add_regions("lsp_highlight_{}{}".format(kind, mode), r) + keys.append("lsp_highlight_{}{}".format(kind, mode)) if hover_highlight_style in ("underline", "stippled"): - self.view.add_regions(HOVER_HIGHLIGHT_KEY, r) + keys.append(HOVER_HIGHLIGHT_KEY) + for key in keys: + self.view.add_regions(key, r, flags=REGIONS_INITIALIZE_FLAGS) self._diagnostic_annotations.initialize_region_keys() def _clear_auto_complete_triggers(self, settings: sublime.Settings) -> None: @@ -300,7 +304,7 @@ def present_diagnostics_async( self, is_view_visible: bool, data_per_severity: Dict[Tuple[int, bool], DiagnosticSeverityData] ) -> None: flags = userprefs().diagnostics_highlight_style_flags() # for single lines - multiline_flags = None if userprefs().show_multiline_diagnostics_highlights else sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE # noqa: E501 + multiline_flags = None if userprefs().show_multiline_diagnostics_highlights else sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO # noqa: E501 level = userprefs().show_diagnostics_severity_level for sev in reversed(range(1, len(DIAGNOSTIC_SEVERITY) + 1)): self._draw_diagnostics( @@ -320,7 +324,7 @@ def _draw_diagnostics( flags: int, multiline: bool ) -> None: - ICON_FLAGS = sublime.HIDE_ON_MINIMAP | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE + ICON_FLAGS = sublime.HIDE_ON_MINIMAP | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO key = self.diagnostics_key(severity, multiline) tags = {tag: TagData('{}_tags_{}'.format(key, tag)) for tag in DIAGNOSTIC_TAG_VALUES} data = data_per_severity.get((severity, multiline)) @@ -341,7 +345,8 @@ def _draw_diagnostics( self.view.erase_regions("{}_underline".format(key)) for data in tags.values(): if data.regions: - self.view.add_regions(data.key, data.regions, data.scope, flags=sublime.DRAW_NO_OUTLINE) + self.view.add_regions( + data.key, data.regions, data.scope, flags=sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO) else: self.view.erase_regions(data.key)