From 69f8ca85ee0caf256be1938c96285119ce997a71 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Tue, 28 Nov 2023 00:27:26 +0100 Subject: [PATCH 01/11] Improve type stubs --- stubs/sublime.pyi | 163 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 122 insertions(+), 41 deletions(-) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index 769213c91..65057817d 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -1,48 +1,83 @@ -# Stubs for sublime (Python 3.5) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. - -from typing import Any, Callable, Dict, Iterator, List, Optional, Reversible, Sequence, Tuple, Union - - -class _LogWriter: - def flush(self) -> None: - ... - - def write(self, s: str) -> None: - ... +# Stubs for sublime.py (Python 3.3 API Environment) +from typing import Any, Callable, Dict, Iterator, List, Literal, Optional, Reversible, Sequence, Tuple, Union HOVER_TEXT = ... # type: int +"""The mouse is hovered over the text.""" HOVER_GUTTER = ... # type: int +"""The mouse is hovered over the gutter.""" HOVER_MARGIN = ... # type: int +"""The mouse is hovered in the white space to the right of a line.""" + ENCODED_POSITION = ... # type: int +"""Indicates that the file name should be searched for a `:row` or `:row:col` suffix.""" TRANSIENT = ... # type: int -SEMI_TRANSIENT = ... # type: int +"""Open the file as a preview only: it won't have a tab assigned it until modified.""" FORCE_GROUP = ... # type: int +"""Don't select the file if it is open in a different group. Instead make a new clone of that file in the desired group.""" +SEMI_TRANSIENT = ... # type: int +"""If a sheet is newly created, it will be set to semi-transient. Semi-transient sheets generally replace other semi-transient sheets. This is used for the side-bar preview. Only valid with `ADD_TO_SELECTION` or `REPLACE_MRU`.""" ADD_TO_SELECTION = ... # type: int +"""Add the file to the currently selected sheets in the group.""" REPLACE_MRU = ... # type: int +"""Causes the sheet to replace the most-recently used sheet in the current sheet selection.""" CLEAR_TO_RIGHT = ... # type: int -IGNORECASE = ... # type: int +"""All currently selected sheets to the right of the most-recently used sheet will be unselected before opening the file. Only valid in combination with `ADD_TO_SELECTION`.""" +FORCE_CLONE = ... # type: int +"""Don't select the file if it is open. Instead make a new clone of that file in the desired group.""" + LITERAL = ... # type: int +"""Whether the find pattern should be matched literally or as a regex.""" +IGNORECASE = ... # type: int +"""Whether case should be considered when matching the find pattern.""" +WHOLEWORD = ... # type: int +"""Whether to only match whole words.""" +REVERSE = ... # type: int +"""Whether to search backwards.""" +WRAP = ... # type: int +"""Whether to wrap around once the end is reached.""" + MONOSPACE_FONT = ... # type: int +"""Use a monospace font.""" KEEP_OPEN_ON_FOCUS_LOST = ... # type: int +"""Keep the quick panel open if the window loses input focus.""" +WANT_EVENT = ... # type: int +"""Pass a second parameter to the `on_done` callback, a `Event`.""" + HTML = ... # type: int COOPERATE_WITH_AUTO_COMPLETE = ... # type: int +"""Causes the popup to display next to the auto complete menu.""" HIDE_ON_MOUSE_MOVE = ... # type: int +"""Causes the popup to hide when the mouse is moved, clicked or scrolled.""" HIDE_ON_MOUSE_MOVE_AWAY = ... # type: int +"""Causes the popup to hide when the mouse is moved (unless towards the popup), or when clicked or scrolled.""" KEEP_ON_SELECTION_MODIFIED = ... # type: int +"""Prevent the popup from hiding when the selection is modified.""" +HIDE_ON_CHARACTER_EVENT = ... # type: int +"""Hide the popup when a character is typed.""" + DRAW_EMPTY = ... # type: int +"""Draw empty regions with a vertical bar. By default, they aren't drawn at all.""" HIDE_ON_MINIMAP = ... # type: int +"""Don't show the regions on the minimap.""" DRAW_EMPTY_AS_OVERWRITE = ... # type: int +"""Draw empty regions with a horizontal bar instead of a vertical one.""" PERSISTENT = ... # type: int -DRAW_OUTLINED = ... # type: int +"""Save the regions in the session.""" DRAW_NO_FILL = ... # type: int +"""Disable filling the regions, leaving only the outline.""" +HIDDEN = ... # type: int +"""Don't draw the regions.""" DRAW_NO_OUTLINE = ... # type: int +"""Disable drawing the outline of the regions.""" DRAW_SOLID_UNDERLINE = ... # type: int +"""Draw a solid underline below the regions.""" DRAW_STIPPLED_UNDERLINE = ... # type: int +"""Draw a stippled underline below the regions.""" DRAW_SQUIGGLY_UNDERLINE = ... # type: int -HIDDEN = ... # type: int +"""Draw a squiggly underline below the regions.""" +NO_UNDO = ... # type: int + OP_EQUAL = ... # type: int OP_NOT_EQUAL = ... # type: int OP_REGEX_MATCH = ... # type: int @@ -50,51 +85,65 @@ OP_NOT_REGEX_MATCH = ... # type: int OP_REGEX_CONTAINS = ... # type: int OP_NOT_REGEX_CONTAINS = ... # type: int CLASS_WORD_START = ... # type: int +"""The point is the start of a word.""" CLASS_WORD_END = ... # type: int +"""The point is the end of a word.""" CLASS_PUNCTUATION_START = ... # type: int +"""The point is the start of a sequence of punctuation characters.""" CLASS_PUNCTUATION_END = ... # type: int +"""The point is the end of a sequence of punctuation characters.""" CLASS_SUB_WORD_START = ... # type: int +"""The point is the start of a sub-word.""" CLASS_SUB_WORD_END = ... # type: int +"""The point is the end of a sub-word.""" CLASS_LINE_START = ... # type: int +"""The point is the start of a line.""" CLASS_LINE_END = ... # type: int +"""The point is the end of a line.""" CLASS_EMPTY_LINE = ... # type: int +"""The point is an empty line.""" + INHIBIT_WORD_COMPLETIONS = ... # type: int +"""Prevent Sublime Text from showing completions based on the contents of the view.""" INHIBIT_EXPLICIT_COMPLETIONS = ... # type: int -INHIBIT_REORDER = ... # type: int +"""Prevent Sublime Text from showing completions based on `.sublime-completions` files.""" DYNAMIC_COMPLETIONS = ... # type: int -COMPLETION_FLAG_KEEP_PREFIX = ... # type: int -COMPLETION_FORMAT_COMMAND = ... # type: int +"""If completions should be re-queried as the user types.""" +INHIBIT_REORDER = ... # type: int +"""Prevent Sublime Text from changing the completion order.""" + DIALOG_CANCEL = ... # type: int DIALOG_YES = ... # type: int DIALOG_NO = ... # type: int -UI_ELEMENT_SIDE_BAR = ... # type: int -UI_ELEMENT_MINIMAP = ... # type: int -UI_ELEMENT_TABS = ... # type: int -UI_ELEMENT_STATUS_BAR = ... # type: int -UI_ELEMENT_MENU = ... # type: int -UI_ELEMENT_OPEN_FILES = ... # type: int + LAYOUT_INLINE = ... # type: int +"""The phantom is positioned inline with the text at the beginning of its `Region`.""" LAYOUT_BELOW = ... # type: int +"""The phantom is positioned below the line, left-aligned with the beginning of its `Region`.""" LAYOUT_BLOCK = ... # type: int +"""The phantom is positioned below the line, left-aligned with the beginning of the line.""" + KIND_ID_AMBIGUOUS = ... # type: int KIND_ID_KEYWORD = ... # type: int KIND_ID_TYPE = ... # type: int -KIND_ID_COLOR_DARK = ... # type: int -KIND_ID_COLOR_LIGHT = ... # type: int -KIND_ID_COLOR_BLUISH = ... # type: int -KIND_ID_COLOR_CYANISH = ... # type: int -KIND_ID_COLOR_GREENISH = ... # type: int -KIND_ID_COLOR_ORANGISH = ... # type: int -KIND_ID_COLOR_PINKISH = ... # type: int -KIND_ID_COLOR_PURPLISH = ... # type: int -KIND_ID_COLOR_REDISH = ... # type: int -KIND_ID_COLOR_YELLOWISH = ... # type: int KIND_ID_FUNCTION = ... # type: int KIND_ID_NAMESPACE = ... # type: int KIND_ID_NAVIGATION = ... # type: int KIND_ID_MARKUP = ... # type: int KIND_ID_VARIABLE = ... # type: int KIND_ID_SNIPPET = ... # type: int + +KIND_ID_COLOR_REDISH = ... # type: int +KIND_ID_COLOR_ORANGISH = ... # type: int +KIND_ID_COLOR_YELLOWISH = ... # type: int +KIND_ID_COLOR_GREENISH = ... # type: int +KIND_ID_COLOR_CYANISH = ... # type: int +KIND_ID_COLOR_BLUISH = ... # type: int +KIND_ID_COLOR_PURPLISH = ... # type: int +KIND_ID_COLOR_PINKISH = ... # type: int +KIND_ID_COLOR_DARK = ... # type: int +KIND_ID_COLOR_LIGHT = ... # type: int + KIND_AMBIGUOUS = ... # type: Tuple[int, str, str] KIND_KEYWORD = ... # type: Tuple[int, str, str] KIND_TYPE = ... # type: Tuple[int, str, str] @@ -104,9 +153,29 @@ KIND_NAVIGATION = ... # type: Tuple[int, str, str] KIND_MARKUP = ... # type: Tuple[int, str, str] KIND_VARIABLE = ... # type: Tuple[int, str, str] KIND_SNIPPET = ... # type: Tuple[int, str, str] + +SYMBOL_SOURCE_ANY = ... # type: int +"""Use any source - both the index and open files.""" +SYMBOL_SOURCE_INDEX = ... # type: int +"""Use the index created when scanning through files in a project folder.""" +SYMBOL_SOURCE_OPEN_FILES = ... # type: int +"""Use the open files, unsaved or otherwise.""" + +SYMBOL_TYPE_ANY = ... # type: int +"""Any symbol type - both definitions and references.""" +SYMBOL_TYPE_DEFINITION = ... # type: int +"""Only definitions.""" +SYMBOL_TYPE_REFERENCE = ... # type: int +"""Only references.""" + COMPLETION_FORMAT_TEXT = ... # type: int +"""Plain text, upon completing the text is inserted verbatim.""" COMPLETION_FORMAT_SNIPPET = ... # type: int -WANT_EVENT = ... # type: int +"""A snippet, with `$` variables.""" +COMPLETION_FORMAT_COMMAND = ... # type: int +"""A command string, in the format returned by `format_command()`.""" + +COMPLETION_FLAG_KEEP_PREFIX = ... # type: int class Settings: @@ -135,50 +204,62 @@ class Settings: def version() -> str: + """The version number.""" ... -def platform() -> str: +def platform() -> Literal["osx", "linux", "windows"]: + """The platform which the plugin is being run on.""" ... -def arch() -> str: +def arch() -> Literal["x32", "x64", "arm64"]: + """The CPU architecture.""" ... -def channel() -> str: +def channel() -> Literal["dev", "stable"]: + """The release channel of this build of Sublime Text.""" ... def executable_path() -> str: + """The path to the main Sublime Text executable.""" ... -def executable_hash() -> str: +def executable_hash() -> Tuple[str, str, str]: + """A tuple uniquely identifying the installation of Sublime Text.""" ... def packages_path() -> str: + """The path to the "Packages" folder.""" ... def installed_packages_path() -> str: + """The path to the "Installed Packages" folder.""" ... def cache_path() -> str: + """The path where Sublime Text stores cache files.""" ... def status_message(msg: str) -> None: + """Show a message in the status bar.""" ... def error_message(msg: str) -> None: + """Display an error dialog.""" ... def message_dialog(msg: str) -> None: + """Display a message dialog.""" ... From 4233edba8659cda7daba0cd4241f5b99d6d005ff Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Fri, 1 Dec 2023 17:21:44 +0100 Subject: [PATCH 02/11] Improve type stubs for sublime.py --- plugin/core/configurations.py | 3 +- plugin/documents.py | 12 +- plugin/goto_diagnostic.py | 14 +- plugin/references.py | 2 +- plugin/session_view.py | 3 +- stubs/sublime.pyi | 2533 +++++++++++++++++++++++++++------ 6 files changed, 2161 insertions(+), 406 deletions(-) diff --git a/plugin/core/configurations.py b/plugin/core/configurations.py index 8fc51c566..1232de31b 100644 --- a/plugin/core/configurations.py +++ b/plugin/core/configurations.py @@ -62,7 +62,8 @@ def update(self, updated_config_name: Optional[str] = None) -> None: self._reload_configs(updated_config_name, notify_listeners=True) def _reload_configs(self, updated_config_name: Optional[str] = None, notify_listeners: bool = False) -> None: - project_settings = (self._window.project_data() or {}).get("settings", {}).get("LSP", {}) + project_data = self._window.project_data() + project_settings = project_data.get("settings", {}).get("LSP", {}) if isinstance(project_data, dict) else {} if updated_config_name is None: self.all.clear() for name, config in self._global_configs.items(): diff --git a/plugin/documents.py b/plugin/documents.py index 13de9b713..a3b3188fb 100644 --- a/plugin/documents.py +++ b/plugin/documents.py @@ -70,8 +70,16 @@ def is_regular_view(v: sublime.View) -> bool: # Not from the quick panel (CTRL+P), and not a special view like a console, output panel or find-in-files panels. - is_widget = v.settings().get('is_widget') - return not v.sheet().is_transient() and v.element() is None and not is_widget + if v.element() is not None: + return False + if v.settings().get('is_widget'): + return False + sheet = v.sheet() + if not sheet: + return False + if sheet.is_transient(): + return False + return True def previous_non_whitespace_char(view: sublime.View, pt: int) -> str: diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index d83341bcf..0ab0dffa3 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -193,8 +193,10 @@ def description(self, value: DocumentUri, text: str) -> str: return self._project_path(parse_uri(value)) def cancel(self) -> None: - if self._preview is not None and self._preview.sheet().is_transient(): - self._preview.close() + if self._preview is not None: + sheet = self._preview.sheet() + if sheet and sheet.is_transient(): + self._preview.close() self.window.focus_view(self.view) def preview(self, value: Optional[DocumentUri]) -> str: @@ -246,7 +248,7 @@ def list_items(self) -> List[sublime.ListInputItem]: text = "{}: {}".format(format_severity(diagnostic_severity(diagnostic)), first_line) annotation = format_diagnostic_source_and_code(diagnostic) kind = DIAGNOSTIC_KINDS[diagnostic_severity(diagnostic)] - list_items.append(sublime.ListInputItem(text, (i, diagnostic), annotation=annotation, kind=kind)) + list_items.append(sublime.ListInputItem(text, [i, diagnostic], annotation=annotation, kind=kind)) return list_items def placeholder(self) -> str: @@ -268,8 +270,10 @@ def confirm(self, value: Optional[Tuple[int, Diagnostic]]) -> None: sublime.set_timeout_async(functools.partial(session.open_location_async, location)) def cancel(self) -> None: - if self._preview is not None and self._preview.sheet().is_transient(): - self._preview.close() + if self._preview is not None: + sheet = self._preview.sheet() + if sheet and sheet.is_transient(): + self._preview.close() self.window.focus_view(self.view) def preview(self, value: Optional[Tuple[int, Diagnostic]]) -> Union[str, sublime.Html]: diff --git a/plugin/references.py b/plugin/references.py index 35961378b..ecae586a5 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_OUTLINED) + panel.add_regions('ReferenceHighlight', regions, 'comment', flags=sublime.DRAW_NO_FILL) def _get_relative_path(base_dir: Optional[str], file_path: str) -> str: diff --git a/plugin/session_view.py b/plugin/session_view.py index f9df622c3..addfd68ae 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -255,7 +255,8 @@ def get_language_id(self) -> Optional[str]: return listener.get_language_id() if listener else None def get_view_for_group(self, group: int) -> Optional[sublime.View]: - return self.view if self.view.sheet().group() == group else None + sheet = self.view.sheet() + return self.view if sheet and sheet.group() == group else None def get_capability_async(self, capability_path: str) -> Optional[Any]: return self.session_buffer.get_capability(capability_path) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index 65057817d..70f31f2de 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -1,679 +1,1367 @@ # Stubs for sublime.py (Python 3.3 API Environment) -from typing import Any, Callable, Dict, Iterator, List, Literal, Optional, Reversible, Sequence, Tuple, Union +from typing import Any, Callable, Dict, Iterable, Iterator, List, Literal, Optional, Reversible, Sequence, Tuple +from typing_extensions import deprecated -HOVER_TEXT = ... # type: int +HOVER_TEXT: int = ... """The mouse is hovered over the text.""" -HOVER_GUTTER = ... # type: int +HOVER_GUTTER: int = ... """The mouse is hovered over the gutter.""" -HOVER_MARGIN = ... # type: int +HOVER_MARGIN: int = ... """The mouse is hovered in the white space to the right of a line.""" -ENCODED_POSITION = ... # type: int +ENCODED_POSITION: int = ... """Indicates that the file name should be searched for a `:row` or `:row:col` suffix.""" -TRANSIENT = ... # type: int +TRANSIENT: int = ... """Open the file as a preview only: it won't have a tab assigned it until modified.""" -FORCE_GROUP = ... # type: int -"""Don't select the file if it is open in a different group. Instead make a new clone of that file in the desired group.""" -SEMI_TRANSIENT = ... # type: int -"""If a sheet is newly created, it will be set to semi-transient. Semi-transient sheets generally replace other semi-transient sheets. This is used for the side-bar preview. Only valid with `ADD_TO_SELECTION` or `REPLACE_MRU`.""" -ADD_TO_SELECTION = ... # type: int +FORCE_GROUP: int = ... +""" +Don't select the file if it is open in a different group. Instead make a new clone of that file in the desired group. +""" +SEMI_TRANSIENT: int = ... +""" +If a sheet is newly created, it will be set to semi-transient. Semi-transient sheets generally replace other +semi-transient sheets. This is used for the side-bar preview. Only valid with `ADD_TO_SELECTION` or `REPLACE_MRU`. +""" +ADD_TO_SELECTION: int = ... """Add the file to the currently selected sheets in the group.""" -REPLACE_MRU = ... # type: int +REPLACE_MRU: int = ... """Causes the sheet to replace the most-recently used sheet in the current sheet selection.""" -CLEAR_TO_RIGHT = ... # type: int -"""All currently selected sheets to the right of the most-recently used sheet will be unselected before opening the file. Only valid in combination with `ADD_TO_SELECTION`.""" -FORCE_CLONE = ... # type: int +CLEAR_TO_RIGHT: int = ... +""" +All currently selected sheets to the right of the most-recently used sheet will be unselected before opening the file. +Only valid in combination with `ADD_TO_SELECTION`. +""" +FORCE_CLONE: int = ... """Don't select the file if it is open. Instead make a new clone of that file in the desired group.""" -LITERAL = ... # type: int +LITERAL: int = ... """Whether the find pattern should be matched literally or as a regex.""" -IGNORECASE = ... # type: int +IGNORECASE: int = ... """Whether case should be considered when matching the find pattern.""" -WHOLEWORD = ... # type: int +WHOLEWORD: int = ... """Whether to only match whole words.""" -REVERSE = ... # type: int +REVERSE: int = ... """Whether to search backwards.""" -WRAP = ... # type: int +WRAP: int = ... """Whether to wrap around once the end is reached.""" -MONOSPACE_FONT = ... # type: int +MONOSPACE_FONT: int = ... """Use a monospace font.""" -KEEP_OPEN_ON_FOCUS_LOST = ... # type: int +KEEP_OPEN_ON_FOCUS_LOST: int = ... """Keep the quick panel open if the window loses input focus.""" -WANT_EVENT = ... # type: int +WANT_EVENT: int = ... """Pass a second parameter to the `on_done` callback, a `Event`.""" -HTML = ... # type: int -COOPERATE_WITH_AUTO_COMPLETE = ... # type: int +HTML: int = ... +COOPERATE_WITH_AUTO_COMPLETE: int = ... """Causes the popup to display next to the auto complete menu.""" -HIDE_ON_MOUSE_MOVE = ... # type: int +HIDE_ON_MOUSE_MOVE: int = ... """Causes the popup to hide when the mouse is moved, clicked or scrolled.""" -HIDE_ON_MOUSE_MOVE_AWAY = ... # type: int +HIDE_ON_MOUSE_MOVE_AWAY: int = ... """Causes the popup to hide when the mouse is moved (unless towards the popup), or when clicked or scrolled.""" -KEEP_ON_SELECTION_MODIFIED = ... # type: int +KEEP_ON_SELECTION_MODIFIED: int = ... """Prevent the popup from hiding when the selection is modified.""" -HIDE_ON_CHARACTER_EVENT = ... # type: int +HIDE_ON_CHARACTER_EVENT: int = ... """Hide the popup when a character is typed.""" -DRAW_EMPTY = ... # type: int +DRAW_EMPTY: int = ... """Draw empty regions with a vertical bar. By default, they aren't drawn at all.""" -HIDE_ON_MINIMAP = ... # type: int +HIDE_ON_MINIMAP: int = ... """Don't show the regions on the minimap.""" -DRAW_EMPTY_AS_OVERWRITE = ... # type: int +DRAW_EMPTY_AS_OVERWRITE: int = ... """Draw empty regions with a horizontal bar instead of a vertical one.""" -PERSISTENT = ... # type: int +PERSISTENT: int = ... """Save the regions in the session.""" -DRAW_NO_FILL = ... # type: int +DRAW_NO_FILL: int = ... """Disable filling the regions, leaving only the outline.""" -HIDDEN = ... # type: int +HIDDEN: int = ... """Don't draw the regions.""" -DRAW_NO_OUTLINE = ... # type: int +DRAW_NO_OUTLINE: int = ... """Disable drawing the outline of the regions.""" -DRAW_SOLID_UNDERLINE = ... # type: int +DRAW_SOLID_UNDERLINE: int = ... """Draw a solid underline below the regions.""" -DRAW_STIPPLED_UNDERLINE = ... # type: int +DRAW_STIPPLED_UNDERLINE: int = ... """Draw a stippled underline below the regions.""" -DRAW_SQUIGGLY_UNDERLINE = ... # type: int +DRAW_SQUIGGLY_UNDERLINE: int = ... """Draw a squiggly underline below the regions.""" -NO_UNDO = ... # type: int - -OP_EQUAL = ... # type: int -OP_NOT_EQUAL = ... # type: int -OP_REGEX_MATCH = ... # type: int -OP_NOT_REGEX_MATCH = ... # type: int -OP_REGEX_CONTAINS = ... # type: int -OP_NOT_REGEX_CONTAINS = ... # type: int -CLASS_WORD_START = ... # type: int +NO_UNDO: int = ... + +OP_EQUAL: int = ... +OP_NOT_EQUAL: int = ... +OP_REGEX_MATCH: int = ... +OP_NOT_REGEX_MATCH: int = ... +OP_REGEX_CONTAINS: int = ... +OP_NOT_REGEX_CONTAINS: int = ... +CLASS_WORD_START: int = ... """The point is the start of a word.""" -CLASS_WORD_END = ... # type: int +CLASS_WORD_END: int = ... """The point is the end of a word.""" -CLASS_PUNCTUATION_START = ... # type: int +CLASS_PUNCTUATION_START: int = ... """The point is the start of a sequence of punctuation characters.""" -CLASS_PUNCTUATION_END = ... # type: int +CLASS_PUNCTUATION_END: int = ... """The point is the end of a sequence of punctuation characters.""" -CLASS_SUB_WORD_START = ... # type: int +CLASS_SUB_WORD_START: int = ... """The point is the start of a sub-word.""" -CLASS_SUB_WORD_END = ... # type: int +CLASS_SUB_WORD_END: int = ... """The point is the end of a sub-word.""" -CLASS_LINE_START = ... # type: int +CLASS_LINE_START: int = ... """The point is the start of a line.""" -CLASS_LINE_END = ... # type: int +CLASS_LINE_END: int = ... """The point is the end of a line.""" -CLASS_EMPTY_LINE = ... # type: int +CLASS_EMPTY_LINE: int = ... """The point is an empty line.""" -INHIBIT_WORD_COMPLETIONS = ... # type: int +INHIBIT_WORD_COMPLETIONS: int = ... """Prevent Sublime Text from showing completions based on the contents of the view.""" -INHIBIT_EXPLICIT_COMPLETIONS = ... # type: int +INHIBIT_EXPLICIT_COMPLETIONS: int = ... """Prevent Sublime Text from showing completions based on `.sublime-completions` files.""" -DYNAMIC_COMPLETIONS = ... # type: int +DYNAMIC_COMPLETIONS: int = ... """If completions should be re-queried as the user types.""" -INHIBIT_REORDER = ... # type: int +INHIBIT_REORDER: int = ... """Prevent Sublime Text from changing the completion order.""" -DIALOG_CANCEL = ... # type: int -DIALOG_YES = ... # type: int -DIALOG_NO = ... # type: int +DIALOG_CANCEL: int = ... +DIALOG_YES: int = ... +DIALOG_NO: int = ... -LAYOUT_INLINE = ... # type: int +LAYOUT_INLINE: int = ... """The phantom is positioned inline with the text at the beginning of its `Region`.""" -LAYOUT_BELOW = ... # type: int +LAYOUT_BELOW: int = ... """The phantom is positioned below the line, left-aligned with the beginning of its `Region`.""" -LAYOUT_BLOCK = ... # type: int +LAYOUT_BLOCK: int = ... """The phantom is positioned below the line, left-aligned with the beginning of the line.""" -KIND_ID_AMBIGUOUS = ... # type: int -KIND_ID_KEYWORD = ... # type: int -KIND_ID_TYPE = ... # type: int -KIND_ID_FUNCTION = ... # type: int -KIND_ID_NAMESPACE = ... # type: int -KIND_ID_NAVIGATION = ... # type: int -KIND_ID_MARKUP = ... # type: int -KIND_ID_VARIABLE = ... # type: int -KIND_ID_SNIPPET = ... # type: int - -KIND_ID_COLOR_REDISH = ... # type: int -KIND_ID_COLOR_ORANGISH = ... # type: int -KIND_ID_COLOR_YELLOWISH = ... # type: int -KIND_ID_COLOR_GREENISH = ... # type: int -KIND_ID_COLOR_CYANISH = ... # type: int -KIND_ID_COLOR_BLUISH = ... # type: int -KIND_ID_COLOR_PURPLISH = ... # type: int -KIND_ID_COLOR_PINKISH = ... # type: int -KIND_ID_COLOR_DARK = ... # type: int -KIND_ID_COLOR_LIGHT = ... # type: int - -KIND_AMBIGUOUS = ... # type: Tuple[int, str, str] -KIND_KEYWORD = ... # type: Tuple[int, str, str] -KIND_TYPE = ... # type: Tuple[int, str, str] -KIND_FUNCTION = ... # type: Tuple[int, str, str] -KIND_NAMESPACE = ... # type: Tuple[int, str, str] -KIND_NAVIGATION = ... # type: Tuple[int, str, str] -KIND_MARKUP = ... # type: Tuple[int, str, str] -KIND_VARIABLE = ... # type: Tuple[int, str, str] -KIND_SNIPPET = ... # type: Tuple[int, str, str] - -SYMBOL_SOURCE_ANY = ... # type: int +KIND_ID_AMBIGUOUS: int = ... +KIND_ID_KEYWORD: int = ... +KIND_ID_TYPE: int = ... +KIND_ID_FUNCTION: int = ... +KIND_ID_NAMESPACE: int = ... +KIND_ID_NAVIGATION: int = ... +KIND_ID_MARKUP: int = ... +KIND_ID_VARIABLE: int = ... +KIND_ID_SNIPPET: int = ... + +KIND_ID_COLOR_REDISH: int = ... +KIND_ID_COLOR_ORANGISH: int = ... +KIND_ID_COLOR_YELLOWISH: int = ... +KIND_ID_COLOR_GREENISH: int = ... +KIND_ID_COLOR_CYANISH: int = ... +KIND_ID_COLOR_BLUISH: int = ... +KIND_ID_COLOR_PURPLISH: int = ... +KIND_ID_COLOR_PINKISH: int = ... +KIND_ID_COLOR_DARK: int = ... +KIND_ID_COLOR_LIGHT: int = ... + +KIND_AMBIGUOUS: Tuple[int, str, str] = ... +KIND_KEYWORD: Tuple[int, str, str] = ... +KIND_TYPE: Tuple[int, str, str] = ... +KIND_FUNCTION: Tuple[int, str, str] = ... +KIND_NAMESPACE: Tuple[int, str, str] = ... +KIND_NAVIGATION: Tuple[int, str, str] = ... +KIND_MARKUP: Tuple[int, str, str] = ... +KIND_VARIABLE: Tuple[int, str, str] = ... +KIND_SNIPPET: Tuple[int, str, str] = ... + +SYMBOL_SOURCE_ANY: int = ... """Use any source - both the index and open files.""" -SYMBOL_SOURCE_INDEX = ... # type: int +SYMBOL_SOURCE_INDEX: int = ... """Use the index created when scanning through files in a project folder.""" -SYMBOL_SOURCE_OPEN_FILES = ... # type: int +SYMBOL_SOURCE_OPEN_FILES: int = ... """Use the open files, unsaved or otherwise.""" -SYMBOL_TYPE_ANY = ... # type: int +SYMBOL_TYPE_ANY: int = ... """Any symbol type - both definitions and references.""" -SYMBOL_TYPE_DEFINITION = ... # type: int +SYMBOL_TYPE_DEFINITION: int = ... """Only definitions.""" -SYMBOL_TYPE_REFERENCE = ... # type: int +SYMBOL_TYPE_REFERENCE: int = ... """Only references.""" -COMPLETION_FORMAT_TEXT = ... # type: int +COMPLETION_FORMAT_TEXT: int = ... """Plain text, upon completing the text is inserted verbatim.""" -COMPLETION_FORMAT_SNIPPET = ... # type: int +COMPLETION_FORMAT_SNIPPET: int = ... """A snippet, with `$` variables.""" -COMPLETION_FORMAT_COMMAND = ... # type: int +COMPLETION_FORMAT_COMMAND: int = ... """A command string, in the format returned by `format_command()`.""" -COMPLETION_FLAG_KEEP_PREFIX = ... # type: int - - -class Settings: - settings_id = ... # type: int - - def __init__(self, id: int) -> None: - ... - - def get(self, key: str, default: Optional[Any] = ...) -> Optional[Any]: - ... - - def has(self, key: str) -> bool: - ... - - def set(self, key: str, value: Any) -> None: - ... - - def erase(self, key: str) -> None: - ... - - def add_on_change(self, tag: str, callback: Callable[[], None]) -> None: - ... - - def clear_on_change(self, tag: str) -> None: - ... +COMPLETION_FLAG_KEEP_PREFIX: int = ... def version() -> str: - """The version number.""" + """ + The version number. + """ ... def platform() -> Literal["osx", "linux", "windows"]: - """The platform which the plugin is being run on.""" + """ + The platform which the plugin is being run on. + """ ... def arch() -> Literal["x32", "x64", "arm64"]: - """The CPU architecture.""" + """ + The CPU architecture. + """ ... def channel() -> Literal["dev", "stable"]: - """The release channel of this build of Sublime Text.""" + """ + The release channel of this build of Sublime Text. + """ ... def executable_path() -> str: - """The path to the main Sublime Text executable.""" + """ + The path to the main Sublime Text executable. + """ ... def executable_hash() -> Tuple[str, str, str]: - """A tuple uniquely identifying the installation of Sublime Text.""" + """ + A tuple uniquely identifying the installation of Sublime Text. + """ ... def packages_path() -> str: - """The path to the "Packages" folder.""" + """ + The path to the "Packages" folder. + """ ... def installed_packages_path() -> str: - """The path to the "Installed Packages" folder.""" + """ + The path to the "Installed Packages" folder. + """ ... def cache_path() -> str: - """The path where Sublime Text stores cache files.""" + """ + The path where Sublime Text stores cache files. + """ ... def status_message(msg: str) -> None: - """Show a message in the status bar.""" + """ + Show a message in the status bar. + """ ... def error_message(msg: str) -> None: - """Display an error dialog.""" + """ + Display an error dialog. + """ ... def message_dialog(msg: str) -> None: - """Display a message dialog.""" + """ + Display a message dialog. + """ ... -def ok_cancel_dialog(msg: str, ok_title: str = ...) -> bool: +def ok_cancel_dialog(msg: str, ok_title: str = ..., title: str = ...) -> bool: + """ + Show a popup dialog with an "ok" and "cancel" button. + + - `msg` - The message to show in the dialog. + - `ok_title` - Optional replacement string for the "ok" button. + - `title` - Optional title for the dialog. Note Linux and macOS do not have a title in their dialog. + + Returns `True` if the user presses the `ok` button, `False` otherwise. + """ ... -def yes_no_cancel_dialog(msg: str, yes_title: str = ..., no_title: str = ...) -> int: +def yes_no_cancel_dialog(msg: str, yes_title: str = ..., no_title: str = ..., title: str = ...) -> int: + """ + Show a popup dialog with a "yes", "no" and "cancel" button. + + - `msg` - The message to show in the dialog. + - `yes_title` - Optional replacement string for the "yes" button. + - `no_title` - Optional replacement string for the "no" button. + - `title` - Optional title for the dialog. Note Linux and macOS do not have a title in their dialog. + + Returns `DIALOG_YES`, `DIALOG_NO` or `DIALOG_CANCEL`. + """ ... -def run_command(cmd: str, args: Optional[Any] = ...) -> None: +def open_dialog( + callback: Callable[[str | List[str] | None], None], + file_types: List[Tuple[str, List[str]]] = ..., + directory: str | None = ..., + multi_select: bool = ..., + allow_folders: bool = ... +) -> None: + """ + Show the open file dialog. + + - `callback` - Called with selected path(s) or `None` once the dialog is closed. + - `file_types` - A list of allowed file types, consisting of a description and a list of allowed extensions. + - `directory` - The directory the dialog should start in. Will use the virtual working directory if not provided. + - `multi_select` - Whether to allow selecting multiple files. When `True` the callback will be called with a list. + - `allow_folders` - Whether to also allow selecting folders. Only works on macOS. If you only want to select folders + use `select_folder_dialog`. + """ ... +def save_dialog( + callback: Callable[[str | None], None], + file_types: List[Tuple[str, List[str]]] = ..., + directory: str | None = ..., + name: str | None = ..., + extension: str | None = ..., +) -> None: + """ + Show the save file dialog. + + - `callback` - Called with selected path or `None` once open dialog is closed. + - `file_types` - A list of allowed file types, consisting of a description and a list of allowed extensions. + - `directory` - The directory the dialog should start in. Will use the virtual working directory if not provided. + - `name` - The default name of the file in the save dialog. + - `extension` - The default extension used in the save dialog. + """ + ... + + +def select_folder_dialog( + callback: Callable[[str | List[str] | None], None], + directory: str | None = ..., + multi_select: bool = ..., +) -> None: + """ + Show the select folder dialog. + + - `callback` - Called with selected path(s) or `None` once open dialog is closed. + - `directory` - The directory the dialog should start in. Will use the virtual working directory if not provided. + - `multi_select` - Whether to allow selecting multiple folders. When `True` the callback will be called with a list. + """ + ... + + +def choose_font_dialog( + callback: Callable[[Dict[str, Any] | None], None], + default: Dict[str, Any] | None = ... +) -> None: + """ + Show a dialog for selecting a font. + + - `callback` - Called with the font options, matching the format used in settings + (eg. `{ "font_face": "monospace" }`). May be called more than once, or will be called with `None` if the dialog + is cancelled. + - `default` - The default values to select/return. Same format as the argument passed to `callback`. + """ + ... + + +def run_command(cmd: str, args: Dict[str, Any] | None = ...) -> None: + """ + Runs the named `ApplicationCommand` with the (optional) given `args`. + """ + ... + + +def format_command(cmd: str, args: Dict[str, Any] | None = ...) -> str: + """ + Creates a "command string" from a str cmd name, and an optional dict of args. This is used when constructing a + command-based `CompletionItem`. + """ + ... + + +def html_format_command(cmd: str, args: Dict[str, Any] | None = ...) -> str: + """ + Creates an escaped "command string" for usage in HTML popups and sheets. + """ + ... + + +def command_url(cmd: str, args: Dict[str, Any] | None = ...) -> str: + """ + Creates a `subl:` protocol URL for executing a command in a minihtml link. + """ + ... + + +def get_clipboard_async(callback: Callable[[str], None], size_limit: int = ...) -> None: + """ + Calls `callback` with the contents of the clipboard. For performance reasons if the size of the clipboard content is + bigger than `size_limit`, an empty string will be returned. + """ + ... + + +@deprecated("Use get_clipboard_async() when possible") def get_clipboard(size_limit: int = ...) -> str: + """ + Returns the content of the clipboard. For performance reasons if the size of the clipboard content is bigger than + size_limit, an empty string will be returned. + """ ... def set_clipboard(text: str) -> None: + """ + Sets the contents of the clipboard. + """ + ... + + +def log_commands(flag: bool | None = ...) -> None: + """ + Controls command logging. If enabled, all commands run from key bindings and the menu will be logged to the console. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ + ... + + +def get_log_commands() -> bool: + """ + Returns whether command logging is enabled. + """ + ... + + +def log_input(flag: bool | None = ...) -> None: + """ + Control whether all key presses will be logged to the console. Use this to find the names of certain keys on the + keyboard. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ + ... + + +def get_log_input() -> bool: + """ + Returns whether input logging is enabled. + """ + ... + + +def log_fps(flag: bool | None = ...) -> None: + """ + Control whether rendering timings like frames per second get logged. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ + ... + + +def get_log_fps() -> bool: + """ + Returns whether fps logging is enabled. + """ + ... + + +def log_result_regex(flag: bool | None = ...) -> None: + """ + Control whether result regex logging is enabled. Use this to debug `"file_regex"` and `"line_regex"` in build + systems. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ ... -def log_commands(flag: bool) -> None: +def get_log_result_regex() -> bool: + """ + Returns whether result regex logging is enabled. + """ ... -def log_input(flag: bool) -> None: +def log_indexing(flag: bool | None = ...) -> None: + """ + Control whether indexing logs are printed to the console. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ ... -def log_result_regex(flag: bool) -> None: +def get_log_indexing() -> bool: + """ + Returns whether indexing logging is enabled. + """ + ... + + +def log_build_systems(flag: bool | None = ...) -> None: + """ + Control whether build system logs are printed to the console. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ + ... + + +def get_log_build_systems() -> bool: + """ + Returns whether build system logging is enabled. + """ + ... + + +def log_control_tree(flag: bool | None = ...) -> None: + """ + Control whether control tree logging is enabled. When enabled clicking with Ctrl+Alt will log the control tree under + the mouse to the console. + + - `flag` - Whether to log. Passing `None` toggles logging. + """ ... -def log_indexing(flag: bool) -> None: +def get_log_control_tree() -> bool: + """ + Returns whether control tree logging is enabled. + """ ... -def log_build_systems(flag: bool) -> None: +def ui_info() -> Dict[str, Any]: + """ + Information about the user interface including top-level keys `system`, `theme` and `color_scheme`. + """ ... def score_selector(scope_name: str, selector: str) -> int: + """ + Match the `selector` against the given `scope_name`, returning a score for how well they match. + + A score of `0` means no match, above `0` means a match. Different selectors may be compared against the same scope: + a higher score means the selector is a better match for the scope. + """ ... def load_resource(name: str) -> str: + """ + Loads the given resource. The name should be in the format "Packages/Default/Main.sublime-menu". + + Raises `FileNotFoundError` if resource is not found. + """ ... def load_binary_resource(name: str) -> bytes: + """ + Loads the given binary resource. The name should be in the format "Packages/Default/Main.sublime-menu". + + Raises `FileNotFoundError` if resource is not found. + """ ... def find_resources(pattern: str) -> Sequence[str]: + """Finds resources whose file name matches the given glob pattern.""" ... -def encode_value(val: Any, pretty: bool = ...) -> str: +def encode_value(val: Any, pretty: bool = ..., update_text: str = ...) -> str: + """ + Encode a JSON compatible `Value` into a string representation. + + - `pretty` - Whether the result should include newlines and be indented. + - `update_text` - Incrementally update the value encoded in this text. Best effort is made to preserve the contents + of `update_text` - comments, indentation, etc. This is the same algorithm used to change settings values. + Providing this makes `pretty` have no effect. + """ ... def decode_value(data: str) -> Any: + """ + Decode a JSON string into an object. Note that comments and trailing commas are allowed. + + Raises `ValueError` if the string is not valid JSON. + """ ... -def expand_variables(val: Any, variables: dict) -> Any: +def expand_variables(val: Any, variables: Dict[str, str]) -> Any: + """ + Expands any variables in `val` using the variables defined in the dictionary `variables`. `val` may also be a list + or dict, in which case the structure will be recursively expanded. Strings should use snippet syntax, for example: + + ```python + expand_variables("Hello, ${name}", {"name": "Foo"}) + ``` + """ ... def load_settings(base_name: str) -> Settings: + """ + Loads the named settings. The name should include a file name and extension, but not a path. The packages will be + searched for files matching the base_name, and the results will be collated into the settings object. + + Subsequent calls to `load_settings` with the base_name will return the same object, and not load the settings from + disk again. + """ ... def save_settings(base_name: str) -> None: + """ + Flush any in-memory changes to the named settings object to disk. + """ ... def set_timeout(f: Callable[[], Any], timeout_ms: int = ...) -> None: + """ + Schedules a function to be called in the future. Sublime Text will block while the function is running. + """ ... def set_timeout_async(f: Callable[[], Any], timeout_ms: int = ...) -> None: + """ + Schedules a function to be called in the future. The function will be called in a worker thread, and Sublime Text + will not block while the function is running. + """ ... -def active_window() -> 'Window': +def active_window() -> Window: + """ + The most recently used `Window`. + """ ... -def windows() -> 'Sequence[Window]': +def windows() -> List[Window]: + """ + A list of all the open windows. + """ ... -def get_macro() -> Sequence[dict]: +def get_macro() -> List[Dict[str, Any]]: + """ + A list of the commands and args that compromise the currently recorded macro. Each dict will contain the keys + `"command"` and `"args"`. + """ ... -def syntax_from_path(syntax_path: str) -> Optional[Syntax]: +def project_history() -> List[str]: + """ + A list of most recently opened workspaces. Sublime-project files with the same name are listed in place of + sublime-workspace files. + """ ... -def command_url(cmd: str, args: Optional[dict] = ...) -> str: +def folder_history() -> List[str]: + """ + A list of recent folders added to sublime projects. + """ ... -class Syntax: - path = ... # type: str - name = ... # type: str - hidden = ... # type: bool - scope = ... # type: str +class Window: + window_id: int = ... + settings_object: Settings = ... + template_settings_object = ... - def __init__(self, path: str, name: str, hidden: bool, scope: str) -> None: + def __init__(self, id: int) -> None: + ... + + def __eq__(self, other: object) -> bool: ... + def __bool__(self) -> bool: + ... -class CompletionItem: - trigger = ... # type: str - annotation = ... # type: str - completion = ... # type: str - completion_format = ... # type: int - kind = ... # type: Tuple[int, str, str] - details = ... # type: str - flags = ... # type: int + def id(self) -> int: + """ + A number that uniquely identifies this window. + """ + ... - def __init__( - self, - trigger: str, - annotation: str = "", - completion: str = "", - completion_format: int = COMPLETION_FORMAT_TEXT, - kind: Tuple[int, str, str] = KIND_AMBIGUOUS, - details: str = "") -> None: + def is_valid(self) -> bool: + """ + Check whether this window is still valid. Will return `False` for a closed window, for example. + """ ... - @classmethod - def snippet_completion( - cls, - trigger: str, - snippet: str, - annotation: str = " ", - kind: Tuple[int, str, str] = KIND_SNIPPET, - details: str = "") -> 'CompletionItem': + def hwnd(self): + """ + A platform specific window handle. Windows only. + """ ... - @classmethod - def command_completion(cls, - trigger: str, - command: str, - args: dict = {}, - annotation: str = "", - kind: Tuple[int, str, str] = KIND_AMBIGUOUS, - details: str = "" - ) -> 'CompletionItem': + def active_sheet(self) -> Sheet | None: + """ + The currently focused `Sheet`. + """ ... + def active_view(self) -> View | None: + """ + The currently edited `View`. + """ + ... -class CompletionList: - def set_completions(self, completions: List[CompletionItem], flags: int = 0) -> None: + def new_html_sheet(self, name: str, contents: str, flags: int = ..., group: int = ...) -> Sheet: + """ + Construct a sheet with HTML contents rendered using minihtml. + + - `name` - The name of the sheet to show in the tab. + - `contents` - The HTML contents of the sheet. + - `flags` - Only `TRANSIENT` and `ADD_TO_SELECTION` are allowed. + - `group` - The group to add the sheet to. `-1` for the active group. + """ ... + def run_command(self, cmd: str, args: Dict[str, Any] | None = ...) -> None: + """ + Run the named `WindowCommand` with the (optional) given args. This method is able to run any sort of command, + dispatching the command via input focus. + """ + ... -class Window: - window_id = ... # type: int - settings_object = ... # type: Settings - template_settings_object = ... # type: Any + def new_file(self, flags: int = ..., syntax: str = ...) -> View: + """ + Create a new empty file. - def __init__(self, id: int) -> None: + - `flags` - Either `0`, `TRANSIENT` or `ADD_TO_SELECTION`. + - `syntax` - The name of the syntax to apply to the file. + + Returns the `View` for the file. + """ ... - def __eq__(self, other: object) -> bool: + def open_file(self, fname: str, flags: int = ..., group: int = ...) -> View: + """ + Open the named file. If the file is already opened, it will be brought to the front. Note that as file loading + is asynchronous, operations on the returned view won't be possible until its `is_loading()` method returns + `False`. + + - `fname` - The path to the file to open. + - `flags` + - `group` - The group to add the sheet to. `-1` for the active group. + """ ... - def __bool__(self) -> bool: + def find_open_file(self, fname: str, group: int = ...) -> View | None: + """ + Find a opened file by file name. + + - `fname` - The path to the file to open. + - `group` - The group in which to search for the file. `-1` for any group. + + Returns the `View` to the file or `None` if the file isn't open. + """ ... - def id(self) -> int: + def file_history(self) -> List[str]: + """ + Get the list of previously opened files. This is the same list as File > Open Recent. + """ ... - def is_valid(self) -> bool: + def num_groups(self) -> int: + """ + The number of view groups in the window. + """ ... - # def hwnd(self): ... - def active_sheet(self) -> 'Sheet': + def active_group(self) -> int: + """ + The index of the currently selected group. + """ ... - def active_view(self) -> 'Optional[View]': + def focus_group(self, idx: int) -> None: + """ + Focus the specified group, making it active. + """ ... - def new_html_sheet(self, name: str, contents: str, flags: int = ..., group: int = ...) -> 'Sheet': + def focus_sheet(self, sheet: Sheet) -> None: + """ + Switches to the given `Sheet`. + """ ... - def run_command(self, cmd: str, args: Optional[Any] = ...) -> None: + def focus_view(self, view: View) -> None: + """ + Switches to the given `View`. + """ ... - def new_file(self, flags: int = ..., syntax: str = ...) -> 'View': + def select_sheets(self, sheets: List[Sheet]) -> None: + """ + Change the selected sheets for the entire window. + """ ... - def open_file(self, fname: str, flags: int = ..., group: int = ...) -> 'View': + def bring_to_front(self) -> None: + """ + Bring the window in front of any other windows. + """ ... - def find_open_file(self, fname: str, group: int = ...) -> 'Optional[View]': + def get_sheet_index(self, sheet: Sheet) -> Tuple[int, int]: + """ + The a tuple of the group and index within the group of the given `Sheet`. + """ ... - def num_groups(self) -> int: + def get_view_index(self, view: View) -> Tuple[int, int]: + """ + The a tuple of the group and index within the group of the given `View`. + """ ... - def active_group(self) -> int: + def set_sheet_index(self, sheet: Sheet, group: int, idx: int) -> None: + """ + Move the given `Sheet` to the given `group` at the given `index`. + """ ... - def focus_group(self, idx: int) -> None: + def set_view_index(self, view: View, group: int, idx: int) -> None: + """ + Move the given `View` to the given `group` at the given `index`. + """ ... - def focus_sheet(self, sheet: 'Sheet') -> None: + def move_sheets_to_group( + self, + sheets: List[Sheet], + group: int, + insertion_idx: int = ..., + select: bool = ... + ) -> None: + """ + Moves all provided sheets to specified group at insertion index provided. If an index is not provided defaults + to last index of the destination group. + + - `sheets` - The sheets to move. + - `group` - The index of the group to move the sheets to. + - `insertion_idx` - The point inside the group at which to insert the sheets. + - `select` - Whether the sheets should be selected after moving them. + """ ... - def focus_view(self, view: 'View') -> None: + def sheets(self) -> List[Sheet]: + """ + All open sheets in the window. + """ ... - def select_sheets(self, sheets: 'List[Sheet]') -> None: + def views(self, *, include_transient: bool = ...) -> List[View]: + """ + All open sheets in the window. + + - `include_transient` - Whether the transient sheet should be included. + """ ... - def get_sheet_index(self, sheet: 'Sheet') -> Tuple[int, int]: + def selected_sheets(self) -> List[Sheet]: + """ + All selected sheets in the window's currently selected group. + """ ... - def get_view_index(self, view: 'View') -> Tuple[int, int]: + def selected_sheets_in_group(self, group: int) -> List[Sheet]: + """ + All selected sheets in the specified group. + """ ... - def set_sheet_index(self, sheet: 'Sheet', group: int, idx: int) -> None: + def active_sheet_in_group(self, group: int) -> Sheet | None: + """ + The currently focused `Sheet` in the given group. + """ ... - def set_view_index(self, view: 'View', group: int, idx: int) -> None: + def active_view_in_group(self, group: int) -> View | None: + """ + The currently focused `View` in the given group. + """ ... - def sheets(self) -> 'List[Sheet]': + def sheets_in_group(self, group: int) -> List[Sheet]: + """ + A list of all sheets in the specified group. + """ ... - def selected_sheets(self) -> 'List[Sheet]': + def views_in_group(self, group: int) -> List[View]: + """ + A list of all views in the specified group. + """ ... - def selected_sheets_in_group(self, group: int) -> 'List[Sheet]': + def num_sheets_in_group(self, group: int) -> int: + """ + The number of sheets in the specified group. + """ ... - def views(self) -> 'List[View]': + def num_views_in_group(self, group: int) -> int: + """ + The number of views in the specified group. + """ ... - def active_sheet_in_group(self, group: int) -> 'Sheet': + def transient_sheet_in_group(self, group: int) -> Sheet | None: + """ + The transient sheet in the specified group. + """ ... - def active_view_in_group(self, group: int) -> 'Optional[View]': + def transient_view_in_group(self, group: int) -> View | None: + """ + The transient view in the specified group. + """ ... - def sheets_in_group(self, group: int) -> 'List[Sheet]': + def promote_sheet(self, sheet: Sheet) -> None: + """ + Promote the 'Sheet' parameter if semi-transient or transient. + """ ... - def views_in_group(self, group: int) -> 'List[View]': + def layout(self): + """ + Get the group layout of the window. + """ ... - def transient_sheet_in_group(self, group: int) -> 'Sheet': + @deprecated("Use layout() instead") + def get_layout(self): ... - def transient_view_in_group(self, group: int) -> 'View': + def set_layout(self, layout: Dict[str, Any]) -> None: + """ + Set the group layout of the window. + """ ... - # def layout(self): ... - # def get_layout(self): ... - # def set_layout(self, layout): ... - def create_output_panel(self, name: str, unlisted: bool = ...) -> 'View': + def create_output_panel(self, name: str, unlisted: bool = ...) -> View: + """ + Find the view associated with the named output panel, creating it if required. The output panel can be shown by + running the `show_panel` window command, with the `panel` argument set to the name with an `"output."` prefix. + + The optional `unlisted` parameter is a boolean to control if the output panel should be listed in the panel + switcher. + """ ... - def find_output_panel(self, name: str) -> 'Optional[View]': + def find_output_panel(self, name: str) -> View | None: + """ + The `View` associated with the named output panel, or `None` if the output panel does not exist. + """ ... def destroy_output_panel(self, name: str) -> None: + """ + Destroy the named output panel, hiding it if currently open. + """ ... - def active_panel(self) -> Optional[str]: + def active_panel(self) -> str | None: + """ + Returns the name of the currently open panel, or None if no panel is open. Will return built-in panel names + (e.g. `"console"`, `"find"`, etc.) in addition to output panels. + """ ... def panels(self) -> List[str]: + """ + Returns a list of the names of all panels that have not been marked as unlisted. Includes certain built-in + panels in addition to output panels. + """ ... - def get_output_panel(self, name: str) -> 'Optional[View]': - ... - - def show_input_panel(self, caption: str, initial_text: str, on_done: Optional[Callable], - on_change: Optional[Callable], on_cancel: Optional[Callable]) -> 'View': + @deprecated("Use create_output_panel(...) instead") + def get_output_panel(self, name: str) -> View | None: ... - def show_quick_panel(self, - items: List[Any], - on_select: Callable, - flags: int = ..., - selected_index: int = ..., - on_highlight: Optional[Callable] = ..., - placeholder: Optional[str] = ...) -> None: + def show_input_panel( + self, + caption: str, + initial_text: str, + on_done: Callable[[str], None] | None, + on_change: Callable[[str], None] | None, + on_cancel: Callable[[], None] | None + ) -> View: + """ + Shows the input panel, to collect a line of input from the user. + + - `caption` - The label to put next to the input widget. + - `initial_text` - The initial text inside the input widget. + - `on_done` - Called with the final input when the user presses Enter. + - `on_change` - Called with the input when it's changed. + - `on_cancel` - Called when the user cancels input using Esc. + + Returns the `View` used for the input widget. + """ + ... + + def show_quick_panel( + self, + items: List[Any], + on_select: Callable[..., None], + flags: int = ..., + selected_index: int = ..., + on_highlight: Callable[..., None] = ..., + placeholder: str | None = ... + ) -> None: + """ + Show a quick panel to select an item in a list. on_select will be called once, with the index of the selected + item. If the quick panel was cancelled, `on_select` will be called with an argument of `-1`. + + - `items` - May be either a list of strings, a list of lists of strings where the first item is the trigger + and all subsequent strings are details shown below, or a `QuickPanelItem`. + - `on_select` - Called with the selected item's index when the quick panel is completed. If the panel was + cancelled this is called with `-1`. A second `Event` argument may be passed when the `WANT_EVENT` flag is + present. + - `flags` - Flags controlling behavior. + - `selected_index` - The initially selected item. `-1` for no selection. + - `on_highlight` - Called every time the highlighted item in the quick panel is changed. + - `placeholder` - Text displayed in the filter input field before any query is typed. + """ ... def is_sidebar_visible(self) -> bool: + """ + Whether the sidebar is visible. + """ ... - def set_sidebar_visible(self, flag: bool) -> None: + def set_sidebar_visible(self, flag: bool, animate: bool = ...) -> None: + """ + Hides or shows the sidebar. + """ ... def is_minimap_visible(self) -> bool: + """ + Whether the minimap is visible. + """ ... def set_minimap_visible(self, flag: bool) -> None: + """ + Hides or shows the minimap. + """ ... def is_status_bar_visible(self) -> bool: + """ + Whether the status bar is visible. + """ ... def set_status_bar_visible(self, flag: bool) -> None: + """ + Hides or shows the status bar. + """ ... def get_tabs_visible(self) -> bool: + """ + Whether the tabs are visible. + """ ... def set_tabs_visible(self, flag: bool) -> None: + """ + Hides or shows the tabs. + """ ... def is_menu_visible(self) -> bool: + """ + Whether the menu is visible. + """ ... def set_menu_visible(self, flag: bool) -> None: + """ + Hides or shows the menu. + """ ... def folders(self) -> List[str]: + """ + A list of the currently open folders in this `Window`. + """ ... - def project_file_name(self) -> str: + def project_file_name(self) -> str | None: + """ + The name of the currently opened project file, if any. + """ ... - def project_data(self) -> Optional[dict]: + def project_data(self) -> bool | str | int | float | List[Any] | Dict[str, Any] | None: + """ + The project data associated with the current window. The data is in the same format as the contents of a + `.sublime-project` file. + """ ... - def set_project_data(self, v: Union[dict, None]) -> None: + def set_project_data(self, v: bool | str | int | float | List[Any] | Dict[str, Any] | None) -> None: + """ + Updates the project data associated with the current window. If the window is associated with a + `.sublime-project` file, the project file will be updated on disk, otherwise the window will store the data + internally. + """ + ... + + def workspace_file_name(self) -> str | None: + """ + The name of the currently opened workspace file, if any. + """ ... def settings(self) -> Settings: + """ + The `Settings` object for this `Window`. Any changes to this settings object will be specific to this window. + """ ... - # def template_settings(self): ... - def lookup_symbol_in_index(self, sym: str) -> List[str]: + def template_settings(self): + """ + Per-window settings that are persisted in the session, and duplicated into new windows. + """ ... - def lookup_symbol_in_open_files(self, sym: str) -> List[str]: + def symbol_locations( + self, + sym: str, + source: int = ..., + type: int = ..., + kind_id: int = ..., + kind_letter: str = ... + ) -> List[SymbolLocation]: + """ + Find all locations where the symbol `sym` is located. + + - `sym` - The name of the symbol. + - `source` - Sources which should be searched for the symbol. + - `type` - The type of symbol to find. + - `kind_id` - The kind ID of the symbol. + - `kind_letter` - The letter representing the kind of the symbol. + + Returns the found symbol locations. + """ ... - def extract_variables(self) -> dict: + @deprecated("Use symbol_locations() instead") + def lookup_symbol_in_index(self, sym: str) -> List[SymbolLocation]: + """ + All locations where the symbol is defined across files in the current project. + """ + ... + + @deprecated("Use symbol_locations() instead") + def lookup_symbol_in_open_files(self, sym: str) -> List[SymbolLocation]: + """ + All locations where the symbol is defined across open files. + """ + ... + + @deprecated("Use symbol_locations() instead") + def lookup_references_in_index(self, symbol: str) -> List[SymbolLocation]: + """ + All locations where the symbol is referenced across files in the current project. + """ + ... + + @deprecated("Use symbol_locations() instead") + def lookup_references_in_open_files(self, symbol: str) -> List[SymbolLocation]: + """ + All locations where the symbol is referenced across open files. + """ + ... + + def extract_variables(self) -> Dict[str, str]: + """ + Get the `dict` of contextual keys of the window. + + May contain: + + * `"packages"` + * `"platform"` + * `"file"` + * `"file_path"` + * `"file_name"` + * `"file_base_name"` + * `"file_extension"` + * `"folder"` + * `"project"` + * `"project_path"` + * `"project_name"` + * `"project_base_name"` + * `"project_extension"` + + This `dict` is suitable for use with `expand_variables()`. + """ ... def status_message(self, msg: str) -> None: + """ + Show a message in the status bar. + """ ... class Edit: - edit_token = ... # type: Any + """ + A grouping of buffer modifications. - def __init__(self, token: Any) -> None: + `Edit` objects are passed to `TextCommand`s, and can not be created by the user. Using an invalid `Edit` object, or + an `Edit` object from a different `View`, will cause the functions that require them to fail. + """ + edit_token: int = ... + + def __init__(self, token: int) -> None: ... class Region: - a = ... # type: int - b = ... # type: int - xpos = ... # type: int + """ + A singular selection region. This region has a order - `b` may be before or at `a`. + + Also commonly used to represent an area of the text buffer, where ordering and `xpos` are generally ignored. + """ + a: int = ... + """The first end of the region.""" + b: int = ... + """The second end of the region. In a selection this is the location of the caret. May be less than `a`.""" + xpos: float = ... + """ + In a selection this is the target horizontal position of the region. This affects behavior when pressing the up or + down keys. Use `-1` if undefined. + """ - def __init__(self, a: int, b: Optional[int] = ..., xpos: int = ...) -> None: + def __init__(self, a: int, b: int | None = ..., xpos: float = ...) -> None: ... def __len__(self) -> int: + """The size of the region.""" ... def __eq__(self, rhs: object) -> bool: + """Whether the two regions are identical. Ignores `xpos`.""" ... def __lt__(self, rhs: object) -> bool: + """Whether this region starts before the rhs. The end of the region is used to resolve ties.""" + ... + + def to_tuple(self) -> Tuple[int, int]: + """ + Returns a tuple of this region (excluding xpos). + + Use this to uniquely identify a region in a set or similar. Regions + can't be used for that directly as they may be mutated. + """ ... def empty(self) -> bool: + """Whether the region is empty, ie. `a == b`.""" ... def begin(self) -> int: + """The smaller of `a` and `b`.""" ... def end(self) -> int: + """The larger of `a` and `b`.""" ... def size(self) -> int: + """Equivalent to `__len__`.""" ... - def contains(self, x: 'Union[Region, int]') -> bool: + def contains(self, x: Region | int) -> bool: ... - def cover(self, rhs: 'Region') -> 'Region': + def cover(self, rhs: Region) -> Region: + """A `Region` spanning both regions.""" ... - def intersection(self, rhs: 'Region') -> 'Region': + def intersection(self, rhs: Region) -> Region: + """A `Region` covered by both regions.""" ... - def intersects(self, rhs: 'Region') -> bool: + def intersects(self, rhs: Region) -> bool: + """Whether the provided region intersects this region.""" ... - def to_tuple(self) -> Tuple[int, int]: + +class HistoricPosition: + """ + Provides a snapshot of the row and column info for a `Point`, before changes were made to a `View`. This is + primarily useful for replaying changes to a document. + """ + pt: int = ... + """The offset from the beginning of the `View`.""" + row: int = ... + """The row the `pt` was in when the `HistoricPosition` was recorded.""" + col: int = ... + """The column the `py` was in when the `HistoricPosition` was recorded, in Unicode characters.""" + col_utf16: int = ... + """The value of `col`, but in UTF-16 code units.""" + col_utf8: int = ... + """The value of `col`, but in UTF-8 code units.""" + + +class TextChange: + """ + Represents a change that occurred to the text of a `View`. This is primarily useful for replaying changes to a + document. + """ + a: HistoricPosition = ... + """The beginning `HistoricPosition` of the region that was modified.""" + b: HistoricPosition = ... + """The ending `HistoricPosition` of the region that was modified.""" + len_utf16: int = ... + """The length of the old contents, in UTF-16 code units.""" + len_utf8: int = ... + """The length of the old contents, in UTF-8 code units.""" + str: str = ... + """A string of the new contents of the region specified by `a` and `b`.""" + + def __init__(self, pa: HistoricPosition, pb: HistoricPosition, len_utf16: int, len_utf8: int, s: str) -> None: ... class Selection(Reversible): - view_id = ... # type: Any + """ + Maintains a set of sorted non-overlapping Regions. A selection may be empty. + + This is primarily used to represent the textual selection. + """ + view_id: int = ... - def __init__(self, id: Any) -> None: + def __init__(self, id: int) -> None: ... def __reversed__(self) -> Iterator[Region]: @@ -683,95 +1371,185 @@ class Selection(Reversible): ... def __len__(self) -> int: + """ + The number of regions in the selection. + """ ... def __getitem__(self, index: int) -> Region: + """ + The region at the given `index`. + """ ... def __delitem__(self, index: int) -> None: + """ + Delete the region at the given `index`. + """ ... - def __eq__(self, rhs: Any) -> bool: + def __eq__(self, rhs: Selection | None) -> bool: + """ + Whether the selections are identical. + """ ... - def __lt__(self, rhs: Any) -> bool: + def __lt__(self, rhs: Selection | None) -> bool: ... def __bool__(self) -> bool: + """ + The selection is `True` when not empty. + """ ... def is_valid(self) -> bool: + """ + Whether this selection is for a valid view. + """ ... def clear(self) -> None: + """ + Remove all regions from the selection. + """ ... - def add(self, x: Union[Region, int]) -> None: + def add(self, x: Region | int) -> None: + """ + Add a `Region` or point to the selection. It will be merged with the existing regions if intersecting. + """ ... - def add_all(self, regions: Iterator[Union[Region, int]]) -> None: + def add_all(self, regions: Iterable[Region | int]) -> None: + """ + Add all the regions from the given iterable. + """ ... def subtract(self, region: Region) -> None: + """ + Subtract a region from the selection, such that the whole region is no longer contained within the selection. + """ ... def contains(self, region: Region) -> bool: + """ + Whether the provided region is contained within the selection. + """ ... class Sheet: - sheet_id = ... # type: Any + """ + Represents a content container, i.e. a tab, within a window. Sheets may contain a `View`, or an image preview. + """ + sheet_id: int = ... - def __init__(self, id: Any) -> None: + def __init__(self, id: int) -> None: ... def __eq__(self, other: object) -> bool: ... def id(self) -> int: + """A number that uniquely identifies this sheet.""" ... - def window(self) -> Optional[Window]: + def window(self) -> Window | None: + """The `Window` containing this sheet. May be `None` if the sheet has been closed.""" ... - def group(self) -> int: + def view(self) -> View | None: + """The `View` contained within the sheet if any.""" ... - def view(self) -> 'Optional[View]': + def file_name(self) -> str | None: + """The full name of the file associated with the sheet, or `None` if it doesn't exist on disk.""" ... def is_semi_transient(self) -> bool: + """Whether this sheet is semi-transient.""" ... def is_transient(self) -> bool: + """ + Whether this sheet is exclusively transient. + + Note that a sheet may be both open as a regular file and be transient. In this case `is_transient` will still + return `False`. + """ ... + def is_selected(self) -> bool: + """Whether this sheet is currently selected.""" + ... -class HtmlSheet(Sheet): - sheet_id = ... # type: Any + def group(self) -> int | None: + """The (layout) group that the sheet is contained within.""" + ... - def __init__(self, id: Any) -> None: + def close(self, on_close: Callable[[bool], None] = ...) -> None: + """Closes the sheet.""" ... + +class TextSheet(Sheet): + """ + Specialization for sheets containing editable text, ie. a `View`. + """ def set_name(self, name: str) -> None: + """Set the name displayed in the tab. Only affects unsaved files.""" + ... + + +class ImageSheet(Sheet): + """ + Specialization for sheets containing an image. + """ + ... + + +class HtmlSheet(Sheet): + """ + Specialization for sheets containing HTML. + """ + def set_name(self, name: str) -> None: + """Set the name displayed in the tab.""" ... def set_contents(self, contents: str) -> None: + """Set the HTML content of the sheet.""" ... class ContextStackFrame: - context_name = ... # type: str - source_file = ... # type: str - source_location = ... # type: Tuple[int, int] + """ + Represents a single stack frame in the syntax highlighting. + """ + context_name: str = ... + """The name of the context.""" + source_file: str = ... + """The name of the file the context is defined in.""" + source_location: Tuple[int, int] = ... + """ + The location of the context inside the source file as a pair of row and column. Maybe be `(-1, -1)` if the location + is unclear, like in tmLanguage based syntaxes. + """ class View: - view_id = ... # type: Any - selection = ... # type: Any - settings_object = ... # type: Any + """ + Represents a view into a text `Buffer`. + + Note that multiple views may refer to the same `Buffer`, but they have their own unique selection and geometry. A + list of these may be gotten using `View.clones()` or `Buffer.views()`. + """ + view_id: int = ... + selection: Selection = ... + settings_object: Settings | None = ... - def __init__(self, id: Any) -> None: + def __init__(self, id: int) -> None: ... def __len__(self) -> int: @@ -783,347 +1561,1083 @@ class View: def __bool__(self) -> bool: ... - def sheet(self) -> Sheet: + def id(self) -> int: + """ + A number that uniquely identifies this view. + """ ... - def syntax(self) -> Any: + def buffer_id(self) -> int: + """ + A number that uniquely identifies this view's `Buffer`. + """ ... - def element(self) -> Optional[str]: + def buffer(self) -> Buffer: + """ + The `Buffer` for which this is a view. + """ ... - def id(self) -> int: + def sheet_id(self) -> int: + """ + The ID of the `Sheet` for this `View`, or `0` if not part of any sheet. + """ ... - def buffer(self) -> "Optional[Buffer]": + def sheet(self) -> Sheet | None: + """ + The `Sheet` for this view, if displayed in a sheet. + """ ... - def buffer_id(self) -> int: + def element(self) -> str | None: + """ + Returns `None` for normal views that are part of a `Sheet`. For views that comprise part of the UI a string is + returned from the following list: + + * `"console:input"` - The console input. + * `"goto_anything:input"` - The input for the Goto Anything. + * `"command_palette:input"` - The input for the Command Palette. + * `"find:input"` - The input for the Find panel. + * `"incremental_find:input"` - The input for the Incremental Find panel. + * `"replace:input:find"` - The Find input for the Replace panel. + * `"replace:input:replace"` - The Replace input for the Replace panel. + * `"find_in_files:input:find"` - The Find input for the Find in Files panel. + * `"find_in_files:input:location"` - The Where input for the Find in Files panel. + * `"find_in_files:input:replace"` - The Replace input for the Find in Files panel. + * `"find_in_files:output"` - The output panel for Find in Files (buffer or output panel). + * `"input:input"` - The input for the Input panel. + * `"exec:output"` - The output for the exec command. + * `"output:output"` - A general output panel. + + The console output, indexer status output and license input controls are not accessible via the API. + """ ... def is_valid(self) -> bool: + """ + Check whether this view is still valid. Will return `False` for a closed view, for example. + """ ... def is_primary(self) -> bool: + """ + Whether view is the primary view into a `Buffer`. Will only be `False` if the user has opened multiple views + into a file. + """ + ... + + def window(self) -> Window | None: + """ + A reference to the window containing the view, if any. + """ ... - def window(self) -> Optional[Window]: + def clones(self) -> List[View]: + """ + All the other views into the same `Buffer`. + """ ... - def file_name(self) -> Optional[str]: + def file_name(self) -> str | None: + """ + The full name of the file associated with the sheet, or `None` if it doesn't exist on disk. + """ ... - def close(self) -> None: + def close(self, on_close: Callable[[bool], None] = ...) -> None: + """ + Closes the view. + """ ... def retarget(self, new_fname: str) -> None: + """ + Change the file path the buffer will save to. + """ ... def name(self) -> str: + """ + The name assigned to the buffer, if any. + """ ... def set_name(self, name: str) -> None: + """ + Assign a name to the buffer. Displayed as in the tab for unsaved files. + """ + ... + + def reset_reference_document(self) -> None: + """ + Clears the state of the incremental diff for the view. + """ + ... + + def set_reference_document(self, reference: str) -> None: + """ + Uses the string reference to calculate the initial diff for the incremental diff. + """ ... def is_loading(self) -> bool: + """ + Whether the buffer is still loading from disk, and not ready for use. + """ ... def is_dirty(self) -> bool: + """ + Whether there are any unsaved modifications to the buffer. + """ ... def is_read_only(self) -> bool: + """ + Whether the buffer may not be modified. + """ ... def set_read_only(self, read_only: bool) -> None: + """ + Set the read only property on the buffer. + """ ... def is_scratch(self) -> bool: + """ + Whether the buffer is a scratch buffer. See `set_scratch()`. + """ ... def set_scratch(self, scratch: bool) -> None: + """ + Sets the scratch property on the buffer. When a modified scratch buffer is closed, it will be closed without + prompting to save. Scratch buffers never report as being dirty. + """ ... def encoding(self) -> str: + """ + The encoding currently associated with the buffer. + """ ... def set_encoding(self, encoding_name: str) -> None: + """ + Applies a new encoding to the file. This will be used when the file is saved. + """ ... def line_endings(self) -> str: + """ + The encoding currently associated with the file. + """ ... def set_line_endings(self, line_ending_name: str) -> None: + """ + Sets the line endings that will be applied when next saving. + """ ... def size(self) -> int: + """ + The number of character in the file. + """ ... - # def begin_edit(self, edit_token, cmd, args: Optional[Any] = ...) -> Edit: ... - # def end_edit(self, edit: Edit) -> None: ... - def is_in_edit(self) -> bool: - ... + # def begin_edit(self, edit_token: int, cmd: str, args: Dict[str, Any] | None = ...) -> Edit: + # ... + + # def end_edit(self, edit: Edit) -> None: + # ... + + # def is_in_edit(self) -> bool: + # ... def insert(self, edit: Edit, pt: int, text: str) -> None: + """ + Insert the given string into the buffer. + + - `edit` - An `Edit` object provided by a `TextCommand`. + - `point` - The text point in the view where to insert. + - `text` - The text to insert. + + Returns the actual number of characters inserted. This may differ from the provided text due to tab translation. + + Raises `ValueError` if the `Edit` object is in an invalid state, ie. outside of a `TextCommand`. + """ ... def erase(self, edit: Edit, r: Region) -> None: + """ + Erases the contents of the provided `Region` from the buffer. + """ ... def replace(self, edit: Edit, r: Region, text: str) -> None: + """ + Replaces the contents of the `Region` in the buffer with the provided string. + """ ... def change_count(self) -> int: + """ + The current change count. + + Each time the buffer is modified, the change count is incremented. The change count can be used to determine if + the buffer has changed since the last it was inspected. + """ + ... + + def change_id(self) -> Tuple[int, int, int]: + """ + Get a 3-element tuple that can be passed to `transform_region_from()` to obtain a region equivalent to a region + of the view in the past. This is primarily useful for plugins providing text modification that must operate in + an asynchronous fashion and must be able to handle the view contents changing between the request and response. + """ ... - def run_command(self, cmd: str, args: Optional[Any] = ...) -> None: + def transform_region_from(self, r: Region, when: Tuple[int, int, int]) -> Region: + """ + Transforms a region from a previous point in time to an equivalent region in the current state of the `View`. + `when` must have been obtained from `change_id()` at the point in time the region is from. + """ + ... + + def run_command(self, cmd: str, args: Dict[str, Any] | None = ...) -> None: + """ + Run the named `TextCommand` with the (optional) given `args`. + """ ... def sel(self) -> Selection: + """ + The views `Selection`. + """ ... - def substr(self, x: Union[Region, int]) -> str: + def substr(self, x: Region | int) -> str: + """ + The string at the point or within the `Region` provided. + """ ... - def find(self, pattern: str, start_pt: int, flags: int = ...) -> Optional[Region]: + def find(self, pattern: str, start_pt: int, flags: int = ...) -> Region: + """ + The first `Region` matching the provided pattern. + + - `pattern` - The regex or literal pattern to search by. + - `start_pt` - The point to start searching from. + - `flags` - Controls various behaviors of find. + """ ... - def find_all(self, pattern: str, flags: int = ..., fmt: Optional[Any] = ..., - extractions: Optional[Any] = ...) -> 'List[Region]': + def find_all( + self, + pattern: str, + flags: int = ..., + fmt: str | None = ..., + extractions: List[str] | None = ... + ) -> List[Region]: + """ + All (non-overlapping) regions matching the pattern. + + - `pattern` - The regex or literal pattern to search by. + - `flags` - Controls various behaviors of find. + - `fmt` - When not `None` all matches in the `extractions` list will be formatted with the provided format + string. + - `extractions` - An optionally provided list to place the contents of the find results into. + """ ... def settings(self) -> Settings: + """ + The view's `Settings` object. Any changes to it will be private to this view. + """ + ... + + def meta_info(self, key: str, pt: int) -> bool | str | int | float | List[Any] | Dict[str, Any] | None: + """ + Look up the preference `key` for the scope at the provided point `pt` from all matching `.tmPreferences` files. + + Examples of keys are `TM_COMMENT_START` and `showInSymbolList`. + """ + ... + + def extract_tokens_with_scopes(self, r: Region) -> List[Tuple[Region, str]]: + """ + A list of pairs containing the `Region` and the scope of each token. + + - `region` - The region from which to extract tokens and scopes. + """ ... - # def meta_info(self, key, pt: int): ... def extract_scope(self, pt: int) -> Region: + """ + The extent of the syntax scope name assigned to the character at the given point `pt`, narrower syntax scope + names included. + """ + ... + + def expand_to_scope(self, pt: int, selector: str) -> Region | None: + """ + Expand by the provided scope selector from the `Point`. + + - `pt` - The point from which to expand. + - `selector` - The scope selector to match. + + Returns the matched `Region`, if any. + """ ... def scope_name(self, pt: int) -> str: + """ + The syntax scope name assigned to the character at the given point. + """ ... - def context_backtrace(self, pt: int) -> Union[List[ContextStackFrame], List[str]]: + def context_backtrace(self, pt: int) -> List[ContextStackFrame]: + """ + Get a backtrace of `ContextStackFrame`s at the provided point `pt`. + + Note this function is particularly slow. + """ ... def match_selector(self, pt: int, selector: str) -> bool: + """ + Whether the provided scope selector matches the point `pt`. + """ ... def score_selector(self, pt: int, selector: str) -> int: + """ + Equivalent to + ```python + sublime.score_selector(view.scope_name(pt), selector) + ``` + """ ... def find_by_selector(self, selector: str) -> List[Region]: + """ + Find all regions in the file matching the given selector. + """ + ... + + def style(self): + """ + The global style settings for the view. All colors are normalized to the six character hex form with a leading + hash, e.g. `#ff0000`. + """ ... - # def indented_region(self, pt: int): ... - # def indentation_level(self, pt: int): ... + def style_for_scope(self, scope: str) -> Dict[str, Any]: + """ + Accepts a string scope name and returns a `dict` of style information including the keys: + + * `"foreground"` + * `"background"` (only if set and different from global background) + * `"bold"` + * `"italic"` + * `"glow"` + * `"underline"` + * `"stippled_underline"` + * `"squiggly_underline"` + * `"source_line"` + * `"source_column"` + * `"source_file"` + + The foreground and background colors are normalized to the six character hex form with a leading hash, e.g. + `#ff0000`. + """ + ... + + # def indented_region(self, pt: int) -> Region: + # ... + + # def indentation_level(self, pt: int) -> int: + # ... + def has_non_empty_selection_region(self) -> bool: ... def lines(self, r: Region) -> List[Region]: + """ + A list of lines (in sorted order) intersecting the provided `Region`. + """ ... def split_by_newlines(self, r: Region) -> List[Region]: + """ + Splits the region up such that each `Region` returned exists on exactly one line. + """ ... - def line(self, x: Union[Region, int]) -> Region: + def line(self, x: Region | int) -> Region: + """ + The line that contains the point or an expanded `Region` to the beginning/end of lines, excluding the newline + character. + """ ... - def full_line(self, x: Union[Region, int]) -> Region: + def full_line(self, x: Region | int) -> Region: + """ + The line that contains the point or an expanded `Region` to the beginning/end of lines, including the newline + character. + """ ... - def word(self, x: Union[Region, int]) -> Region: + def word(self, x: Region | int) -> Region: + """ + The word that contains the provided point. If a `Region` is provided it's beginning/end are expanded to word + boundaries. + """ ... def classify(self, pt: int) -> int: + """ + Classify the provided point. + """ ... - def find_by_class(self, pt: int, forward: bool, classes: int, separators: str = ...) -> int: - ... + def find_by_class( + self, + pt: int, + forward: bool, + classes: int, + separators: str = ..., + sub_word_separators: str = ... + ) -> int: + """ + Find the next location that matches the provided classification. + + - `pt` - The point to start searching from. + - `forward` - Whether to search forward or backwards. + - `classes` - The classification to search for. + - `separators` - The word separators to use when classifying. + - `sub_word_separators` - The sub-word separators to use when classifying. + """ + ... + + def expand_by_class( + self, + x: Region | int, + classes: int, + separators: str = ..., + sub_word_separators: str = ... + ) -> Region: + """ + Expand the provided point or `Region` to the left and right until each side lands on a location that matches the + provided classification. - def expand_by_class(self, x: Union[Region, int], classes: int, separators: str = ...) -> Region: + - `classes` - The classification to search by. + - `separators` - The word separators to use when classifying. + - `sub_word_separators` - The sub-word separators to use when classifying. + """ ... def rowcol(self, tp: int) -> Tuple[int, int]: + """ + Calculates the 0-based line and column numbers of the point. Column numbers are returned as number of Unicode + characters. + """ ... def rowcol_utf8(self, tp: int) -> Tuple[int, int]: + """ + Calculates the 0-based line and column numbers of the point. Column numbers are returned as UTF-8 code units. + """ ... def rowcol_utf16(self, tp: int) -> Tuple[int, int]: + """ + Calculates the 0-based line and column numbers of the point. Column numbers are returned as UTF-16 code units. + """ ... - def text_point(self, row: int, col: int, *, clamp_column: bool = False) -> int: + def text_point(self, row: int, col: int, *, clamp_column: bool = ...) -> int: + """ + Calculates the character offset of the given, 0-based, `row` and `col`. `col` is interpreted as the number of + Unicode characters to advance past the beginning of the row. + + - `clamp_column` - Whether `col` should be restricted to valid values for the given `row`. + """ ... - def text_point_utf8(self, row: int, col_utf8: int, *, clamp_column: bool = False) -> int: + def text_point_utf8(self, row: int, col_utf8: int, *, clamp_column: bool = ...) -> int: + """ + Calculates the character offset of the given, 0-based, `row` and `col`. `col` is interpreted as the number of + UTF-8 code units to advance past the beginning of the row. + + - `clamp_column` - Whether `col` should be restricted to valid values for the given `row`. + """ ... - def text_point_utf16(self, row: int, col_utf16: int, *, clamp_column: bool = False) -> int: + def text_point_utf16(self, row: int, col_utf16: int, *, clamp_column: bool = ...) -> int: + """ + Calculates the character offset of the given, 0-based, `row` and `col`. `col` is interpreted as the number of + UTF-16 code units to advance past the beginning of the row. + + - `clamp_column` - Whether `col` should be restricted to valid values for the given `row`. + """ ... def visible_region(self) -> Region: + """ + The currently visible area of the view. + """ ... - def show(self, x: Union[Selection, Region, int], show_surrounds: bool = True, keep_to_left: bool = False, - animate: bool = True) -> None: + def show( + self, + x: Region | Selection | int, + show_surrounds: bool = ..., + keep_to_left: bool = ..., + animate: bool = ... + ) -> None: + """ + Scroll the view to show the given location. + + - `location` - The location to scroll the view to. For a `Selection` only the first `Region` is shown. + - `show_surrounds` - Whether to show the surrounding context around the location. + - `keep_to_left` - Whether the view should be kept to the left, if horizontal scrolling is possible. + - `animate` - Whether the scrolling should be animated. + """ ... - def show_at_center(self, x: Union[Selection, Region, int], animate: bool = True) -> None: + def show_at_center(self, x: Region | int, animate: bool = ...) -> None: + """ + Scroll the view to center on the location. + + - `x` - Which point or `Region` to scroll to. + - `animate` - Whether the scrolling should be animated. + """ ... def viewport_position(self) -> Tuple[int, int]: + """ + The offset of the viewport in layout coordinates. + """ ... def set_viewport_position(self, xy: Tuple[int, int], animate: bool = ...) -> None: + """ + Scrolls the viewport to the given layout position. + """ ... def viewport_extent(self) -> Tuple[int, int]: + """ + The width and height of the viewport. + """ ... def layout_extent(self) -> Tuple[int, int]: + """ + The width and height of the layout. + """ ... def text_to_layout(self, tp: int) -> Tuple[int, int]: + """ + Convert a text point to a layout position. + """ + ... + + def text_to_window(self, tp: int) -> Tuple[int, int]: + """ + Convert a text point to a window position. + """ ... def layout_to_text(self, xy: Tuple[int, int]) -> int: + """ + Convert a layout position to a text point. + """ + ... + + def layout_to_window(self, xy: Tuple[int, int]) -> Tuple[int, int]: + """ + Convert a layout position to a window position. + """ ... def window_to_layout(self, xy: Tuple[int, int]) -> Tuple[int, int]: + """ + Convert a window position to a layout position. + """ ... def window_to_text(self, xy: Tuple[int, int]) -> int: + """ + Convert a window position to a text point. + """ ... def line_height(self) -> float: + """ + The light height used in the layout. + """ ... def em_width(self) -> float: + """ + The typical character width used in the layout. + """ ... def is_folded(self, sr: Region) -> bool: + """ + Whether the provided `Region` is folded. + """ ... - # def folded_regions(self): ... - def fold(self, x: Union[Region, List[Region]]) -> bool: + def folded_regions(self) -> List[Region]: + """ + The list of folded regions. + """ ... - def unfold(self, x: Union[Region, List[Region]]) -> List[Region]: + def fold(self, x: Region | List[Region]) -> bool: + """ + Fold the provided `Region`(s). + + Returns `False` if the regions were already folded. + """ ... - def add_regions(self, key: str, regions: List[Region], scope: str = ..., icon: str = ..., flags: int = ..., - annotations: List[str] = ..., annotation_color: str = ..., - on_navigate: Callable[[str], None] = ..., on_close: Callable[[], None] = ...) -> None: + def unfold(self, x: Region | List[Region]) -> List[Region]: + """ + Unfold all text in the provided `Region`(s). + + Returns the unfolded regions. + """ + ... + + def add_regions( + self, + key: str, + regions: List[Region], + scope: str = ..., + icon: str = ..., + flags: int = ..., + annotations: List[str] = ..., + annotation_color: str = ..., + on_navigate: Callable[[str], None] = ..., + on_close: Callable[[], None] = ... + ) -> None: + """ + Adds visual indicators to regions of text in the view. Indicators include icons in the gutter, underlines under + the text, borders around the text and annotations. Annotations are drawn aligned to the right-hand edge of the + view and may contain HTML markup. + + - `key` - An identifier for the collection of regions. If a set of regions already exists for this key they will + be overridden. + - `regions` - The list of regions to add. These should not overlap. + - `scope` - An optional string used to source a color to draw the regions in. The scope is matched against the + color scheme. Examples include: `"invalid"` and `"string"`. + See [Scope Naming](https://www.sublimetext.com/docs/scope_naming.html) for a list of common scopes. If the + scope is empty, the regions won't be drawn. Also supports the following pseudo-scopes, to allow picking the + closest color from the user‘s color scheme: + - `"region.redish"` + - `"region.orangish"` + - `"region.yellowish"` + - `"region.greenish"` + - `"region.cyanish"` + - `"region.bluish"` + - `"region.purplish"` + - `"region.pinkish"` + - `icon` - An optional string specifying an icon to draw in the gutter next to each region. The icon will be + tinted using the color associated with the `scope`. Standard icon names are `"dot"`, `"circle"` and + `"bookmark"`. The icon may also be a full package-relative path, such as + `"Packages/Theme - Default/dot.png"`. + - `flags` - Flags specifying how the region should be drawn, among other behavior. + - `annotations` - An optional collection of strings containing HTML documents to display along the right-hand + edge of the view. There should be the same number of annotations as regions. See minihtml for supported + HTML. + - `annotation_color` - An optional string of the CSS color to use when drawing the left border of the annotation. + See [minihtml Reference: Colors](https://www.sublimetext.com/docs/minihtml.html#colors) for supported color + formats. + - `on_navigate` - Called when a link in an annotation is clicked. Will be passed the `href` of the link. + - `on_close` - Called when the annotations are closed. + """ ... def get_regions(self, key: str) -> List[Region]: + """ + The regions associated with the given `key`, if any. + """ ... def erase_regions(self, key: str) -> None: + """ + Remove the regions associated with the given `key`. + """ ... - # def add_phantom(self, key: str, region: Region, content: str, layout, on_navigate: Optional[Any] = ...): ... - # def erase_phantoms(self, key: str) -> None: ... - # def erase_phantom_by_id(self, pid) -> None: ... - # def query_phantom(self, pid): ... - # def query_phantoms(self, pids): ... - def assign_syntax(self, syntax_file: str) -> None: + # def add_phantom( + # self, key: str, region: Region, content: str, layout: int, on_navigate: Callable[[str], None] | None = ... + # ) -> int: + # ... + + # def erase_phantoms(self, key: str) -> None: + # ... + + # def erase_phantom_by_id(self, pid: int) -> None: + # ... + + # def query_phantom(self, pid: int) -> List[Region]: + # ... + + # def query_phantoms(self, pids: List[int]) -> List[Region]: + # ... + + def assign_syntax(self, syntax: str | Syntax) -> None: + """ + Changes the syntax used by the view. `syntax` may be a packages path to a syntax file, a `scope:` specifier + string, or a `Syntax` object. + """ ... + @deprecated("Use assign_syntax(...) instead") def set_syntax_file(self, syntax_file: str) -> None: ... + def syntax(self) -> Any: + """ + The syntax assigned to the buffer. + """ + ... + + @deprecated("Use symbol_regions() instead") def symbols(self) -> List[Tuple[Region, str]]: ... - # def get_symbols(self): ... - # def indexed_symbols(self): ... + @deprecated("Use symbol_regions() instead") + def get_symbols(self) -> List[Tuple[Region, str]]: + ... + + @deprecated("Use indexed_symbol_regions() instead") + def indexed_symbols(self) -> List[Tuple[Region, str]]: + ... + + @deprecated("Use indexed_symbol_regions() instead") + def indexed_references(self) -> List[Tuple[Region, str]]: + ... + + def symbol_regions(self) -> List[SymbolRegion]: + """ + Info about symbols that are part of the view's symbol list. + """ + ... + + def indexed_symbol_regions(self, type: int = ...) -> List[SymbolRegion]: + """ + Info about symbols that are indexed. + + - `type` - The type of symbol to return. + """ + ... + def set_status(self, key: str, value: str) -> None: + """ + Add the status `key` to the view. The `value` will be displayed in the status bar, in a comma separated list of + all status values, ordered by key. Setting the `value` to `""` will clear the status. + """ ... def get_status(self, key: str) -> str: + """ + The previous assigned value associated with the given `key`, if any. + """ ... def erase_status(self, key: str) -> None: + """ + Clear the status associated with the provided `key`. + """ ... - # def extract_completions(self, prefix: str, tp: int = ...): ... - # def find_all_results(self): ... - # def find_all_results_with_text(self): ... - def command_history(self, delta: int, modifying_only: bool = ...) -> 'Tuple[str, dict, int]': + def extract_completions(self, prefix: str, tp: int = ...) -> List[str]: + """ + Get a list of word-completions based on the contents of the view. + + - `prefix` - The prefix to filter words by. + - `tp` - The point by which to weigh words. Closer words are preferred. + """ + ... + + # def find_all_results(self) -> List[Tuple[str, int, int]]: + # ... + + # def find_all_results_with_text(self) -> List[Tuple[str, int, int]]: + # ... + + def command_history(self, delta: int, modifying_only: bool = ...) -> Tuple[Optional[str], Optional[dict], int]: + """ + Get info on previous run commands stored in the undo/redo stack. + + - `delta` - The offset into the undo/redo stack. Positive values indicate to look in the redo stack for commands. + - `modifying_only` - Whether only commands that modify the text buffer are considered. + + Returns the command name, command arguments and repeat count for the history entry. If the undo/redo history + doesn't extend far enough, then `(None, None, 0)` will be returned. + """ ... def overwrite_status(self) -> bool: + """ + The overwrite status, which the user normally toggles via the insert key. + """ ... def set_overwrite_status(self, value: bool) -> None: + """ + Set the overwrite status. + """ ... - def show_popup_menu(self, items: List[str], on_select: 'Callable', flags: int = ...) -> None: + def show_popup_menu(self, items: List[str], on_select: Callable[[int], None], flags: int = ...) -> None: + """ + Show a popup menu at the caret, for selecting an item in a list. + + - `items` - The list of entries to show in the list. + - `on_select` - Called once with the index of the selected item. If the popup was cancelled `-1` is passed + instead. + - `flags` - must be `0`, currently unused. + """ ... - def show_popup(self, - content: str, - flags: int = ..., - location: int = ..., - max_width: int = ..., - max_height: int = ..., - on_navigate: Optional[Any] = ..., - on_hide: Optional[Any] = ...) -> None: + def show_popup( + self, + content: str, + flags: int = ..., + location: int = ..., + max_width: int = ..., + max_height: int = ..., + on_navigate: Callable[[str], None] | None = ..., + on_hide: Callable[[], None] | None = ... + ) -> None: + """ + Show a popup displaying HTML content. + + - `content` - The HTML content to display. + - `flags` - Flags controlling popup behavior. + - `location` - The point at which to display the popup. If `-1` the popup is shown at the current postion of the + caret. + - `max_width` - The maximum width of the popup. + - `max_height` - The maximum height of the popup. + - `on_navigate` - Called when a link is clicked in the popup. Passed the value of the `href` attribute of the + clicked link. + - `on_hide` - Called when the popup is hidden. + """ ... def update_popup(self, content: str) -> None: + """ + Update the content of the currently visible popup. + """ ... def is_popup_visible(self) -> bool: + """ + Whether a popup is currently shown. + """ ... def hide_popup(self) -> None: + """ + Hide the current popup. + """ ... def is_auto_complete_visible(self) -> bool: + """ + Whether the auto-complete menu is currently visible. + """ ... - def change_id(self) -> Any: # opaque handle object + def preserve_auto_complete_on_focus_lost(self): + """ + Sets the auto complete popup state to be preserved the next time the `View` loses focus. When the `View` regains + focus, the auto complete window will be re-shown, with the previously selected entry pre-selected. + """ ... - def transform_region_from(self, region: Region, change_id: Any) -> Region: + def export_to_html( + self, + regions=None, + minihtml: bool = ..., + enclosing_tags: bool = ..., + font_size: bool = ..., + font_family: bool = ... + ) -> str: + """ + Generates an HTML string of the current view contents, including styling for syntax highlighting. + + - `regions` - The region(s) to export. By default the whole view is exported. + - `minihtml` - Whether the exported HTML should be compatible with minihtml. + - `enclosing_tags` - Whether a `
` with base-styling is added. Note that without this no background color is + set. + - `font_size` - Whether to include the font size in the top level styling. Only applies when `enclosing_tags` is + `True`. + - `font_family` - Whether to include the font family in the top level styling. Only applies when `enclosing_tags` + is `True`. + """ ... - def style_for_scope(self, scope: str) -> Dict[str, Any]: + def clear_undo_stack(self) -> None: + """ + Clear the undo/redo stack. + """ ... class Buffer: - buffer_id = ... # type: int + """ + Represents a text buffer. Multiple `View` objects may share the same buffer. + """ + buffer_id: int = ... + + def __init__(self, id: int) -> None: + ... + + def __eq__(self, other: object) -> bool: + ... + + def id(self) -> int: + """ + Returns a number that uniquely identifies this buffer. + """ + ... + + def file_name(self) -> str | None: + """ + The full name file the file associated with the buffer, or `None` if it doesn't exist on disk. + """ + ... + + def views(self) -> List[View]: + """ + Returns a list of all views that are associated with this buffer. + """ + ... + + def primary_view(self) -> View: + """ + The primary view associated with this buffer. + """ + ... + + + +class Settings: + """ + A `dict` like object that a settings hierarchy. + """ + settings_id: int = ... def __init__(self, id: int) -> None: ... - def views(self) -> Optional[List[View]]: + def get( + self, + key: str, + default: bool | str | int | float | List[Any] | Dict[str, Any] | None = ... + ) -> Any: + """ + Returns the named setting. + """ + ... + + def has(self, key: str) -> bool: + """ + Returns whether the provided `key` is set. + """ + ... + + def set(self, key: str, value: bool | str | int | float | List[Any] | Dict[str, Any] | None) -> None: + """ + Set the named `key` to the provided `value`. + """ ... - def primary_view(self) -> Optional[View]: + def erase(self, key: str) -> None: + """ + Deletes the provided `key` from the setting. Note that a parent setting may also provide this key, thus deleting + may not entirely remove a key. + """ + ... + + def add_on_change(self, tag: str, callback: Callable[[], None]) -> None: + """ + Register a callback to be run whenever a setting is changed. + + - `tag` - A string associated with the callback. For use with `clear_on_change`. + - `callback` - A callable object to be run when a setting is changed. + """ + ... + + def clear_on_change(self, tag: str) -> None: + """ + Remove all callbacks associated with the provided `tag`. See `add_on_change`. + """ ... class Phantom: - region = ... # type: Region - content = ... # type: Any - layout = ... # type: Any - on_navigate = ... # type: Any - id = ... # type: Any + """ + Represents an minihtml-based decoration to display non-editable content interspersed in a `View`. Used with + `PhantomSet` to actually add the phantoms to the `View`. Once a `Phantom` has been constructed and added to the + `View`, changes to the attributes will have no effect. + """ + region: Region = ... + """The `Region` associated with the phantom. The phantom is displayed at the start of the `Region`.""" + content: str = ... + """The HTML content of the phantom.""" + layout: int = ... + """How the phantom should be placed relative to the `region`.""" + on_navigate: Callable[[str], None] | None = ... + """Called when a link in the HTML is clicked. The value of the `href` attribute is passed.""" - def __init__(self, region: Region, content: str, layout: int, on_navigate: Optional[Any] = ...) -> None: + def __init__( + self, + region: Region, + content: str, + layout: int, + on_navigate: Callable[[str], None] | None = ... + ) -> None: ... - def __eq__(self, rhs: object) -> bool: + def __eq__(self, rhs: 'Phantom') -> bool: + ... + + def to_tuple(self) -> Tuple[Tuple[int, int], str, int, Optional[Callable[[str], None]]]: + """ + Returns a tuple of this phantom containing the region, content, layout + and callback. + + Use this to uniquely identify a phantom in a set or similar. Phantoms + can't be used for that directly as they are mutable. + """ ... class PhantomSet: - view = ... # type: View - key = ... # type: Any - phantoms = ... # type: Any + """ + A collection that manages `Phantom` objects and the process of adding them, updating them and removing them from a + `View`. + """ + view: View = ... + """The `View` the phantom set is attached to.""" + key: str = ... + """A string used to group the phantoms together.""" + phantoms: List[Phantom] = ... def __init__(self, view: View, key: str = ...) -> None: ... @@ -1131,54 +2645,281 @@ class PhantomSet: def __del__(self) -> None: ... - def update(self, new_phantoms: Sequence[Phantom]) -> None: + def update(self, new_phantoms: Iterable[Phantom]) -> None: + """ + Update the set of phantoms. If the `Phantom.region` of existing phantoms have changed they will be moved; new + phantoms are added and ones not present are removed. + """ ... -class HistoricPosition: - pt = ... # type: int - row = ... # type: int - col = ... # type: int - col_utf16 = ... # type: int - col_utf8 = ... # type: int +class Html: + """ + Used to indicate that a string is formatted as HTML. + """ + data: str = ... + def __init__( + self, + data: str, + ) -> None: + ... -class TextChange: - a = ... # type: HistoricPosition - b = ... # type: HistoricPosition - str = ... # type: str - len_utf8 = ... # type: int - len_utf16 = ... # type: int + +class CompletionList: + """ + Represents a list of completions, some of which may be in the process of being asynchronously fetched. + """ + target = ... + completions: List[str] | List[Tuple[str, str]] | List[CompletionItem] | None = ... + flags: int = ... + + def __init__( + self, + completions: List[str] | List[Tuple[str, str]] | List[CompletionItem] | None = ..., + flags: int = ... + ) -> None: + """ + - `completions` - If `None` is passed, the method `set_completions()` must be called before the completions will + be displayed to the user. + - `flags` - Flags controlling auto-complete behavior. + """ + ... + + def set_completions(self, completions: List[str] | List[Tuple[str, str]] | List[CompletionItem], flags: int = ...) -> None: + """ + Sets the list of completions, allowing the list to be displayed to the user. + """ + ... + + +class CompletionItem: + """ + Represents an available auto-completion item. + """ + trigger: str = ... + """Text to match against the user's input.""" + annotation: str = ... + """A hint to draw to the right-hand side of the trigger.""" + completion: str = ... + """Text to insert if the completion is specified. If empty the `trigger` will be inserted instead.""" + completion_format: int = ... + """The format of the completion.""" + kind: Tuple[int, str, str] = ... + """The kind of the completion.""" + details: str = ... + """ + An optional minihtml description of the completion, shown in the detail pane at the bottom of the auto complete + window. + """ + flags: int = ... + + def __init__( + self, + trigger: str, + annotation: str = ..., + completion: str = ..., + completion_format: int = ..., + kind: Tuple[int, str, str] = ..., + details: str = ..., + flags: int = ... + ) -> None: + ... + + def __eq__(self, rhs: 'CompletionItem') -> bool: + ... + + @classmethod + def snippet_completion( + cls, + trigger: str, + snippet: str, + annotation: str = ..., + kind: Tuple[int, str, str] = ..., + details: str = ... + ) -> 'CompletionItem': + """ + Specialized constructor for snippet completions. The `completion_format` is always `COMPLETION_FORMAT_SNIPPET`. + """ + ... + + @classmethod + def command_completion( + cls, + trigger: str, + command: str, + args: Dict[str, Any] = ..., + annotation: str = ..., + kind: Tuple[int, str, str] = ..., + details: str = ... + ) -> 'CompletionItem': + """ + Specialized constructor for command completions. The `completion_format` is always `COMPLETION_FORMAT_COMMAND`. + """ + ... + + +def list_syntaxes() -> List[Syntax]: + """List all known syntaxes. + + Returns a list of `Syntax`. + """ + ... + + +def syntax_from_path(path: str) -> Syntax | None: + """Get the syntax for a specific path. + + Returns a Syntax or `None`. + """ + ... + + +def find_syntax_by_name(name: str) -> List[Syntax]: + """Find syntaxes with the specified name. + + Name must match exactly. Return a list of `Syntax`. + """ + ... + + +def find_syntax_by_scope(scope: str) -> List[Syntax]: + """Find syntaxes with the specified scope. + + Scope must match exactly. Return a list of `Syntax`. + """ + ... + + +def find_syntax_for_file(path: str, first_line: str = ...) -> Syntax | None: + """Find the syntax to use for a path. + + Uses the file extension, various application settings and optionally the + first line of the file to pick the right syntax for the file. + + Returns a `Syntax`. + """ + ... + + +class Syntax: + """ + Contains information about a syntax. + """ + path: str = ... + """The packages path to the syntax file.""" + name: str = ... + """The name of the syntax.""" + hidden: bool = ... + """If the syntax is hidden from the user.""" + scope: str = ... + """The base scope name of the syntax.""" + + def __init__(self, path: str, name: str, hidden: bool, scope: str) -> None: + ... + + def __eq__(self, other: object) -> bool: + ... class QuickPanelItem: + """ + Represents a row in the quick panel, shown via `Window.show_quick_panel()`. + """ + trigger: str = ... + """Text to match against user's input.""" + details: str | List[str] | Tuple[str] = ... + """A minihtml string or list of strings displayed below the trigger.""" + annotation: str = ... + """Hint to draw to the right-hand side of the row.""" + kind: Tuple[int, str, str] = ... + """The kind of the item.""" + def __init__( self, trigger: str, - details: Union[str, List[str]] = "", - annotation: str = "", - kind: Tuple[int, str, str] = KIND_AMBIGUOUS + details: str | Sequence[str] = ..., + annotation: str = ..., + kind: Tuple[int, str, str] = ... ) -> None: ... class ListInputItem: - value = ... # type: Any - kind = ... # type: Tuple[int, str, str] + """ + Represents a row shown via `ListInputHandler`. + """ + text: str = ... + """Text to match against the user's input.""" + value: Any = ... + """A `Value` passed to the command if the row is selected.""" + details: str | List[str] | Tuple[str] = ... + """A minihtml string or list of strings displayed below the trigger.""" + annotation: str = ... + """Hint to draw to the right-hand side of the row.""" + kind: Tuple[int, str, str] = ... + """The kind of the item.""" + def __init__( self, text: str, - value: Any, - details: Union[str, List[str]] = "", - annotation: str = "", - kind: Tuple[int, str, str] = KIND_AMBIGUOUS + value: bool | str | int | float | List[Any] | Dict[str, Any] | None, + details: str | Sequence[str] = ..., + annotation: str = ..., + kind: Tuple[int, str, str] = ... ) -> None: ... -class Html: +class SymbolRegion: + """ + Contains information about a `Region` of a `View` that contains a symbol. + """ + name: str = ... + """The name of the symbol.""" + region: Region = ... + """The location of the symbol within the `View`.""" + syntax: str = ... + """The name of the syntax for the symbol.""" + type: int = ... + """The type of the symbol""" + kind: Tuple[int, str, str] = ... + """The kind of the symbol.""" + + def __init__(self, name: str, region: Region, syntax: str, type: int, kind: Tuple[int, str, str]) -> None: + ... + + +class SymbolLocation: + """ + Contains information about a file that contains a symbol. + """ + path: str = ... + """The filesystem path to the file containing the symbol.""" + display_name: str = ... + """The project-relative path to the file containing the symbol.""" + row: int = ... + """The row of the file the symbol is contained on.""" + col: int = ... + """The column of the row that the symbol is contained on.""" + syntax: str = ... + """The name of the syntax for the symbol.""" + type: int = ... + """The type of the symbol.""" + kind: Tuple[int, str, str] = ... + """The kind of the symbol.""" + def __init__( self, - text: str, + path: str, + display_name: str, + row: int, + col: int, + syntax: str, + type: int, + kind: Tuple[int, str, str] ) -> None: ... + + def path_encoded_position(self) -> str: + ... From 42ad6cdcf414d37f374dbfc6a20bfd5bdcdf823c Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Fri, 1 Dec 2023 19:35:11 +0100 Subject: [PATCH 03/11] Add stubs for sublime_plugin.py --- stubs/sublime_plugin.pyi | 909 ++++++++++++++++++++++++++++++++++----- 1 file changed, 796 insertions(+), 113 deletions(-) diff --git a/stubs/sublime_plugin.pyi b/stubs/sublime_plugin.pyi index 1a7b2a4a1..e26f168d3 100644 --- a/stubs/sublime_plugin.pyi +++ b/stubs/sublime_plugin.pyi @@ -1,182 +1,865 @@ -# Stubs for sublime_plugin (Python 3.5) -# -# NOTE: This dynamically typed stub was automatically generated by stubgen. -from sublime import View, Window, Edit, Buffer -from typing import Any, Optional, Dict, List -assert Optional - -# api_ready = ... # type: bool -# application_command_classes = ... # type: Any -# window_command_classes = ... # type: Any -# text_command_classes = ... # type: Any -# view_event_listener_classes = ... # type: Any -view_event_listeners = ... # type: Dict[int, List[ViewEventListener]] -# all_command_classes = ... # type: Any -# all_callbacks = ... # type: Any -# profile = ... # type: Any - -# def unload_module(module): ... -# def unload_plugin(modulename): ... -# def reload_plugin(modulename): ... -# def create_application_commands(): ... -# def create_window_commands(window_id): ... -# def create_text_commands(view_id): ... -# def on_api_ready(): ... -# def is_view_event_listener_applicable(cls, view): ... -# def create_view_event_listeners(classes, view): ... -# def check_view_event_listeners(view): ... -# def attach_view(view): ... - -# check_all_view_event_listeners_scheduled = ... # type: bool - -# def check_all_view_event_listeners(): ... -# def detach_view(view): ... -# def event_listeners_for_view(view): ... -# def find_view_event_listener(view, cls): ... -# def on_new(view_id): ... -# def on_new_async(view_id): ... -# def on_clone(view_id): ... -# def on_clone_async(view_id): ... - -# class Summary: -# max = ... # type: float -# sum = ... # type: float -# count = ... # type: int -# def __init__(self) -> None: ... -# def record(self, x): ... - -# def run_callback(event, callback, expr): ... -# def run_view_listener_callback(view, name): ... -# def run_async_view_listener_callback(view, name): ... -# def on_load(view_id): ... -# def on_load_async(view_id): ... -# def on_pre_close(view_id): ... -# def on_close(view_id): ... -# def on_pre_save(view_id): ... -# def on_pre_save_async(view_id): ... -# def on_post_save(view_id): ... -# def on_post_save_async(view_id): ... -# def on_modified(view_id): ... -# def on_modified_async(view_id): ... -# def on_selection_modified(view_id): ... -# def on_selection_modified_async(view_id): ... -# def on_activated(view_id): ... -# def on_activated_async(view_id): ... -# def on_deactivated(view_id): ... -# def on_deactivated_async(view_id): ... -# def on_query_context(view_id, key, operator, operand, match_all): ... -# def normalise_completion(c): ... -# def on_query_completions(view_id, prefix, locations): ... -# def on_hover(view_id, point, hover_zone): ... -# def on_text_command(view_id, name, args): ... -# def on_window_command(window_id, name, args): ... -# def on_post_text_command(view_id, name, args): ... -# def on_post_window_command(window_id, name, args): ... +# Stubs for sublime_plugin.py (Python 3.3 API Environment) +from sublime import Buffer, CompletionItem, CompletionList, Edit, Html, ListInputItem, Settings, TextChange, View, Window +from typing import Any, Dict, List, Tuple + + +view_event_listeners: Dict[int, List[ViewEventListener]] = ... + + +class CommandInputHandler: + + def name(self) -> str: + """ + The command argument name this input handler is editing. Defaults to `foo_bar` for an input handler named + `FooBarInputHandler`. + """ + ... + + def placeholder(self) -> str: + """ + Placeholder text is shown in the text entry box before the user has entered anything. Empty by default. + """ + ... + + def initial_text(self) -> str: + """ + Initial text shown in the text entry box. Empty by default. + """ + ... + + def initial_selection(self) -> List[Tuple[int, int]]: + """ + A list of 2-element tuples, defining the initially selected parts of the initial text. + """ + ... + + def preview(self, text: str) -> str | Html: + """ + Called whenever the user changes the text in the entry box. The returned value (either plain text or HTML) will + be shown in the preview area of the Command Palette. + """ + ... + + def validate(self, text: str) -> bool: + """ + Called whenever the user presses enter in the text entry box. Return `False` to disallow the current value. + """ + ... + + def cancel(self) -> None: + """ + Called when the input handler is canceled, either by the user pressing backspace or escape. + """ + ... + + def confirm(self, text: str) -> None: + """ + Called when the input is accepted, after the user has pressed enter and the text has been validated. + """ + ... + + def next_input(self, args) -> CommandInputHandler | None: + """ + Return the next input after the user has completed this one. May return + :py:`None` to indicate no more input is required, or + `sublime_plugin.BackInputHandler()` to indicate that the input handler + should be popped off the stack instead. + """ + ... + + def want_event(self) -> bool: + """ + Whether the `validate()` and `confirm()` methods should received a second `Event` parameter. Returns `False` by + default. + """ + ... + + +class BackInputHandler(CommandInputHandler): + ... + + +class TextInputHandler(CommandInputHandler): + """ + TextInputHandlers can be used to accept textual input in the Command Palette. Return a subclass of this from + `Command.input()`. + + For an input handler to be shown to the user, the command returning the input handler MUST be made available in the + Command Palette by adding the command to a `Default.sublime-commands` file. + """ + def description(self, text: str) -> str: + """ + The text to show in the Command Palette when this input handler is not at the top of the input handler stack. + Defaults to the text the user entered. + """ + ... + + +class ListInputHandler(CommandInputHandler): + """ + ListInputHandlers can be used to accept a choice input from a list items in the Command Palette. Return a subclass + of this from `Command.input()`. + + For an input handler to be shown to the user, the command returning the input handler MUST be made available in the + Command Palette by adding the command to a `Default.sublime-commands` file. + """ + def list_items(self) -> List[str] | Tuple[List[str], int] | List[Tuple[str, Any]] | \ + Tuple[List[Tuple[str, Any]], int] | List[ListInputItem] | Tuple[List[ListInputItem], int]: + """ + This method should return the items to show in the list. + + The returned value may be a `list` of items, or a 2-element `tuple` containing a list of items, and an `int` + index of the item to pre-select. + + Each item in the list may be one of: + + * A string used for both the row text and the value passed to the command + * A 2-element tuple containing a string for the row text, and a `Value` to pass to the command + * A `sublime.ListInputItem` object + """ + ... + + def description(self, value, text: str) -> str: + """ + The text to show in the Command Palette when this input handler is not at the top of the input handler stack. + Defaults to the text of the list item the user selected. + """ + ... class Command: + def name(self) -> str: + """ + Return the name of the command. By default this is derived from the name of the class. + """ ... - # def is_enabled_(self, args): ... - def is_enabled(self) -> bool: + def is_enabled(self, **kwargs: Dict[str, Any]) -> bool: + """ + Return whether the command is able to be run at this time. Command arguments are passed as keyword arguments. + The default implementation simply always returns `True`. + """ ... - # def is_visible_(self, args): ... - def is_visible(self) -> bool: + def is_visible(self, **kwargs: Dict[str, Any]) -> bool: + """ + Return whether the command should be shown in the menu at this time. Command arguments are passed as keyword + arguments. The default implementation always returns `True`. + """ ... - # def is_checked_(self, args): ... - def is_checked(self) -> bool: + def is_checked(self, **kwargs: Dict[str, Any]) -> bool: + """ + Return whether a checkbox should be shown next to the menu item. Command arguments are passed as keyword + arguments. The `.sublime-menu` file must have the `"checkbox"` key set to `true` for this to be used. + """ ... - # def description_(self, args): ... - def description(self) -> str: + def description(self, **kwargs: Dict[str, Any]) -> str: + """ + Return a description of the command with the given arguments. Command arguments are passed as keyword arguments. + Used in the menu, if no caption is provided. Return `None` to get the default description. + """ ... - # def filter_args(self, args): ... def want_event(self) -> bool: + """ + Return whether to receive an `Event` argument when the command is triggered by a mouse action. The event + information allows commands to determine which portion of the view was clicked on. The default implementation + returns `False`. + """ + ... + + def input(self, args: Dict[str, Any]) -> CommandInputHandler | None: + """ + If this returns something other than `None`, the user will be prompted for an input before the command is run in + the Command Palette. + """ + ... + + def input_description(self) -> str: + """ + Allows a custom name to be show to the left of the cursor in the input box, instead of the default one generated + from the command name. + """ + ... + + def run(self, **kwargs: Dict[str, Any]) -> None: + """ + Called when the command is run. Command arguments are passed as keyword arguments. + """ ... class ApplicationCommand(Command): + """ + A `Command` instantiated just once. + """ ... class WindowCommand(Command): - window = ... # type: Window + """ + A `Command` instantiated once per window. The `Window` object may be retrieved via `self.window`. + """ + window: Window = ... + """The `Window` this command is attached to.""" def __init__(self, window: Window) -> None: ... - # def run_(self, edit_token, args): ... - - # def run(self) -> None: (mypy issue #5876). - # ... - class TextCommand(Command): - view = ... # type: View + """ + A `Command` instantiated once per `View`. The `View` object may be retrieved + via `self.view `. + """ + view: View = ... + """The `View` this command is attached to.""" def __init__(self, view: View) -> None: ... - # def run_(self, edit_token, args): ... - # def run(self, edit: Edit) -> None: (mypy issue #5876) - # ... + def run(self, edit: Edit, **kwargs: Dict[str, Any]) -> None: + """ + Called when the command is run. Command arguments are passed as keyword arguments. + """ + ... class EventListener: - ... + def on_init(self, views: List[View]) -> None: + """ + Called once with a list of views that were loaded before the EventListener was instantiated. + """ + ... -class TextChangeListener: + def on_exit(self) -> None: + """ + Called once after the API has shut down, immediately before the plugin_host process exits. + """ + ... - buffer = ... # type: Buffer + def on_new(self, view: View) -> None: + """ + Called when a new file is created. + """ + ... - @classmethod - def is_applicable(cls, buffer: Buffer) -> bool: + def on_new_async(self, view: View) -> None: + """ + Called when a new buffer is created. Runs in a separate thread, and does not block the application. + """ ... - def __init__(self) -> None: + def on_associate_buffer(self, buffer: Buffer) -> None: + """ + Called when a buffer is associated with a file. `buffer` will be a `Buffer` object. + """ ... - def attach(self, buffer: Buffer) -> None: + def on_associate_buffer_async(self, buffer: Buffer) -> None: + """ + Called when a buffer is associated with file. Runs in a separate thread, and does not block the application. + `buffer` will be a `Buffer` object. + """ ... - def detach(self) -> None: + def on_clone(self, view: View) -> None: + """ + Called when a view is cloned from an existing one. + """ ... - def is_attached(self) -> bool: + def on_clone_async(self, view: View) -> None: + """ + Called when a view is cloned from an existing one. Runs in a separate thread, and does not block the + application. + """ + ... + + def on_load(self, view: View) -> None: + """ + Called when the file is finished loading. + """ + ... + + def on_load_async(self, view: View) -> None: + """ + Called when the file is finished loading. Runs in a separate thread, and does not block the application. + """ + ... + + def on_reload(self, view: View) -> None: + """ + Called when the View is reloaded. + """ + ... + + def on_reload_async(self, view: View) -> None: + """ + Called when the View is reloaded. Runs in a separate thread, and does not block the application. + """ + ... + + def on_revert(self, view: View) -> None: + """ + Called when the View is reverted. + """ + ... + + def on_revert_async(self, view: View) -> None: + """ + Called when the View is reverted. Runs in a separate thread, and does not block the application. + """ + ... + + def on_pre_move(self, view: View) -> None: + """ + Called right before a view is moved between two windows, passed the `View` object. + """ + ... + + def on_post_move(self, view: View) -> None: + """ + Called right after a view is moved between two windows, passed the `View` object. + """ + ... + + def on_post_move_async(self, view: View) -> None: + """ + Called right after a view is moved between two windows, passed the `View` object. Runs in a separate thread, and + does not block the application. + """ + ... + + def on_pre_close(self, view: View) -> None: + """ + Called when a view is about to be closed. The view will still be in the window at this point. + """ + ... + + def on_close(self, view: View) -> None: + """ + Called when a view is closed (note, there may still be other views into the same buffer). + """ + ... + + def on_pre_save(self, view: View) -> None: + """ + Called just before a view is saved. + """ + ... + + def on_pre_save_async(self, view: View) -> None: + """ + Called just before a view is saved. Runs in a separate thread, and does not block the application. + """ + ... + + def on_post_save(self, view: View) -> None: + """ + Called after a view has been saved. + """ + ... + + def on_post_save_async(self, view: View) -> None: + """ + Called after a view has been saved. Runs in a separate thread, and does not block the application. + """ + ... + + def on_modified(self, view: View) -> None: + """ + Called after changes have been made to a view. + """ + ... + + def on_modified_async(self, view: View) -> None: + """ + Called after changes have been made to a view. Runs in a separate thread, and does not block the application. + """ + ... + + def on_selection_modified(self, view: View) -> None: + """ + Called after the selection has been modified in a view. + """ + ... + + def on_selection_modified_async(self, view: View) -> None: + """ + Called after the selection has been modified in a view. Runs in a separate thread, and does not block the + application. + """ + ... + + def on_activated(self, view: View) -> None: + """ + Called when a view gains input focus. + """ + ... + + def on_activated_async(self, view: View) -> None: + """ + Called when a view gains input focus. Runs in a separate thread, and does not block the application. + """ + ... + + def on_deactivated(self, view: View) -> None: + """ + Called when a view loses input focus. + """ + ... + + def on_deactivated_async(self, view: View) -> None: + """ + Called when a view loses input focus. Runs in a separate thread, and does not block the application. + """ + ... + + def on_hover(self, view: View, point: int, hover_zone: int) -> None: + """ + Called when the user's mouse hovers over the view for a short period. + + - `view` - The view. + - `point` - The closest point in the view to the mouse location. The mouse may not actually be located adjacent + based on the value of `hover_zone`. + - `hover_zone` - Which element in Sublime Text the mouse has hovered over. + """ + ... + + def on_query_context(self, view: View, key: str, operator: int, operand: str, match_all: bool) -> bool | None: + """ + Called when determining to trigger a key binding with the given context key. If the plugin knows how to respond + to the context, it should return either `True` of `False`. If the context is unknown, it should return `None`. + + - `key` - The context key to query. This generally refers to specific state held by a plugin. + - `operator` - The operator to check against the operand; whether to check equality, inequality, etc. + - `operand` - The value against which to check using the `operator`. + - `match_all` - This should be used if the context relates to the selections: does every selection have to + match (`True`), or is at least one matching enough (`False`)? + """ + ... + + def on_query_completions( + self, + view: View, + prefix: str, + locations: List[int] + ) -> List[str] | Tuple[List[str], int] | List[Tuple[str, str]] | Tuple[List[Tuple[str, str]], int] | \ + List[CompletionItem] | Tuple[List[CompletionItem], int] | CompletionList | None: + """ + Called whenever completions are to be presented to the user. + + - `prefix` - The text already typed by the user. + - `locations` - The list of points being completed. Since this method is called for all completions no matter + the syntax, `self.view.match_selector(point, relevant_scope)` should be called to determine if the point is + relevant. + + Returns a list of completions in one of the valid formats or `None` if no completions are provided. + """ + ... + + def on_text_command(self, view: View, command_name: str, args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]] | None: + """ + Called when a text command is issued. The listener may return a (command, arguments) tuple to rewrite the + command, or `None` to run the command unmodified. + """ + ... + + def on_window_command( + self, + window: Window, + command_name: str, + args: Dict[str, Any] + ) -> Tuple[str, Dict[str, Any]] | None: + """ + Called when a window command is issued. The listener may return a (command, arguments) tuple to rewrite the + command, or `None` to run the command unmodified. + """ + ... + + def on_post_text_command(self, view: View, command_name: str, args: Dict[str, Any]) -> None: + """ + Called after a text command has been executed. + """ + ... + + def on_post_window_command(self, window: Window, command_name: str, args: Dict[str, Any]) -> None: + """ + Called after a window command has been executed. + """ + ... + + def on_new_window(self, window: Window) -> None: + """ + Called when a window is created, passed the Window object. + """ + ... + + def on_new_window_async(self, window: Window) -> None: + """ + Called when a window is created, passed the Window object. Runs in a separate thread, and does not block the + application. + """ + ... + + def on_pre_close_window(self, window: Window) -> None: + """ + Called right before a window is closed, passed the Window object. + """ + ... + + def on_new_project(self, window: Window) -> None: + """ + Called right after a new project is created, passed the Window object. + """ + ... + + def on_new_project_async(self, window: Window) -> None: + """ + Called right after a new project is created, passed the Window object. Runs in a separate thread, and does not + block the application. + """ + ... + + def on_load_project(self, window: Window) -> None: + """ + Called right after a project is loaded, passed the Window object. + """ + ... + + def on_load_project_async(self, window: Window) -> None: + """ + Called right after a project is loaded, passed the Window object. Runs in a separate thread, and does not block + the application. + """ + ... + + def on_pre_save_project(self, window: Window) -> None: + """ + Called right before a project is saved, passed the Window object. + """ + ... + + def on_post_save_project(self, window: Window) -> None: + """ + Called right after a project is saved, passed the Window object. + """ + ... + + def on_post_save_project_async(self, window: Window) -> None: + """ + Called right after a project is saved, passed the Window object. Runs in a separate thread, and does not block + the application. + """ + ... + + def on_pre_close_project(self, window: Window) -> None: + """ + Called right before a project is closed, passed the Window object. + """ ... class ViewEventListener: + """ + A class that provides similar event handling to `EventListener`, but bound to a specific view. Provides class + method-based filtering to control what views objects are created for. + """ + view: View = ... + @classmethod - def is_applicable(cls, settings: dict) -> bool: + def is_applicable(cls, settings: Settings) -> bool: + """ + Whether this listener should apply to a view with the given `Settings`. + """ ... @classmethod def applies_to_primary_view_only(cls) -> bool: + """ + Whether this listener should apply only to the primary view for a file or all of its clones as well. + """ ... - view = ... # type: View - def __init__(self, view: View) -> None: ... + def on_load(self) -> None: + """ + Called when the file is finished loading. + """ + ... -class CommandInputHandler: - ... + def on_load_async(self) -> None: + """ + Same as `on_load` but runs in a separate thread, not blocking the application. + """ + ... + def on_reload(self) -> None: + """ + Called when the file is reloaded. + """ + ... -class BackInputHandler(CommandInputHandler): - ... + def on_reload_async(self) -> None: + """ + Same as `on_reload` but runs in a separate thread, not blocking the application. + """ + ... + def on_revert(self) -> None: + """ + Called when the file is reverted. + """ + ... -class TextInputHandler(CommandInputHandler): - ... + def on_revert_async(self) -> None: + """ + Same as `on_revert` but runs in a separate thread, not blocking the application. + """ + ... + def on_pre_move(self) -> None: + """ + Called right before a view is moved between two windows. + """ + ... -class ListInputHandler(CommandInputHandler): - ... + def on_post_move(self) -> None: + """ + Called right after a view is moved between two windows. + """ + ... + + def on_post_move_async(self) -> None: + """ + Same as `on_post_move` but runs in a separate thread, not blocking the application. + """ + ... + + def on_pre_close(self) -> None: + """ + Called when a view is about to be closed. The view will still be in the window at this point. + """ + ... + + def on_close(self) -> None: + """ + Called when a view is closed (note, there may still be other views into the same buffer). + """ + ... + + def on_pre_save(self) -> None: + """ + Called just before a view is saved. + """ + ... + + def on_pre_save_async(self) -> None: + """ + Same as `on_pre_save` but runs in a separate thread, not blocking the application. + """ + ... + + def on_post_save(self) -> None: + """ + Called after a view has been saved. + """ + ... + + def on_post_save_async(self) -> None: + """ + Same as `on_post_save` but runs in a separate thread, not blocking the application. + """ + ... + + def on_modified(self) -> None: + """ + Called after changes have been made to the view. + """ + ... + + def on_modified_async(self) -> None: + """ + Same as `on_modified` but runs in a separate thread, not blocking the application. + """ + ... + + def on_selection_modified(self) -> None: + """ + Called after the selection has been modified in the view. + """ + ... + + def on_selection_modified_async(self) -> None: + """ + Called after the selection has been modified in the view. Runs in a separate thread, and does not block the + application. + """ + ... + + def on_activated(self) -> None: + """ + Called when a view gains input focus. + """ + ... + + def on_activated_async(self) -> None: + """ + Called when the view gains input focus. Runs in a separate thread, and does not block the application. + """ + ... + + def on_deactivated(self) -> None: + """ + Called when the view loses input focus. + """ + ... + + def on_deactivated_async(self) -> None: + """ + Called when the view loses input focus. Runs in a separate thread, and does not block the application. + """ + ... + + def on_hover(self, point: int, hover_zone: int) -> None: + """ + Called when the user's mouse hovers over the view for a short period. + + - `point` - The closest point in the view to the mouse location. The mouse may not actually be located adjacent + based on the value of `hover_zone`. + - `hover_zone` - Which element in Sublime Text the mouse has hovered over. + """ + ... + + def on_query_context(self, key: str, operator: int, operand: str, match_all: bool) -> bool | None: + """ + Called when determining to trigger a key binding with the given context key. If the plugin knows how to respond + to the context, it should return either `True` of `False`. If the context is unknown, it should return `None`. + + - `key` - The context key to query. This generally refers to specific state held by a plugin. + - `operator` - The operator to check against the operand; whether to check equality, inequality, etc. + - `operand` - The value against which to check using the `operator`. + - `match_all` - This should be used if the context relates to the selections: does every selection have to match + (`True`), or is at least one matching enough (`False`)? + """ + ... + + def on_query_completions( + self, + prefix: str, + locations: List[int] + ) -> List[str] | Tuple[List[str], int] | List[Tuple[str, str]] | Tuple[List[Tuple[str, str]], int] | \ + List[CompletionItem] | Tuple[List[CompletionItem], int] | CompletionList | None: + """ + Called whenever completions are to be presented to the user. + + - `prefix` - The text already typed by the user. + - `locations` - The list of points being completed. Since this method is called for all completions no matter + the syntax, `self.view.match_selector(point, relevant_scope)` should be called to determine if the point is + relevant. + + Returns a list of completions in one of the valid formats or `None` if no completions are provided. + """ + ... + + def on_text_command(self, command_name: str, args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]] | None: + """ + Called when a text command is issued. The listener may return a `(command, arguments)` tuple to rewrite the + command, or `None` to run the command unmodified. + """ + ... + + def on_post_text_command(self, command_name: str, args: Dict[str, Any]) -> None: + """ + Called after a text command has been executed. + """ + ... + + +class TextChangeListener: + """ + A class that provides event handling about text changes made to a specific `Buffer`. Is separate from + `ViewEventListener` since multiple views can share a single buffer. + """ + buffer: Buffer = ... + + @classmethod + def is_applicable(cls, buffer: Buffer) -> bool: + """ + Whether this listener should apply to the provided buffer. + """ + ... + + def __init__(self) -> None: + ... + + def detach(self) -> None: + """ + Remove this listener from the buffer. + + Async callbacks may still be called after this, as they are queued separately. + + Raises `ValueError` if the listener is not attached. + """ + ... + + def attach(self, buffer: Buffer) -> None: + """ + Attach this listener to a buffer. + + Raises `ValueError` if the listener is already attached. + """ + ... + + def is_attached(self) -> bool: + """ + Whether the listener is receiving events from a buffer. May not be called from `__init__`. + """ + ... + + def on_text_changed(self, changes: List[TextChange]) -> None: + """ + Called once after changes has been made to a buffer, with detailed information about what has changed. + """ + ... + + def on_text_changed_async(self, changes: List[TextChange]) -> None: + """ + Same as `on_text_changed` but runs in a separate thread, not blocking the application. + """ + ... + + def on_revert(self) -> None: + """ + Called when the buffer is reverted. + + A revert does not trigger text changes. If the contents of the buffer are required here use `View.substr`. + """ + ... + + def on_revert_async(self) -> None: + """ + Same as `on_revert` but runs in a separate thread, not blocking the application. + """ + ... + + def on_reload(self) -> None: + """ + Called when the buffer is reloaded. + + A reload does not trigger text changes. If the contents of the buffer are required here use `View.substr`. + """ + ... + + def on_reload_async(self) -> None: + """ + Same as `on_reload` but runs in a separate thread, not blocking the application. + """ + ... From 3a0937b838765d694cbc2b767a67313fbe426d02 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Fri, 1 Dec 2023 21:29:05 +0100 Subject: [PATCH 04/11] Fix wrong type for ListInputItem.value --- plugin/goto_diagnostic.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index 0ab0dffa3..c478cbf06 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -13,6 +13,7 @@ from .core.settings import userprefs from .core.types import ClientConfig from .core.typing import Any, Dict, Iterator, List, Optional, Tuple, Union +from .core.typing import cast from .core.url import parse_uri, unparse_uri from .core.views import diagnostic_severity from .core.views import format_diagnostic_for_html @@ -257,10 +258,11 @@ def placeholder(self) -> str: def next_input(self, args: dict) -> Optional[sublime_plugin.CommandInputHandler]: return None if args.get("diagnostic") else sublime_plugin.BackInputHandler() # type: ignore - def confirm(self, value: Optional[Tuple[int, Diagnostic]]) -> None: + def confirm(self, value: Optional[list]) -> None: if not value: return - i, diagnostic = value + i = cast(int, value[0]) + diagnostic = cast(Diagnostic, value[1]) session = self.sessions[i] location = self._get_location(diagnostic) scheme, _ = self.parsed_uri @@ -276,10 +278,11 @@ def cancel(self) -> None: self._preview.close() self.window.focus_view(self.view) - def preview(self, value: Optional[Tuple[int, Diagnostic]]) -> Union[str, sublime.Html]: + def preview(self, value: Optional[list]) -> Union[str, sublime.Html]: if not value: return "" - i, diagnostic = value + i = cast(int, value[0]) + diagnostic = cast(Diagnostic, value[1]) session = self.sessions[i] base_dir = None scheme, path = self.parsed_uri From 0980e6c0151073addea148cb3a01cd04808357d5 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Sat, 2 Dec 2023 04:44:52 +0100 Subject: [PATCH 05/11] Mark module-level constants with Literal value See https://typing.readthedocs.io/en/latest/source/stubs.html#constants and https://typing.readthedocs.io/en/latest/source/stubs.html#id20 --- stubs/sublime.pyi | 206 +++++++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index 70f31f2de..41652299a 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -3,188 +3,188 @@ from typing import Any, Callable, Dict, Iterable, Iterator, List, Literal, Optio from typing_extensions import deprecated -HOVER_TEXT: int = ... +HOVER_TEXT: Literal[1] """The mouse is hovered over the text.""" -HOVER_GUTTER: int = ... +HOVER_GUTTER: Literal[2] """The mouse is hovered over the gutter.""" -HOVER_MARGIN: int = ... +HOVER_MARGIN: Literal[3] """The mouse is hovered in the white space to the right of a line.""" -ENCODED_POSITION: int = ... +ENCODED_POSITION: Literal[1] """Indicates that the file name should be searched for a `:row` or `:row:col` suffix.""" -TRANSIENT: int = ... +TRANSIENT: Literal[4] """Open the file as a preview only: it won't have a tab assigned it until modified.""" -FORCE_GROUP: int = ... +FORCE_GROUP: Literal[8] """ Don't select the file if it is open in a different group. Instead make a new clone of that file in the desired group. """ -SEMI_TRANSIENT: int = ... +SEMI_TRANSIENT: Literal[16] """ If a sheet is newly created, it will be set to semi-transient. Semi-transient sheets generally replace other semi-transient sheets. This is used for the side-bar preview. Only valid with `ADD_TO_SELECTION` or `REPLACE_MRU`. """ -ADD_TO_SELECTION: int = ... +ADD_TO_SELECTION: Literal[32] """Add the file to the currently selected sheets in the group.""" -REPLACE_MRU: int = ... +REPLACE_MRU: Literal[64] """Causes the sheet to replace the most-recently used sheet in the current sheet selection.""" -CLEAR_TO_RIGHT: int = ... +CLEAR_TO_RIGHT: Literal[128] """ All currently selected sheets to the right of the most-recently used sheet will be unselected before opening the file. Only valid in combination with `ADD_TO_SELECTION`. """ -FORCE_CLONE: int = ... +FORCE_CLONE: Literal[256] """Don't select the file if it is open. Instead make a new clone of that file in the desired group.""" -LITERAL: int = ... +LITERAL: Literal[1] """Whether the find pattern should be matched literally or as a regex.""" -IGNORECASE: int = ... +IGNORECASE: Literal[2] """Whether case should be considered when matching the find pattern.""" -WHOLEWORD: int = ... +WHOLEWORD: Literal[4] """Whether to only match whole words.""" -REVERSE: int = ... +REVERSE: Literal[8] """Whether to search backwards.""" -WRAP: int = ... +WRAP: Literal[16] """Whether to wrap around once the end is reached.""" -MONOSPACE_FONT: int = ... +MONOSPACE_FONT: Literal[1] """Use a monospace font.""" -KEEP_OPEN_ON_FOCUS_LOST: int = ... +KEEP_OPEN_ON_FOCUS_LOST: Literal[2] """Keep the quick panel open if the window loses input focus.""" -WANT_EVENT: int = ... +WANT_EVENT: Literal[4] """Pass a second parameter to the `on_done` callback, a `Event`.""" -HTML: int = ... -COOPERATE_WITH_AUTO_COMPLETE: int = ... +HTML: Literal[1] +COOPERATE_WITH_AUTO_COMPLETE: Literal[2] """Causes the popup to display next to the auto complete menu.""" -HIDE_ON_MOUSE_MOVE: int = ... +HIDE_ON_MOUSE_MOVE: Literal[4] """Causes the popup to hide when the mouse is moved, clicked or scrolled.""" -HIDE_ON_MOUSE_MOVE_AWAY: int = ... +HIDE_ON_MOUSE_MOVE_AWAY: Literal[8] """Causes the popup to hide when the mouse is moved (unless towards the popup), or when clicked or scrolled.""" -KEEP_ON_SELECTION_MODIFIED: int = ... +KEEP_ON_SELECTION_MODIFIED: Literal[16] """Prevent the popup from hiding when the selection is modified.""" -HIDE_ON_CHARACTER_EVENT: int = ... +HIDE_ON_CHARACTER_EVENT: Literal[32] """Hide the popup when a character is typed.""" -DRAW_EMPTY: int = ... +DRAW_EMPTY: Literal[1] """Draw empty regions with a vertical bar. By default, they aren't drawn at all.""" -HIDE_ON_MINIMAP: int = ... +HIDE_ON_MINIMAP: Literal[2] """Don't show the regions on the minimap.""" -DRAW_EMPTY_AS_OVERWRITE: int = ... +DRAW_EMPTY_AS_OVERWRITE: Literal[4] """Draw empty regions with a horizontal bar instead of a vertical one.""" -PERSISTENT: int = ... +PERSISTENT: Literal[16] """Save the regions in the session.""" -DRAW_NO_FILL: int = ... +DRAW_NO_FILL: Literal[32] """Disable filling the regions, leaving only the outline.""" -HIDDEN: int = ... +HIDDEN: Literal[128] """Don't draw the regions.""" -DRAW_NO_OUTLINE: int = ... +DRAW_NO_OUTLINE: Literal[256] """Disable drawing the outline of the regions.""" -DRAW_SOLID_UNDERLINE: int = ... +DRAW_SOLID_UNDERLINE: Literal[512] """Draw a solid underline below the regions.""" -DRAW_STIPPLED_UNDERLINE: int = ... +DRAW_STIPPLED_UNDERLINE: Literal[1024] """Draw a stippled underline below the regions.""" -DRAW_SQUIGGLY_UNDERLINE: int = ... +DRAW_SQUIGGLY_UNDERLINE: Literal[2048] """Draw a squiggly underline below the regions.""" -NO_UNDO: int = ... - -OP_EQUAL: int = ... -OP_NOT_EQUAL: int = ... -OP_REGEX_MATCH: int = ... -OP_NOT_REGEX_MATCH: int = ... -OP_REGEX_CONTAINS: int = ... -OP_NOT_REGEX_CONTAINS: int = ... -CLASS_WORD_START: int = ... +NO_UNDO: Literal[8192] + +OP_EQUAL: Literal[0] +OP_NOT_EQUAL: Literal[1] +OP_REGEX_MATCH: Literal[2] +OP_NOT_REGEX_MATCH: Literal[3] +OP_REGEX_CONTAINS: Literal[4] +OP_NOT_REGEX_CONTAINS: Literal[5] +CLASS_WORD_START: Literal[1] """The point is the start of a word.""" -CLASS_WORD_END: int = ... +CLASS_WORD_END: Literal[2] """The point is the end of a word.""" -CLASS_PUNCTUATION_START: int = ... +CLASS_PUNCTUATION_START: Literal[4] """The point is the start of a sequence of punctuation characters.""" -CLASS_PUNCTUATION_END: int = ... +CLASS_PUNCTUATION_END: Literal[8] """The point is the end of a sequence of punctuation characters.""" -CLASS_SUB_WORD_START: int = ... +CLASS_SUB_WORD_START: Literal[16] """The point is the start of a sub-word.""" -CLASS_SUB_WORD_END: int = ... +CLASS_SUB_WORD_END: Literal[32] """The point is the end of a sub-word.""" -CLASS_LINE_START: int = ... +CLASS_LINE_START: Literal[64] """The point is the start of a line.""" -CLASS_LINE_END: int = ... +CLASS_LINE_END: Literal[128] """The point is the end of a line.""" -CLASS_EMPTY_LINE: int = ... +CLASS_EMPTY_LINE: Literal[256] """The point is an empty line.""" -INHIBIT_WORD_COMPLETIONS: int = ... +INHIBIT_WORD_COMPLETIONS: Literal[8] """Prevent Sublime Text from showing completions based on the contents of the view.""" -INHIBIT_EXPLICIT_COMPLETIONS: int = ... +INHIBIT_EXPLICIT_COMPLETIONS: Literal[16] """Prevent Sublime Text from showing completions based on `.sublime-completions` files.""" -DYNAMIC_COMPLETIONS: int = ... +DYNAMIC_COMPLETIONS: Literal[32] """If completions should be re-queried as the user types.""" -INHIBIT_REORDER: int = ... +INHIBIT_REORDER: Literal[128] """Prevent Sublime Text from changing the completion order.""" -DIALOG_CANCEL: int = ... -DIALOG_YES: int = ... -DIALOG_NO: int = ... +DIALOG_CANCEL: Literal[0] +DIALOG_YES: Literal[1] +DIALOG_NO: Literal[2] -LAYOUT_INLINE: int = ... +LAYOUT_INLINE: Literal[0] """The phantom is positioned inline with the text at the beginning of its `Region`.""" -LAYOUT_BELOW: int = ... +LAYOUT_BELOW: Literal[1] """The phantom is positioned below the line, left-aligned with the beginning of its `Region`.""" -LAYOUT_BLOCK: int = ... +LAYOUT_BLOCK: Literal[2] """The phantom is positioned below the line, left-aligned with the beginning of the line.""" -KIND_ID_AMBIGUOUS: int = ... -KIND_ID_KEYWORD: int = ... -KIND_ID_TYPE: int = ... -KIND_ID_FUNCTION: int = ... -KIND_ID_NAMESPACE: int = ... -KIND_ID_NAVIGATION: int = ... -KIND_ID_MARKUP: int = ... -KIND_ID_VARIABLE: int = ... -KIND_ID_SNIPPET: int = ... - -KIND_ID_COLOR_REDISH: int = ... -KIND_ID_COLOR_ORANGISH: int = ... -KIND_ID_COLOR_YELLOWISH: int = ... -KIND_ID_COLOR_GREENISH: int = ... -KIND_ID_COLOR_CYANISH: int = ... -KIND_ID_COLOR_BLUISH: int = ... -KIND_ID_COLOR_PURPLISH: int = ... -KIND_ID_COLOR_PINKISH: int = ... -KIND_ID_COLOR_DARK: int = ... -KIND_ID_COLOR_LIGHT: int = ... - -KIND_AMBIGUOUS: Tuple[int, str, str] = ... -KIND_KEYWORD: Tuple[int, str, str] = ... -KIND_TYPE: Tuple[int, str, str] = ... -KIND_FUNCTION: Tuple[int, str, str] = ... -KIND_NAMESPACE: Tuple[int, str, str] = ... -KIND_NAVIGATION: Tuple[int, str, str] = ... -KIND_MARKUP: Tuple[int, str, str] = ... -KIND_VARIABLE: Tuple[int, str, str] = ... -KIND_SNIPPET: Tuple[int, str, str] = ... - -SYMBOL_SOURCE_ANY: int = ... +KIND_ID_AMBIGUOUS: Literal[0] +KIND_ID_KEYWORD: Literal[1] +KIND_ID_TYPE: Literal[2] +KIND_ID_FUNCTION: Literal[3] +KIND_ID_NAMESPACE: Literal[4] +KIND_ID_NAVIGATION: Literal[5] +KIND_ID_MARKUP: Literal[6] +KIND_ID_VARIABLE: Literal[7] +KIND_ID_SNIPPET: Literal[8] + +KIND_ID_COLOR_REDISH: Literal[9] +KIND_ID_COLOR_ORANGISH: Literal[10] +KIND_ID_COLOR_YELLOWISH: Literal[11] +KIND_ID_COLOR_GREENISH: Literal[12] +KIND_ID_COLOR_CYANISH: Literal[13] +KIND_ID_COLOR_BLUISH: Literal[14] +KIND_ID_COLOR_PURPLISH: Literal[15] +KIND_ID_COLOR_PINKISH: Literal[16] +KIND_ID_COLOR_DARK: Literal[17] +KIND_ID_COLOR_LIGHT: Literal[18] + +KIND_AMBIGUOUS: Tuple[int, str, str] +KIND_KEYWORD: Tuple[int, str, str] +KIND_TYPE: Tuple[int, str, str] +KIND_FUNCTION: Tuple[int, str, str] +KIND_NAMESPACE: Tuple[int, str, str] +KIND_NAVIGATION: Tuple[int, str, str] +KIND_MARKUP: Tuple[int, str, str] +KIND_VARIABLE: Tuple[int, str, str] +KIND_SNIPPET: Tuple[int, str, str] + +SYMBOL_SOURCE_ANY: Literal[0] """Use any source - both the index and open files.""" -SYMBOL_SOURCE_INDEX: int = ... +SYMBOL_SOURCE_INDEX: Literal[1] """Use the index created when scanning through files in a project folder.""" -SYMBOL_SOURCE_OPEN_FILES: int = ... +SYMBOL_SOURCE_OPEN_FILES: Literal[2] """Use the open files, unsaved or otherwise.""" -SYMBOL_TYPE_ANY: int = ... +SYMBOL_TYPE_ANY: Literal[0] """Any symbol type - both definitions and references.""" -SYMBOL_TYPE_DEFINITION: int = ... +SYMBOL_TYPE_DEFINITION: Literal[1] """Only definitions.""" -SYMBOL_TYPE_REFERENCE: int = ... +SYMBOL_TYPE_REFERENCE: Literal[2] """Only references.""" -COMPLETION_FORMAT_TEXT: int = ... +COMPLETION_FORMAT_TEXT: Literal[0] """Plain text, upon completing the text is inserted verbatim.""" -COMPLETION_FORMAT_SNIPPET: int = ... +COMPLETION_FORMAT_SNIPPET: Literal[1] """A snippet, with `$` variables.""" -COMPLETION_FORMAT_COMMAND: int = ... +COMPLETION_FORMAT_COMMAND: Literal[2] """A command string, in the format returned by `format_command()`.""" -COMPLETION_FLAG_KEEP_PREFIX: int = ... +COMPLETION_FLAG_KEEP_PREFIX: Literal[1] def version() -> str: From 84672f7110d7ea29fe6d2127c26f521956ec5596 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Sat, 2 Dec 2023 05:01:36 +0100 Subject: [PATCH 06/11] Don't use assignments for class attributes See https://typing.readthedocs.io/en/latest/source/stubs.html#stub-style-classes --- stubs/sublime.pyi | 140 +++++++++++++++++++-------------------- stubs/sublime_plugin.pyi | 10 +-- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index 41652299a..f036e5d83 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -679,9 +679,9 @@ def folder_history() -> List[str]: class Window: - window_id: int = ... - settings_object: Settings = ... - template_settings_object = ... + window_id: int + settings_object: Settings + template_settings_object: Settings def __init__(self, id: int) -> None: ... @@ -1238,7 +1238,7 @@ class Edit: `Edit` objects are passed to `TextCommand`s, and can not be created by the user. Using an invalid `Edit` object, or an `Edit` object from a different `View`, will cause the functions that require them to fail. """ - edit_token: int = ... + edit_token: int def __init__(self, token: int) -> None: ... @@ -1250,11 +1250,11 @@ class Region: Also commonly used to represent an area of the text buffer, where ordering and `xpos` are generally ignored. """ - a: int = ... + a: int """The first end of the region.""" - b: int = ... + b: int """The second end of the region. In a selection this is the location of the caret. May be less than `a`.""" - xpos: float = ... + xpos: float """ In a selection this is the target horizontal position of the region. This affects behavior when pressing the up or down keys. Use `-1` if undefined. @@ -1321,15 +1321,15 @@ class HistoricPosition: Provides a snapshot of the row and column info for a `Point`, before changes were made to a `View`. This is primarily useful for replaying changes to a document. """ - pt: int = ... + pt: int """The offset from the beginning of the `View`.""" - row: int = ... + row: int """The row the `pt` was in when the `HistoricPosition` was recorded.""" - col: int = ... + col: int """The column the `py` was in when the `HistoricPosition` was recorded, in Unicode characters.""" - col_utf16: int = ... + col_utf16: int """The value of `col`, but in UTF-16 code units.""" - col_utf8: int = ... + col_utf8: int """The value of `col`, but in UTF-8 code units.""" @@ -1338,15 +1338,15 @@ class TextChange: Represents a change that occurred to the text of a `View`. This is primarily useful for replaying changes to a document. """ - a: HistoricPosition = ... + a: HistoricPosition """The beginning `HistoricPosition` of the region that was modified.""" - b: HistoricPosition = ... + b: HistoricPosition """The ending `HistoricPosition` of the region that was modified.""" - len_utf16: int = ... + len_utf16: int """The length of the old contents, in UTF-16 code units.""" - len_utf8: int = ... + len_utf8: int """The length of the old contents, in UTF-8 code units.""" - str: str = ... + str: str """A string of the new contents of the region specified by `a` and `b`.""" def __init__(self, pa: HistoricPosition, pb: HistoricPosition, len_utf16: int, len_utf8: int, s: str) -> None: @@ -1359,7 +1359,7 @@ class Selection(Reversible): This is primarily used to represent the textual selection. """ - view_id: int = ... + view_id: int def __init__(self, id: int) -> None: ... @@ -1444,7 +1444,7 @@ class Sheet: """ Represents a content container, i.e. a tab, within a window. Sheets may contain a `View`, or an image preview. """ - sheet_id: int = ... + sheet_id: int def __init__(self, id: int) -> None: ... @@ -1527,11 +1527,11 @@ class ContextStackFrame: """ Represents a single stack frame in the syntax highlighting. """ - context_name: str = ... + context_name: str """The name of the context.""" - source_file: str = ... + source_file: str """The name of the file the context is defined in.""" - source_location: Tuple[int, int] = ... + source_location: Tuple[int, int] """ The location of the context inside the source file as a pair of row and column. Maybe be `(-1, -1)` if the location is unclear, like in tmLanguage based syntaxes. @@ -1545,9 +1545,9 @@ class View: Note that multiple views may refer to the same `Buffer`, but they have their own unique selection and geometry. A list of these may be gotten using `View.clones()` or `Buffer.views()`. """ - view_id: int = ... - selection: Selection = ... - settings_object: Settings | None = ... + view_id: int + selection: Selection + settings_object: Settings | None def __init__(self, id: int) -> None: ... @@ -2502,7 +2502,7 @@ class Buffer: """ Represents a text buffer. Multiple `View` objects may share the same buffer. """ - buffer_id: int = ... + buffer_id: int def __init__(self, id: int) -> None: ... @@ -2540,7 +2540,7 @@ class Settings: """ A `dict` like object that a settings hierarchy. """ - settings_id: int = ... + settings_id: int def __init__(self, id: int) -> None: ... @@ -2596,13 +2596,13 @@ class Phantom: `PhantomSet` to actually add the phantoms to the `View`. Once a `Phantom` has been constructed and added to the `View`, changes to the attributes will have no effect. """ - region: Region = ... + region: Region """The `Region` associated with the phantom. The phantom is displayed at the start of the `Region`.""" - content: str = ... + content: str """The HTML content of the phantom.""" - layout: int = ... + layout: int """How the phantom should be placed relative to the `region`.""" - on_navigate: Callable[[str], None] | None = ... + on_navigate: Callable[[str], None] | None """Called when a link in the HTML is clicked. The value of the `href` attribute is passed.""" def __init__( @@ -2633,11 +2633,11 @@ class PhantomSet: A collection that manages `Phantom` objects and the process of adding them, updating them and removing them from a `View`. """ - view: View = ... + view: View """The `View` the phantom set is attached to.""" - key: str = ... + key: str """A string used to group the phantoms together.""" - phantoms: List[Phantom] = ... + phantoms: List[Phantom] def __init__(self, view: View, key: str = ...) -> None: ... @@ -2657,7 +2657,7 @@ class Html: """ Used to indicate that a string is formatted as HTML. """ - data: str = ... + data: str def __init__( self, @@ -2670,9 +2670,9 @@ class CompletionList: """ Represents a list of completions, some of which may be in the process of being asynchronously fetched. """ - target = ... - completions: List[str] | List[Tuple[str, str]] | List[CompletionItem] | None = ... - flags: int = ... + target: Any + completions: List[str] | List[Tuple[str, str]] | List[CompletionItem] | None + flags: int def __init__( self, @@ -2697,22 +2697,22 @@ class CompletionItem: """ Represents an available auto-completion item. """ - trigger: str = ... + trigger: str """Text to match against the user's input.""" - annotation: str = ... + annotation: str """A hint to draw to the right-hand side of the trigger.""" - completion: str = ... + completion: str """Text to insert if the completion is specified. If empty the `trigger` will be inserted instead.""" - completion_format: int = ... + completion_format: int """The format of the completion.""" - kind: Tuple[int, str, str] = ... + kind: Tuple[int, str, str] """The kind of the completion.""" - details: str = ... + details: str """ An optional minihtml description of the completion, shown in the detail pane at the bottom of the auto complete window. """ - flags: int = ... + flags: int def __init__( self, @@ -2806,13 +2806,13 @@ class Syntax: """ Contains information about a syntax. """ - path: str = ... + path: str """The packages path to the syntax file.""" - name: str = ... + name: str """The name of the syntax.""" - hidden: bool = ... + hidden: bool """If the syntax is hidden from the user.""" - scope: str = ... + scope: str """The base scope name of the syntax.""" def __init__(self, path: str, name: str, hidden: bool, scope: str) -> None: @@ -2826,13 +2826,13 @@ class QuickPanelItem: """ Represents a row in the quick panel, shown via `Window.show_quick_panel()`. """ - trigger: str = ... + trigger: str """Text to match against user's input.""" - details: str | List[str] | Tuple[str] = ... + details: str | List[str] | Tuple[str] """A minihtml string or list of strings displayed below the trigger.""" - annotation: str = ... + annotation: str """Hint to draw to the right-hand side of the row.""" - kind: Tuple[int, str, str] = ... + kind: Tuple[int, str, str] """The kind of the item.""" def __init__( @@ -2849,15 +2849,15 @@ class ListInputItem: """ Represents a row shown via `ListInputHandler`. """ - text: str = ... + text: str """Text to match against the user's input.""" - value: Any = ... + value: Any """A `Value` passed to the command if the row is selected.""" - details: str | List[str] | Tuple[str] = ... + details: str | List[str] | Tuple[str] """A minihtml string or list of strings displayed below the trigger.""" - annotation: str = ... + annotation: str """Hint to draw to the right-hand side of the row.""" - kind: Tuple[int, str, str] = ... + kind: Tuple[int, str, str] """The kind of the item.""" def __init__( @@ -2875,15 +2875,15 @@ class SymbolRegion: """ Contains information about a `Region` of a `View` that contains a symbol. """ - name: str = ... + name: str """The name of the symbol.""" - region: Region = ... + region: Region """The location of the symbol within the `View`.""" - syntax: str = ... + syntax: str """The name of the syntax for the symbol.""" - type: int = ... + type: int """The type of the symbol""" - kind: Tuple[int, str, str] = ... + kind: Tuple[int, str, str] """The kind of the symbol.""" def __init__(self, name: str, region: Region, syntax: str, type: int, kind: Tuple[int, str, str]) -> None: @@ -2894,19 +2894,19 @@ class SymbolLocation: """ Contains information about a file that contains a symbol. """ - path: str = ... + path: str """The filesystem path to the file containing the symbol.""" - display_name: str = ... + display_name: str """The project-relative path to the file containing the symbol.""" - row: int = ... + row: int """The row of the file the symbol is contained on.""" - col: int = ... + col: int """The column of the row that the symbol is contained on.""" - syntax: str = ... + syntax: str """The name of the syntax for the symbol.""" - type: int = ... + type: int """The type of the symbol.""" - kind: Tuple[int, str, str] = ... + kind: Tuple[int, str, str] """The kind of the symbol.""" def __init__( diff --git a/stubs/sublime_plugin.pyi b/stubs/sublime_plugin.pyi index e26f168d3..04626a950 100644 --- a/stubs/sublime_plugin.pyi +++ b/stubs/sublime_plugin.pyi @@ -3,7 +3,7 @@ from sublime import Buffer, CompletionItem, CompletionList, Edit, Html, ListInpu from typing import Any, Dict, List, Tuple -view_event_listeners: Dict[int, List[ViewEventListener]] = ... +view_event_listeners: Dict[int, List[ViewEventListener]] class CommandInputHandler: @@ -203,7 +203,7 @@ class WindowCommand(Command): """ A `Command` instantiated once per window. The `Window` object may be retrieved via `self.window`. """ - window: Window = ... + window: Window """The `Window` this command is attached to.""" def __init__(self, window: Window) -> None: @@ -215,7 +215,7 @@ class TextCommand(Command): A `Command` instantiated once per `View`. The `View` object may be retrieved via `self.view `. """ - view: View = ... + view: View """The `View` this command is attached to.""" def __init__(self, view: View) -> None: @@ -570,7 +570,7 @@ class ViewEventListener: A class that provides similar event handling to `EventListener`, but bound to a specific view. Provides class method-based filtering to control what views objects are created for. """ - view: View = ... + view: View @classmethod def is_applicable(cls, settings: Settings) -> bool: @@ -788,7 +788,7 @@ class TextChangeListener: A class that provides event handling about text changes made to a specific `Buffer`. Is separate from `ViewEventListener` since multiple views can share a single buffer. """ - buffer: Buffer = ... + buffer: Buffer @classmethod def is_applicable(cls, buffer: Buffer) -> bool: From a83e4e84c5e13f40cd7f28dae51043247f2433b5 Mon Sep 17 00:00:00 2001 From: Janos Wortmann Date: Sat, 2 Dec 2023 05:06:24 +0100 Subject: [PATCH 07/11] Mark undocumented objects See https://typing.readthedocs.io/en/latest/source/stubs.html#undocumented-objects --- stubs/sublime.pyi | 26 +++++++++++++------------- stubs/sublime_plugin.pyi | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index f036e5d83..2c3395bc3 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -1749,13 +1749,13 @@ class View: """ ... - # def begin_edit(self, edit_token: int, cmd: str, args: Dict[str, Any] | None = ...) -> Edit: + # def begin_edit(self, edit_token: int, cmd: str, args: Dict[str, Any] | None = ...) -> Edit: # undocumented # ... - # def end_edit(self, edit: Edit) -> None: + # def end_edit(self, edit: Edit) -> None: # undocumented # ... - # def is_in_edit(self) -> bool: + # def is_in_edit(self) -> bool: # undocumented # ... def insert(self, edit: Edit, pt: int, text: str) -> None: @@ -1957,13 +1957,13 @@ class View: """ ... - # def indented_region(self, pt: int) -> Region: + # def indented_region(self, pt: int) -> Region: # undocumented # ... - # def indentation_level(self, pt: int) -> int: + # def indentation_level(self, pt: int) -> int: # undocumented # ... - def has_non_empty_selection_region(self) -> bool: + def has_non_empty_selection_region(self) -> bool: # undocumented ... def lines(self, r: Region) -> List[Region]: @@ -2282,19 +2282,19 @@ class View: # def add_phantom( # self, key: str, region: Region, content: str, layout: int, on_navigate: Callable[[str], None] | None = ... - # ) -> int: + # ) -> int: # undocumented # ... - # def erase_phantoms(self, key: str) -> None: + # def erase_phantoms(self, key: str) -> None: # undocumented # ... - # def erase_phantom_by_id(self, pid: int) -> None: + # def erase_phantom_by_id(self, pid: int) -> None: # undocumented # ... - # def query_phantom(self, pid: int) -> List[Region]: + # def query_phantom(self, pid: int) -> List[Region]: # undocumented # ... - # def query_phantoms(self, pids: List[int]) -> List[Region]: + # def query_phantoms(self, pids: List[int]) -> List[Region]: # undocumented # ... def assign_syntax(self, syntax: str | Syntax) -> None: @@ -2372,10 +2372,10 @@ class View: """ ... - # def find_all_results(self) -> List[Tuple[str, int, int]]: + # def find_all_results(self) -> List[Tuple[str, int, int]]: # undocumented # ... - # def find_all_results_with_text(self) -> List[Tuple[str, int, int]]: + # def find_all_results_with_text(self) -> List[Tuple[str, int, int]]: # undocumented # ... def command_history(self, delta: int, modifying_only: bool = ...) -> Tuple[Optional[str], Optional[dict], int]: diff --git a/stubs/sublime_plugin.pyi b/stubs/sublime_plugin.pyi index 04626a950..50945641c 100644 --- a/stubs/sublime_plugin.pyi +++ b/stubs/sublime_plugin.pyi @@ -3,7 +3,7 @@ from sublime import Buffer, CompletionItem, CompletionList, Edit, Html, ListInpu from typing import Any, Dict, List, Tuple -view_event_listeners: Dict[int, List[ViewEventListener]] +view_event_listeners: Dict[int, List[ViewEventListener]] # undocumented class CommandInputHandler: From 66a892cd28be88cfeadfa27a9e3b96f4b1aa71f2 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 4 Dec 2023 23:30:45 +0100 Subject: [PATCH 08/11] add NO_UNDO flags to all regions --- plugin/code_lens.py | 3 ++- plugin/core/types.py | 40 +++++++++++++++++++++------------------- plugin/core/views.py | 5 +++-- plugin/diagnostics.py | 2 +- plugin/documents.py | 2 +- plugin/references.py | 2 +- plugin/session_buffer.py | 3 ++- plugin/session_view.py | 7 ++++--- 8 files changed, 35 insertions(+), 29 deletions(-) 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/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..94ada3ed3 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -53,9 +53,10 @@ 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 +DOCUMENT_LINK_FLAGS = sublime.HIDE_ON_MINIMAP | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_SOLID_UNDERLINE | sublime.NO_UNDO # noqa: E501 +SEMANTIC_TOKEN_FLAGS = sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO -_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 DIAGNOSTIC_SEVERITY = [ # Kind CSS class Scope for color Icon resource add_regions flags for single-line diagnostic multi-line diagnostic # noqa: E501 diff --git a/plugin/diagnostics.py b/plugin/diagnostics.py index 0e0ea5831..2495abbb7 100644 --- a/plugin/diagnostics.py +++ b/plugin/diagnostics.py @@ -23,7 +23,7 @@ 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..ce798a269 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -40,6 +40,7 @@ from .core.views import MissingUriError from .core.views import range_to_region from .core.views import region_to_range +from .core.views import SEMANTIC_TOKEN_FLAGS from .core.views import text_document_identifier from .core.views import will_save from .inlay_hint import inlay_hint_to_phantom @@ -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..b9978d287 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -300,7 +300,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 = sublime.NO_UNDO 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 +320,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 +341,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) From 98a8a1d7772f7e9a973ec942c1e379fca4af5489 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Tue, 5 Dec 2023 22:16:14 +0100 Subject: [PATCH 09/11] move to constants --- plugin/core/constants.py | 4 ++++ plugin/core/views.py | 3 --- plugin/session_buffer.py | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/core/constants.py b/plugin/core/constants.py index efe2753b8..82600b0c1 100644 --- a/plugin/core/constants.py +++ b/plugin/core/constants.py @@ -19,6 +19,10 @@ 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 +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/views.py b/plugin/core/views.py index 94ada3ed3..2e0bdbe8c 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -53,9 +53,6 @@ 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 | sublime.NO_UNDO # noqa: E501 -SEMANTIC_TOKEN_FLAGS = sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO - _baseflags = sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.NO_UNDO DIAGNOSTIC_SEVERITY = [ diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index ce798a269..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,13 +36,11 @@ 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 from .core.views import range_to_region from .core.views import region_to_range -from .core.views import SEMANTIC_TOKEN_FLAGS from .core.views import text_document_identifier from .core.views import will_save from .inlay_hint import inlay_hint_to_phantom From 14970e7a3c526b6653993e83ffdd0e0d9b35fba8 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Wed, 6 Dec 2023 20:03:24 +0100 Subject: [PATCH 10/11] fix multiline highlight --- plugin/core/views.py | 9 +++++---- plugin/session_view.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/core/views.py b/plugin/core/views.py index 2e0bdbe8c..060de4264 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -54,13 +54,14 @@ MarkdownLangMap = Dict[str, Tuple[Tuple[str, ...], Tuple[str, ...]]] _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/session_view.py b/plugin/session_view.py index b9978d287..84496ea81 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -300,7 +300,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 = sublime.NO_UNDO if userprefs().show_multiline_diagnostics_highlights else sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE | sublime.NO_UNDO # 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( From 3db87b8b2185900b5187c441f22ec643bce707b6 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Sun, 10 Dec 2023 17:46:23 +0100 Subject: [PATCH 11/11] add REGIONS_INITIALIZE_FLAGS --- plugin/core/constants.py | 1 + plugin/diagnostics.py | 3 ++- plugin/session_view.py | 22 +++++++++++++--------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/plugin/core/constants.py b/plugin/core/constants.py index 82600b0c1..2a1fa9dec 100644 --- a/plugin/core/constants.py +++ b/plugin/core/constants.py @@ -21,6 +21,7 @@ # 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 diff --git a/plugin/diagnostics.py b/plugin/diagnostics.py index 2495abbb7..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,7 +18,7 @@ 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) diff --git a/plugin/session_view.py b/plugin/session_view.py index 84496ea81..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: