diff --git a/pyproject.toml b/pyproject.toml index 466a029..9fab1a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,9 @@ source = "vcs" version-file = "sublime_lib/_version.py" tag-pattern = "v{version}" +[tool.black] +line-length = 100 + [tool.coverage.run] omit = [ "*/tests/*", diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi index fe2b920..80f943e 100644 --- a/stubs/sublime.pyi +++ b/stubs/sublime.pyi @@ -1,47 +1,138 @@ -from typing import Tuple, List, Any, Union, Callable, Optional, TypeVar, Collection +""" +API from ST4202 +""" -location = Tuple[str, str, Tuple[int, int]] -vector = Tuple[float, float] -value = Union[bool, int, float, str, list, dict, None] +from __future__ import annotations +import enum +from collections.abc import Iterable, Iterator, Mapping +from sublime_types import CommandArgs, CompletionValue, DIP, Kind, Point, Value, Vector +from typing import Callable, Literal, override +from typing_extensions import TypeAlias -T = TypeVar('T') -Callback0 = Callable[[], Any] -Callback1 = Callable[[T], Any] +class FileTooLargeError(FileNotFoundError): ... + +class HoverZone(enum.IntEnum): + TEXT = 1 + GUTTER = 2 + MARGIN = 3 HOVER_TEXT: int HOVER_GUTTER: int HOVER_MARGIN: int +class NewFileFlags(enum.IntFlag): + NONE = 0 + ENCODED_POSITION = 1 + TRANSIENT = 4 + FORCE_GROUP = 8 + SEMI_TRANSIENT = 16 + ADD_TO_SELECTION = 32 + REPLACE_MRU = 64 + CLEAR_TO_RIGHT = 128 + FORCE_CLONE = 256 + ENCODED_POSITION: int TRANSIENT: int FORCE_GROUP: int -IGNORECASE: int +SEMI_TRANSIENT: int +ADD_TO_SELECTION: int +REPLACE_MRU: int +CLEAR_TO_RIGHT: int +FORCE_CLONE: int + +class FindFlags(enum.IntFlag): + NONE = 0 + LITERAL = 1 + IGNORECASE = 2 + WHOLEWORD = 4 + REVERSE = 8 + WRAP = 16 + LITERAL: int +IGNORECASE: int +WHOLEWORD: int +REVERSE: int +WRAP: int + +class QuickPanelFlags(enum.IntFlag): + NONE = 0 + MONOSPACE_FONT = 1 + KEEP_OPEN_ON_FOCUS_LOST = 2 + WANT_EVENT = 4 + MONOSPACE_FONT: int KEEP_OPEN_ON_FOCUS_LOST: int +WANT_EVENT: int + +class PopupFlags(enum.IntFlag): + NONE = 0 + COOPERATE_WITH_AUTO_COMPLETE = 2 + HIDE_ON_MOUSE_MOVE = 4 + HIDE_ON_MOUSE_MOVE_AWAY = 8 + KEEP_ON_SELECTION_MODIFIED = 16 + HIDE_ON_CHARACTER_EVENT = 32 + HTML: int COOPERATE_WITH_AUTO_COMPLETE: int HIDE_ON_MOUSE_MOVE: int HIDE_ON_MOUSE_MOVE_AWAY: int +KEEP_ON_SELECTION_MODIFIED: int +HIDE_ON_CHARACTER_EVENT: int + +class RegionFlags(enum.IntFlag): + NONE = 0 + DRAW_EMPTY = 1 + HIDE_ON_MINIMAP = 2 + DRAW_EMPTY_AS_OVERWRITE = 4 + PERSISTENT = 16 + DRAW_NO_FILL = 32 + HIDDEN = 128 + DRAW_NO_OUTLINE = 256 + DRAW_SOLID_UNDERLINE = 512 + DRAW_STIPPLED_UNDERLINE = 1024 + DRAW_SQUIGGLY_UNDERLINE = 2048 + NO_UNDO = 8192 DRAW_EMPTY: int HIDE_ON_MINIMAP: int DRAW_EMPTY_AS_OVERWRITE: int PERSISTENT: int -DRAW_OUTLINED: int DRAW_NO_FILL: int +DRAW_OUTLINED = DRAW_NO_FILL DRAW_NO_OUTLINE: int DRAW_SOLID_UNDERLINE: int DRAW_STIPPLED_UNDERLINE: int DRAW_SQUIGGLY_UNDERLINE: int +NO_UNDO: int HIDDEN: int +class QueryOperator(enum.IntEnum): + EQUAL = 0 + NOT_EQUAL = 1 + REGEX_MATCH = 2 + NOT_REGEX_MATCH = 3 + REGEX_CONTAINS = 4 + NOT_REGEX_CONTAINS = 5 + 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 PointClassification(enum.IntFlag): + NONE = 0 + WORD_START = 1 + WORD_END = 2 + PUNCTUATION_START = 4 + PUNCTUATION_END = 8 + SUB_WORD_START = 16 + SUB_WORD_END = 32 + LINE_START = 64 + LINE_END = 128 + EMPTY_LINE = 256 + CLASS_WORD_START: int CLASS_WORD_END: int CLASS_PUNCTUATION_START: int @@ -51,120 +142,247 @@ CLASS_SUB_WORD_END: int CLASS_LINE_START: int CLASS_LINE_END: int CLASS_EMPTY_LINE: int + +class AutoCompleteFlags(enum.IntFlag): + NONE = 0 + INHIBIT_WORD_COMPLETIONS = 8 + INHIBIT_EXPLICIT_COMPLETIONS = 16 + DYNAMIC_COMPLETIONS = 32 + INHIBIT_REORDER = 128 + INHIBIT_WORD_COMPLETIONS: int INHIBIT_EXPLICIT_COMPLETIONS: int +DYNAMIC_COMPLETIONS: int +INHIBIT_REORDER: int + +class CompletionItemFlags(enum.IntFlag): + NONE = 0 + KEEP_PREFIX = 1 + +COMPLETION_FLAG_KEEP_PREFIX: int + +class DialogResult(enum.IntEnum): + CANCEL = 0 + YES = 1 + NO = 2 DIALOG_CANCEL: int DIALOG_YES: int DIALOG_NO: int -UI_ELEMENT_SIDE_BAR: int -UI_ELEMENT_MINIMAP: int -UI_ELEMENT_TABS: int -UI_ELEMENT_STATUS_BAR: int -UI_ELEMENT_MENU: int -UI_ELEMENT_OPEN_FILES: int +class UIElement(enum.IntEnum): + SIDE_BAR = 1 + MINIMAP = 2 + TABS = 4 + STATUS_BAR = 8 + MENU = 16 + OPEN_FILES = 32 + +class PhantomLayout(enum.IntEnum): + INLINE = 0 + BELOW = 1 + BLOCK = 2 LAYOUT_INLINE: int LAYOUT_BELOW: int LAYOUT_BLOCK: int +class KindId(enum.IntEnum): + AMBIGUOUS = 0 + KEYWORD = 1 + TYPE = 2 + FUNCTION = 3 + NAMESPACE = 4 + NAVIGATION = 5 + MARKUP = 6 + VARIABLE = 7 + SNIPPET = 8 + COLOR_REDISH = 9 + COLOR_ORANGISH = 10 + COLOR_YELLOWISH = 11 + COLOR_GREENISH = 12 + COLOR_CYANISH = 13 + COLOR_BLUISH = 14 + COLOR_PURPLISH = 15 + COLOR_PINKISH = 16 + COLOR_DARK = 17 + COLOR_LIGHT = 18 + +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: Kind +KIND_KEYWORD: Kind +KIND_TYPE: Kind +KIND_FUNCTION: Kind +KIND_NAMESPACE: Kind +KIND_NAVIGATION: Kind +KIND_MARKUP: Kind +KIND_VARIABLE: Kind +KIND_SNIPPET: Kind + +class SymbolSource(enum.IntEnum): + ANY = 0 + INDEX = 1 + OPEN_FILES = 2 + +SYMBOL_SOURCE_ANY: int +SYMBOL_SOURCE_INDEX: int +SYMBOL_SOURCE_OPEN_FILES: int + +class SymbolType(enum.IntEnum): + ANY = 0 + DEFINITION = 1 + REFERENCE = 2 + +SYMBOL_TYPE_ANY: int +SYMBOL_TYPE_DEFINITION: int +SYMBOL_TYPE_REFERENCE: int + +class CompletionFormat(enum.IntEnum): + TEXT = 0 + SNIPPET = 1 + COMMAND = 2 + +COMPLETION_FORMAT_TEXT: int +COMPLETION_FORMAT_SNIPPET: int +COMPLETION_FORMAT_COMMAND: int + def version() -> str: ... -def platform() -> str: ... -def arch() -> str: ... -def channel() -> str: ... +def platform() -> Literal['osx', 'linux', 'windows']: ... +def arch() -> Literal['x32', 'x64', 'arm64']: ... +def channel() -> Literal['dev', 'stable']: ... def executable_path() -> str: ... -def executable_hash() -> Tuple[str, str, str]: ... +def executable_hash() -> tuple[str, str, str]: ... def packages_path() -> str: ... def installed_packages_path() -> str: ... def cache_path() -> str: ... +def lib_path() -> str: ... def status_message(msg: str) -> None: ... def error_message(msg: str) -> None: ... def message_dialog(msg: str) -> None: ... -def ok_cancel_dialog(msg: str, ok_title: str = "") -> bool: ... -def yes_no_cancel_dialog(msg: str, yes_title: str = "", no_title: str = "") -> int: ... -def run_command(cmd: str, args: Optional[dict] = None) -> None: ... +def ok_cancel_dialog(msg: str, ok_title: str = '', title: str = '') -> bool: ... +def yes_no_cancel_dialog(msg: str, yes_title: str = '', no_title: str = '', title: str = '') -> DialogResult: ... +def open_dialog(callback: Callable[[str | list[str] | None], None], file_types: list[tuple[str, list[str]]] = [], directory: str | None = None, multi_select: bool = False, allow_folders: bool = False) -> None: ... +def save_dialog(callback: Callable[[str | None], None], file_types: list[tuple[str, list[str]]] = [], directory: str | None = None, name: str | None = None, extension: str | None = None) -> None: ... +def select_folder_dialog(callback: Callable[[str | list[str] | None], None], directory: str | None = None, multi_select: bool = False) -> None: ... +def choose_font_dialog(callback: Callable[[Value], None], default: dict[str, Value] | None = None) -> None: ... +def run_command(cmd: str, args: CommandArgs = None) -> None: ... +def format_command(cmd: str, args: CommandArgs = None) -> str: ... +def html_format_command(cmd: str, args: CommandArgs = None) -> str: ... +def command_url(cmd: str, args: CommandArgs = None) -> str: ... +def get_clipboard_async(callback: Callable[[str], None], size_limit: int = 16777216) -> None: ... def get_clipboard(size_limit: int = 16777216) -> str: ... def set_clipboard(text: str) -> None: ... -def log_commands(flag: bool) -> None: ... -def log_input(flag: bool) -> None: ... -def log_result_regex(flag: bool) -> None: ... -def log_indexing(flag: bool) -> None: ... -def log_build_systems(flag: bool) -> None: ... +def log_commands(flag: bool | None = None) -> None: ... +def get_log_commands() -> bool: ... +def log_input(flag: bool | None = None) -> None: ... +def get_log_input() -> bool: ... +def log_fps(flag: bool | None = None) -> None: ... +def get_log_fps() -> bool: ... +def log_result_regex(flag: bool | None = None) -> None: ... +def get_log_result_regex() -> bool: ... +def log_indexing(flag: bool | None = None) -> None: ... +def get_log_indexing() -> bool: ... +def log_build_systems(flag: bool | None = None) -> None: ... +def get_log_build_systems() -> bool: ... +def log_control_tree(flag: bool | None = None) -> None: ... +def get_log_control_tree() -> bool: ... +def ui_info() -> dict[str, Value]: ... def score_selector(scope_name: str, selector: str) -> int: ... -def load_resource(name: str) -> str: ... -def load_binary_resource(name: str) -> bytes: ... -def find_resources(pattern: str) -> List[str]: ... -def encode_value(val: Any, pretty: bool = False) -> str: ... -def decode_value(data: str) -> Any: ... -def expand_variables(val: Union[str, list, dict], variables: dict) -> str: ... +def load_resource(name: str, max_size: int = ...) -> str: ... +def load_binary_resource(name: str, max_size: int = ...) -> bytes: ... +def find_resources(pattern: str) -> list[str]: ... +def encode_value(value: Value, pretty: bool = False, update_text: str | None = None) -> str: ... +def decode_value(data: str) -> Value: ... +def expand_variables(value: Value, variables: dict[str, str]) -> Value: ... def load_settings(base_name: str) -> Settings: ... def save_settings(base_name: str) -> None: ... -def set_timeout(f: Callback0, timeout_ms: int = 0) -> None: ... -def set_timeout_async(f: Callback0, timeout_ms: int = 0) -> None: ... +def set_timeout(callback: Callable[[], None], delay: int = 0) -> None: ... +def set_timeout_async(callback: Callable[[], None], delay: int = 0) -> None: ... def active_window() -> Window: ... -def windows() -> List[Window]: ... -def get_macro() -> list: ... +def windows() -> list[Window]: ... +def get_macro() -> list[dict[str, str | CommandArgs]]: ... +def project_history() -> list[str]: ... +def folder_history() -> list[str]: ... class Window: - def __init__(self, id: int): ... - def __eq__(self, other: Any) -> bool: ... + window_id: int + settings_object: Settings | None + template_settings_object: Settings | None + def __init__(self, id: int) -> None: ... + @override + def __hash__(self) -> int: ... + @override + def __eq__(self, other: object) -> bool: ... def __bool__(self) -> bool: ... def id(self) -> int: ... def is_valid(self) -> bool: ... def hwnd(self) -> int: ... - def active_sheet(self) -> Optional[Sheet]: ... - def active_view(self) -> Optional[View]: ... - def run_command(self, cmd: str, args: Optional[dict] = None) -> None: ... - def new_file(self, flags: int = 0, syntax: str = "") -> View: ... - def open_file(self, fname: str, flags: int = 0, group: int = -1) -> View: ... - def find_open_file(self, fname: str) -> Optional[View]: ... + def active_sheet(self) -> Sheet | None: ... + def active_view(self) -> View | None: ... + def new_html_sheet(self, name: str, contents: str, flags: NewFileFlags = ..., group: int = -1) -> Sheet: ... + def run_command(self, cmd: str, args: CommandArgs = None) -> None: ... + def new_file(self, flags: NewFileFlags = ..., syntax: str = '') -> View: ... + def open_file(self, fname: str, flags: NewFileFlags = ..., group: int = -1) -> View: ... + def find_open_file(self, fname: str, group: int = -1) -> View | None: ... + def file_history(self) -> list[str]: ... def num_groups(self) -> int: ... def active_group(self) -> int: ... def focus_group(self, idx: int) -> None: ... def focus_sheet(self, sheet: Sheet) -> None: ... def focus_view(self, view: View) -> None: ... - def get_sheet_index(self, sheet: Sheet) -> Tuple[int, int]: ... - def get_view_index(self, view: View) -> Tuple[int, int]: ... - def set_sheet_index(self, sheet: Sheet, group: int, idx: int) -> None: ... - def set_view_index(self, view: View, group: int, idx: int) -> None: ... - def sheets(self) -> List[Sheet]: ... - def views(self) -> List[View]: ... - def active_sheet_in_group(self, group: int) -> Optional[Sheet]: ... - def active_view_in_group(self, group: int) -> Optional[View]: ... - def sheets_in_group(self, group: int) -> List[Sheet]: ... - def views_in_group(self, group: int) -> List[View]: ... - def transient_sheet_in_group(self, group: int) -> Optional[Sheet]: ... - def transient_view_in_group(self, group: int) -> Optional[View]: ... - def layout(self) -> dict: ... - def get_layout(self) -> dict: ... - def set_layout(self, layout: dict) -> None: ... + def select_sheets(self, sheets: list[Sheet]) -> None: ... + def bring_to_front(self) -> None: ... + def get_sheet_index(self, sheet: Sheet) -> tuple[int, int]: ... + def get_view_index(self, view: View) -> tuple[int, int]: ... + def set_sheet_index(self, sheet: Sheet, group: int, index: int) -> None: ... + def set_view_index(self, view: View, group: int, index: int) -> None: ... + def move_sheets_to_group(self, sheets: list[Sheet], group: int, insertion_idx: int = -1, select: bool = True) -> None: ... + def sheets(self) -> list[Sheet]: ... + def views(self, *, include_transient: bool = False) -> list[View]: ... + def selected_sheets(self) -> list[Sheet]: ... + def selected_sheets_in_group(self, group: int) -> list[Sheet]: ... + def active_sheet_in_group(self, group: int) -> Sheet | None: ... + def active_view_in_group(self, group: int) -> View | None: ... + def sheets_in_group(self, group: int) -> list[Sheet]: ... + def views_in_group(self, group: int) -> list[View]: ... + def num_sheets_in_group(self, group: int) -> int: ... + def num_views_in_group(self, group: int) -> int: ... + def transient_sheet_in_group(self, group: int) -> Sheet | None: ... + def transient_view_in_group(self, group: int) -> View | None: ... + def promote_sheet(self, sheet: Sheet) -> None: ... + def layout(self) -> dict[str, Value]: ... + def get_layout(self) -> dict[str, Value]: ... + def set_layout(self, layout: dict[str, Value]) -> None: ... def create_output_panel(self, name: str, unlisted: bool = False) -> View: ... - def find_output_panel(self, name: str) -> Optional[View]: ... + def find_output_panel(self, name: str) -> View | None: ... def destroy_output_panel(self, name: str) -> None: ... - def active_panel(self) -> Optional[str]: ... - def panels(self) -> List[str]: ... + def create_io_panel(self, name: str, on_input: Callable[[str], None], unlisted: bool = False) -> tuple[View, View]: ... + def find_io_panel(self, name: str) -> tuple[View | None, View | None]: ... + def active_panel(self) -> str | None: ... + def panels(self) -> list[str]: ... def get_output_panel(self, name: str) -> View: ... - def show_input_panel( - self, - caption: str, - initial_text: str, - on_done: Optional[Callback0], - on_change: Optional[Callback1[str]], - on_cancel: Optional[Callback0] - ) -> View: ... - - def show_quick_panel( - self, - items: Union[List[str], List[List[str]]], - on_select: Callback1[int], - flags: int = 0, - selected_index: int = -1, - on_highlight: Optional[Callback1[int]] = None - ) -> 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: ... + def show_quick_panel(self, items: list[str] | list[list[str]] | list[QuickPanelItem], on_select: Callable[[int], None], flags: QuickPanelFlags = ..., selected_index: int = -1, on_highlight: Callable[[int], None] | None = None, placeholder: str | None = None) -> None: ... def is_sidebar_visible(self) -> bool: ... - def set_sidebar_visible(self, flag: bool) -> None: ... + def set_sidebar_visible(self, flag: bool, animate: bool = True) -> None: ... def is_minimap_visible(self) -> bool: ... def set_minimap_visible(self, flag: bool) -> None: ... def is_status_bar_visible(self) -> bool: ... @@ -173,78 +391,141 @@ class Window: def set_tabs_visible(self, flag: bool) -> None: ... def is_menu_visible(self) -> bool: ... def set_menu_visible(self, flag: bool) -> None: ... - def folders(self) -> List[str]: ... - def project_file_name(self) -> Optional[str]: ... - def project_data(self) -> dict: ... - def set_project_data(self, v: dict) -> None: ... + def folders(self) -> list[str]: ... + def project_file_name(self) -> str | None: ... + def workspace_file_name(self) -> str | None: ... + def project_data(self) -> dict[str, Value] | None: ... + def set_project_data(self, data: dict[str, Value]) -> None: ... def settings(self) -> Settings: ... def template_settings(self) -> Settings: ... - def lookup_symbol_in_index(self, sym: str) -> List[location]: ... - def lookup_symbol_in_open_files(self, sym: str) -> List[location]: ... - def lookup_references_in_index(self, sym: str) -> List[location]: ... - def lookup_references_in_open_files(self, sym: str) -> List[location]: ... - def extract_variables(self) -> dict: ... + def symbol_locations(self, sym: str, source: SymbolSource = ..., type: SymbolType = ..., kind_id: KindId = ..., kind_letter: str = '') -> list[SymbolLocation]: ... + def lookup_symbol_in_index(self, symbol: str) -> list[SymbolLocation]: ... + def lookup_symbol_in_open_files(self, symbol: str) -> list[SymbolLocation]: ... + def lookup_references_in_index(self, symbol: str) -> list[SymbolLocation]: ... + def lookup_references_in_open_files(self, symbol: str) -> list[SymbolLocation]: ... + def extract_variables(self) -> dict[str, str]: ... def status_message(self, msg: str) -> None: ... class Edit: + edit_token: int def __init__(self, token: int) -> None: ... class Region: - __slots__ = ['a', 'b', 'xpos'] - - a = 0 # type: int - b = 0 # type: int - xpos = 0 # type: int - - def __init__(self, a: int, b: Optional[int] = None, xpos: int = -1): ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... + a: Point + b: Point + xpos: DIP + def __init__(self, a: Point, b: Point | None = None, xpos: DIP = -1) -> None: ... + def __iter__(self) -> Iterator[int]: ... def __len__(self) -> int: ... - def __eq__(self, rhs: Any) -> bool: ... + @override + def __eq__(self, rhs: object) -> bool: ... def __lt__(self, rhs: Region) -> bool: ... + def __contains__(self, v: Region | Point) -> bool: ... + def to_tuple(self) -> tuple[Point, Point]: ... def empty(self) -> bool: ... - def begin(self) -> int: ... - def end(self) -> int: ... + def begin(self) -> Point: ... + def end(self) -> Point: ... def size(self) -> int: ... - def contains(self, x: Union[int, Region]) -> bool: ... - def cover(self, rhs: Region) -> Region: ... - def intersection(self, rhs: Region) -> Region: ... - def intersects(self, rhs: Region) -> bool: ... + def contains(self, x: Point) -> bool: ... + def cover(self, region: Region) -> Region: ... + def intersection(self, region: Region) -> Region: ... + def intersects(self, region: Region) -> bool: ... + +class HistoricPosition: + pt: Point + row: int + col: int + col_utf16: int + col_utf8: int + def __init__(self, pt: Point, row: int, col: int, col_utf16: int, col_utf8: int) -> None: ... + +Str: TypeAlias = str + +class TextChange: + a: HistoricPosition + b: HistoricPosition + len_utf16: int + len_utf8: int + str: Str + def __init__(self, pa: HistoricPosition, pb: HistoricPosition, len_utf16: int, len_utf8: int, s: Str) -> None: ... class Selection: + view_id: int def __init__(self, id: int) -> None: ... + def __iter__(self) -> Iterator[Region]: ... def __len__(self) -> int: ... def __getitem__(self, index: int) -> Region: ... def __delitem__(self, index: int) -> None: ... - def __eq__(self, rhs: Any) -> bool: ... - def __lt__(self, rhs: Selection) -> bool: ... + @override + def __eq__(self, rhs: object) -> bool: ... + def __lt__(self, rhs: Selection | None) -> bool: ... def __bool__(self) -> bool: ... def is_valid(self) -> bool: ... def clear(self) -> None: ... - def add(self, x: Region) -> None: ... - def add_all(self, regions: List[Region]) -> None: ... + def add(self, x: Region | Point) -> None: ... + def add_all(self, regions: Iterable[Region | Point]) -> None: ... def subtract(self, region: Region) -> None: ... def contains(self, region: Region) -> bool: ... + def has_empty_region(self) -> bool: ... + def has_non_empty_region(self) -> bool: ... + def has_multiple_non_empty_regions(self) -> bool: ... + +def make_sheet(sheet_id: int) -> Sheet: ... class Sheet: + sheet_id: int def __init__(self, id: int) -> None: ... - def __eq__(self, other: Any) -> bool: ... + @override + def __hash__(self) -> int: ... + @override + def __eq__(self, other: object) -> bool: ... def id(self) -> int: ... - def window(self) -> Optional[Window]: ... - def view(self) -> Optional[View]: ... + def window(self) -> Window | None: ... + def view(self) -> View | None: ... + def name(self) -> str | None: ... + def set_name(self, name: str) -> None: ... + def file_name(self) -> str | None: ... + def is_semi_transient(self) -> bool: ... + def is_transient(self) -> bool: ... + def is_selected(self) -> bool: ... + def group(self) -> int | None: ... + def close(self, on_close: Callable[[bool], None] = ...) -> None: ... + +class TextSheet(Sheet): ... +class ImageSheet(Sheet): ... + +class HtmlSheet(Sheet): + def set_contents(self, contents: str) -> None: ... + +class ContextStackFrame: + context_name: str + source_file: str + source_location: tuple[int, int] + def __init__(self, context_name: str, source_file: str, source_location: tuple[int, int]) -> None: ... class View: + view_id: int + selection: Selection + settings_object: Settings | None def __init__(self, id: int) -> None: ... def __len__(self) -> int: ... - def __eq__(self, other: Any) -> bool: ... + @override + def __hash__(self) -> int: ... + @override + def __eq__(self, other: object) -> bool: ... def __bool__(self) -> bool: ... def id(self) -> int: ... def buffer_id(self) -> int: ... + def buffer(self) -> Buffer: ... + def sheet_id(self) -> int: ... + def sheet(self) -> Sheet | None: ... + def element(self) -> str | None: ... def is_valid(self) -> bool: ... def is_primary(self) -> bool: ... - def window(self) -> Optional[Window]: ... - def file_name(self) -> Optional[str]: ... - def close(self) -> bool: ... + def window(self) -> Window | None: ... + def clones(self) -> list[View]: ... + def file_name(self) -> str | None: ... + def close(self, on_close: Callable[[bool], None] = ...) -> bool: ... def retarget(self, new_fname: str) -> None: ... def name(self) -> str: ... def set_name(self, name: str) -> None: ... @@ -261,122 +542,227 @@ class View: def line_endings(self) -> str: ... def set_line_endings(self, line_ending_name: str) -> None: ... def size(self) -> int: ... - def begin_edit(self, edit_token: int, cmd: str, args: Optional[dict] = None) -> Edit: ... + def begin_edit(self, edit_token: int, cmd: str, args: CommandArgs = 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: ... - def erase(self, edit: Edit, r: Region) -> None: ... - def replace(self, edit: Edit, r: Region, text: str) -> None: ... + def insert(self, edit: Edit, pt: Point, text: str) -> int: ... + def erase(self, edit: Edit, region: Region) -> None: ... + def replace(self, edit: Edit, region: Region, text: str) -> None: ... def change_count(self) -> int: ... - def run_command(self, cmd: str, args: Optional[dict] = None) -> None: ... + def change_id(self) -> tuple[int, int, int]: ... + def transform_region_from(self, region: Region, change_id: tuple[int, int, int]) -> Region: ... + def run_command(self, cmd: str, args: CommandArgs = None) -> None: ... def sel(self) -> Selection: ... - def substr(self, x: Union[Region, int]) -> str: ... - def find(self, pattern: str, start_pt: int, flags: int = 0) -> Region: ... - def find_all(self, pattern: str, flags: int = 0, fmt: Optional[str] = None, extractions: Optional[list] = None) -> List[Region]: ... + def substr(self, x: Region | Point) -> str: ... + def find(self, pattern: str, start_pt: Point, flags: FindFlags = ...) -> Region: ... + def find_all(self, pattern: str, flags: FindFlags = ..., fmt: str | None = None, extractions: list[str] | None = None, within: Region | list[Region] | None = None) -> list[Region]: ... def settings(self) -> Settings: ... - def meta_info(self, key: str, pt: int) -> dict: ... - def extract_tokens_with_scopes(self, r: Region) -> List[Tuple[Region, str]]: ... - def extract_scope(self, pt: int) -> Region: ... - def scope_name(self, pt: int) -> str: ... - def match_selector(self, pt: int, selector: str) -> bool: ... - def score_selector(self, pt: int, selector: str) -> int: ... - def find_by_selector(self, selector: str) -> List[Region]: ... - def style(self) -> dict: ... - def style_for_scope(self, scope: str) -> dict: ... - def indented_region(self, pt: int) -> Region: ... - def indentation_level(self, pt: int) -> int: ... + def meta_info(self, key: str, pt: Point) -> Value: ... + def extract_tokens_with_scopes(self, region: Region) -> list[tuple[Region, str]]: ... + def extract_scope(self, pt: Point) -> Region: ... + def expand_to_scope(self, pt: Point, selector: str) -> Region | None: ... + def scope_name(self, pt: Point) -> str: ... + def context_backtrace(self, pt: Point) -> list[ContextStackFrame]: ... + def match_selector(self, pt: Point, selector: str) -> bool: ... + def score_selector(self, pt: Point, selector: str) -> int: ... + def find_by_selector(self, selector: str) -> list[Region]: ... + def style(self) -> dict[str, str]: ... + def style_for_scope(self, scope: str) -> dict[str, Value]: ... + def indented_region(self, pt: Point) -> Region: ... + def indentation_level(self, pt: Point) -> int: ... def has_non_empty_selection_region(self) -> bool: ... - def lines(self, r: Region) -> List[Region]: ... - def split_by_newlines(self, r: Region) -> List[Region]: ... - def line(self, x: Union[int, Region]) -> Region: ... - def full_line(self, x: Union[int, Region]) -> Region: ... - def word(self, x: Union[int, Region]) -> Region: ... - def classify(self, pt: int) -> int: ... - def find_by_class(self, pt: int, forward: bool, classes: int, separators: str = "") -> Region: ... - def expand_by_class(self, x: Union[int, Region], classes: int, separators: str = "") -> Region: ... - def rowcol(self, tp: int) -> Tuple[int, int]: ... - def text_point(self, row: int, col: int) -> int: ... + def lines(self, region: Region) -> list[Region]: ... + def split_by_newlines(self, region: Region) -> list[Region]: ... + def line(self, x: Region | Point) -> Region: ... + def full_line(self, x: Region | Point) -> Region: ... + def word(self, x: Region | Point) -> Region: ... + def classify(self, pt: Point) -> PointClassification: ... + def find_by_class(self, pt: Point, forward: bool, classes: PointClassification, separators: str = '', sub_word_separators: str = '') -> Point: ... + def expand_by_class(self, x: Region | Point, classes: PointClassification, separators: str = '', sub_word_separators: str = '') -> Region: ... + def rowcol(self, tp: Point) -> tuple[int, int]: ... + def rowcol_utf8(self, tp: Point) -> tuple[int, int]: ... + def rowcol_utf16(self, tp: Point) -> tuple[int, int]: ... + def text_point(self, row: int, col: int, *, clamp_column: bool = False) -> Point: ... + def text_point_utf8(self, row: int, col: int, *, clamp_column: bool = False) -> Point: ... + def text_point_utf16(self, row: int, col: int, *, clamp_column: bool = False) -> Point: ... + def utf8_code_units(self, tp: Point | None = None) -> int: ... + def utf16_code_units(self, tp: Point | None = None) -> int: ... def visible_region(self) -> Region: ... - def show(self, x: Union[int, Region, Selection], show_surrounds: bool = True) -> None: ... - def show_at_center(self, x: Union[int, Region]) -> None: ... - def viewport_position(self) -> vector: ... - def set_viewport_position(self, xy: vector, animate: bool = True) -> None: ... - def viewport_extent(self) -> vector: ... - def layout_extent(self) -> vector: ... - def text_to_layout(self, tp: int) -> vector: ... - def text_to_window(self, tp: int) -> vector: ... - def layout_to_text(self, xy: vector) -> int: ... - def layout_to_window(self, xy: vector) -> vector: ... - def window_to_layout(self, xy: vector) -> vector: ... - def window_to_text(self, xy: vector) -> int: ... - def line_height(self) -> float: ... - def em_width(self) -> float: ... - def is_folded(self, sr: Region) -> bool: ... - def folded_regions(self) -> List[Region]: ... - def fold(self, x: Union[Region, List[Region]]) -> bool: ... - def unfold(self, x: Union[Region, List[Region]]) -> List[Region]: ... - def add_regions(self, key: str, regions: Collection[Region], scope: str = "", icon: str = "", flags: int = 0) -> None: ... - def get_regions(self, key: str) -> List[Region]: ... + def show(self, location: Region | Selection | Point, show_surrounds: bool = True, keep_to_left: bool = False, animate: bool = True) -> None: ... + def show_at_center(self, location: Region | Point, animate: bool = True) -> None: ... + def viewport_position(self) -> Vector: ... + def set_viewport_position(self, xy: Vector, animate: bool = True) -> None: ... + def viewport_extent(self) -> Vector: ... + def layout_extent(self) -> Vector: ... + def text_to_layout(self, tp: Point) -> Vector: ... + def text_to_window(self, tp: Point) -> Vector: ... + def layout_to_text(self, xy: Vector) -> Point: ... + def layout_to_window(self, xy: Vector) -> Vector: ... + def window_to_layout(self, xy: Vector) -> Vector: ... + def window_to_text(self, xy: Vector) -> Point: ... + def line_height(self) -> DIP: ... + def em_width(self) -> DIP: ... + def is_folded(self, region: Region) -> bool: ... + def folded_regions(self) -> list[Region]: ... + def fold(self, x: Region | list[Region]) -> bool: ... + def unfold(self, x: Region | list[Region]) -> list[Region]: ... + def add_regions(self, key: str, regions: list[Region], scope: str = '', icon: str = '', flags: RegionFlags = ..., annotations: list[str] = [], annotation_color: str = '', on_navigate: Callable[[str], None] | None = None, on_close: Callable[[], None] | None = None) -> None: ... + def get_regions(self, key: str) -> list[Region]: ... def erase_regions(self, key: str) -> None: ... - def add_phantom(self, key: str, region: Region, content: str, layout: int, on_navigate: Optional[Callback1[str]] = None) -> int: ... + def add_phantom(self, key: str, region: Region, content: str, layout: PhantomLayout, on_navigate: Callable[[str], None] | 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[Tuple[int, int]]: ... - def query_phantoms(self, pids: List[int]) -> List[Tuple[int, int]]: ... - def assign_syntax(self, syntax_file: str) -> 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: ... def set_syntax_file(self, syntax_file: str) -> None: ... - def symbols(self) -> List[Tuple[Region, str]]: ... - def get_symbols(self) -> List[Tuple[Region, str]]: ... - def indexed_symbols(self) -> List[Tuple[Region, str]]: ... - def indexed_references(self) -> List[Tuple[Region, str]]: ... + def syntax(self) -> Syntax | None: ... + def symbols(self) -> list[tuple[Region, str]]: ... + def get_symbols(self) -> list[tuple[Region, str]]: ... + def indexed_symbols(self) -> list[tuple[Region, str]]: ... + def indexed_references(self) -> list[tuple[Region, str]]: ... + def symbol_regions(self) -> list[SymbolRegion]: ... + def indexed_symbol_regions(self, type: SymbolType = ...) -> list[SymbolRegion]: ... def set_status(self, key: str, value: str) -> None: ... - def get_status(self, key: str) -> None: ... + def get_status(self, key: str) -> str: ... def erase_status(self, key: str) -> None: ... - def extract_completions(self, prefix: str, tp: int = -1) -> List[str]: ... - def find_all_results(self) -> List[Tuple[str, int, int]]: ... - def find_all_results_with_text(self) -> List[Tuple[str, int, int, str]]: ... - def command_history(self, delta: int, modifying_only: bool = False) -> Tuple[str, dict, int]: ... + def extract_completions(self, prefix: str, tp: Point = -1) -> list[str]: ... + def find_all_results(self) -> list[tuple[str, int, int]]: ... + def find_all_results_with_text(self) -> list[tuple[str, int, int, str]]: ... + def command_history(self, index: int, modifying_only: bool = False) -> tuple[str, CommandArgs, int]: ... def overwrite_status(self) -> bool: ... def set_overwrite_status(self, value: bool) -> None: ... - def show_popup_menu(self, items: List[str], on_select: Callable[[int], Any], flags: int = 0) -> None: ... - def show_popup( - self, - content: str, - flags: int = 0, - location: int = -1, - max_width: int = 320, - max_height: int = 240, - on_navigate: Optional[Callable[[str], Any]] = None, - on_hide: Optional[Callable[[], Any]] = None - ) -> None: ... - + def show_popup_menu(self, items: list[str], on_done: Callable[[int], None], flags: int = 0) -> None: ... + def show_popup(self, content: str, flags: PopupFlags = ..., location: Point = -1, max_width: DIP = 320, max_height: DIP = 240, on_navigate: Callable[[str], None] | None = None, on_hide: Callable[[], None] | None = None) -> None: ... def update_popup(self, content: str) -> None: ... def is_popup_visible(self) -> bool: ... def hide_popup(self) -> None: ... def is_auto_complete_visible(self) -> bool: ... + def preserve_auto_complete_on_focus_lost(self) -> None: ... + def export_to_html(self, regions: Region | list[Region] | None = None, minihtml: bool = False, enclosing_tags: bool = False, font_size: bool = True, font_family: bool = True) -> str: ... + def clear_undo_stack(self) -> None: ... + +class Buffer: + buffer_id: int + def __init__(self, id: int) -> None: ... + @override + def __hash__(self) -> int: ... + @override + def __eq__(self, other: object) -> bool: ... + def id(self) -> int: ... + def file_name(self) -> str | None: ... + def views(self) -> list[View]: ... + def primary_view(self) -> View: ... class Settings: settings_id: int - def __init__(self, id: int) -> None: ... - def get(self, key: str, default: Any = None) -> Any: ... + def __getitem__(self, key: str) -> Value: ... + def __setitem__(self, key: str, value: Value) -> None: ... + def __delitem__(self, key: str) -> None: ... + def __contains__(self, key: str) -> bool: ... + def to_dict(self) -> dict[str, Value]: ... + def setdefault(self, key: str, value: Value) -> Value: ... + def update(self, other: Mapping[str, Value] | Iterable[tuple[str, Value]] | None = None, /, **kwargs: object) -> None: ... + def get(self, key: str, default: Value = None) -> Value: ... def has(self, key: str) -> bool: ... - def set(self, key: str, value: value) -> None: ... + def set(self, key: str, value: Value) -> None: ... def erase(self, key: str) -> None: ... - def add_on_change(self, tag: str, callback: Callable[[], Any]) -> None: ... + def add_on_change(self, tag: str, callback: Callable[[], None]) -> None: ... def clear_on_change(self, tag: str) -> None: ... class Phantom: - def __init__(self, region: Region, content: str, layout: int, on_navigate: Callable[[str], Any] = None) -> None: ... - def __eq__(self, rhs: Any) -> bool: ... + region: Region + content: str + layout: PhantomLayout + on_navigate: Callable[[str], None] | None + id: int | None + def __init__(self, region: Region, content: str, layout: PhantomLayout, on_navigate: Callable[[str], None] | None = None) -> None: ... + @override + def __eq__(self, rhs: object) -> bool: ... + def to_tuple(self) -> tuple[tuple[Point, Point], str, PhantomLayout, Callable[[str], None] | None]: ... class PhantomSet: - def __init__(self, view: View, key: str = "") -> None: ... + view: View + key: str + phantoms: list[Phantom] + def __init__(self, view: View, key: str = '') -> None: ... def __del__(self) -> None: ... - def update(self, new_phantoms: List[Phantom]) -> None: ... + def update(self, phantoms: Iterable[Phantom]) -> None: ... class Html: - __slots__ = ['data'] + data: str + def __init__(self, data: str) -> None: ... + +class CompletionList: + completions: list[CompletionValue] | None + flags: AutoCompleteFlags + def __init__(self, completions: list[CompletionValue] | None = None, flags: AutoCompleteFlags = ...) -> None: ... + def set_completions(self, completions: list[CompletionValue], flags: AutoCompleteFlags = ...) -> None: ... + +class CompletionItem: + trigger: str + annotation: str + completion: str + completion_format: CompletionFormat + kind: Kind + details: str + flags: CompletionItemFlags + def __init__(self, trigger: str, annotation: str = '', completion: str = '', completion_format: CompletionFormat = ..., kind: Kind = ..., details: str = '', flags: CompletionItemFlags = ...) -> None: ... + @override + def __eq__(self, rhs: object) -> bool: ... + @classmethod + def snippet_completion(cls, trigger: str, snippet: str, annotation: str = '', kind: Kind = ..., details: str = '') -> CompletionItem: ... + @classmethod + def command_completion(cls, trigger: str, command: str, args: CommandArgs = None, annotation: str = '', kind: Kind = ..., details: str = '') -> CompletionItem: ... + +def list_syntaxes() -> list[Syntax]: ... +def syntax_from_path(path: str) -> Syntax | None: ... +def find_syntax_by_name(name: str) -> list[Syntax]: ... +def find_syntax_by_scope(scope: str) -> list[Syntax]: ... +def find_syntax_for_file(path: str, first_line: str = '') -> Syntax | None: ... + +class Syntax: + path: str + name: str + hidden: bool + scope: str + def __init__(self, path: str, name: str, hidden: bool, scope: str) -> None: ... + @override + def __eq__(self, other: object) -> bool: ... + @override + def __hash__(self) -> int: ... + +class QuickPanelItem: + trigger: str + details: str | list[str] | tuple[str] + annotation: str + kind: Kind + def __init__(self, trigger: str, details: str | list[str] | tuple[str] = '', annotation: str = '', kind: Kind = ...) -> None: ... + +class ListInputItem: + text: str + value: object + details: str | list[str] | tuple[str] + annotation: str + kind: Kind + def __init__(self, text: str, value: object, details: str | list[str] | tuple[str] = '', annotation: str = '', kind: Kind = ...) -> None: ... + +class SymbolRegion: + name: str + region: Region + syntax: str + type: SymbolType + kind: Kind + def __init__(self, name: str, region: Region, syntax: str, type: SymbolType, kind: Kind) -> None: ... - def __init__(self, data: Any) -> None: ... - def __str__(self) -> str: ... +class SymbolLocation: + path: str + display_name: str + row: int + col: int + syntax: str + type: SymbolType + kind: Kind + def __init__(self, path: str, display_name: str, row: int, col: int, syntax: str, type: SymbolType, kind: Kind) -> None: ... + def path_encoded_position(self) -> str: ... diff --git a/stubs/sublime_plugin.pyi b/stubs/sublime_plugin.pyi index 5ad9e28..92364c8 100644 --- a/stubs/sublime_plugin.pyi +++ b/stubs/sublime_plugin.pyi @@ -1,71 +1,58 @@ -import sublime - -from typing import Callable, Generic, TypeVar, Optional, Union, List, Tuple, overload - - -InputType = TypeVar('InputType', bound=Union[str, int, float, list, dict, tuple, None]) +""" +API from ST4202 +""" +import sublime +from sublime_types import CommandArgs, CompletionValue, Event, Point, Value -class CommandInputHandler(Generic[InputType]): +class CommandInputHandler: def name(self) -> str: ... - def next_input(self, args: dict) -> Optional[CommandInputHandler]: ... def placeholder(self) -> str: ... def initial_text(self) -> str: ... - def preview(self, arg: InputType) -> Union[str, sublime.Html]: ... - def validate(self, arg: InputType) -> bool: ... + def initial_selection(self) -> list[tuple[int, int]]: ... + def preview(self, text: str) -> str | sublime.Html: ... + def validate(self, text: str, event: Event | None = None) -> bool: ... def cancel(self) -> None: ... + def confirm(self, text: str, event: Event | None = None) -> None: ... + def next_input(self, args: CommandArgs) -> CommandInputHandler | None: ... + def want_event(self) -> bool: ... - @overload - def confirm(self, arg: InputType) -> None: ... - @overload - def confirm(self, arg: InputType, event: dict) -> None: ... - - -class BackInputHandler(CommandInputHandler[None]): - pass - +class BackInputHandler(CommandInputHandler): ... -class TextInputHandler(CommandInputHandler[str]): +class TextInputHandler(CommandInputHandler): def description(self, text: str) -> str: ... - -ListItem = Union[str, Tuple[str, InputType]] - - -class ListInputHandler(CommandInputHandler[InputType], Generic[InputType]): - def list_items(self) -> Union[List[ListItem], Tuple[List[ListItem], int]]: ... - def description(self, v: object, text: str) -> str: ... - +class ListInputHandler(CommandInputHandler): + def list_items(self) -> list[str] | tuple[list[str], int] | list[tuple[str, Value]] | tuple[list[tuple[str, Value]], int] | list[sublime.ListInputItem] | tuple[list[sublime.ListInputItem], int]: ... + def description(self, value: object, text: str) -> str: ... class Command: + @classmethod + def name(cls) -> str: ... def is_enabled(self) -> bool: ... def is_visible(self) -> bool: ... def is_checked(self) -> bool: ... def description(self) -> str: ... - def input(self, args: dict) -> Optional[CommandInputHandler]: ... + def filter_args(self, args: CommandArgs) -> CommandArgs: ... + def want_event(self) -> bool: ... + def input(self, args: CommandArgs) -> CommandInputHandler | None: ... def input_description(self) -> str: ... - class ApplicationCommand(Command): - run: Callable[..., None] - + def run(self, **kwargs: Value) -> None: ... class WindowCommand(Command): window: sublime.Window - - run: Callable[..., None] - + def __init__(self, window: sublime.Window) -> None: ... + def run(self, **kwargs: Value) -> None: ... class TextCommand(Command): view: sublime.View - - run: Callable[..., None] - def want_event(self) -> bool: ... - - -Completion = Union[str, Tuple[str, str], List[str]] + def __init__(self, view: sublime.View) -> None: ... + def run(self, edit: sublime.Edit, **kwargs: Value) -> None: ... class EventListener: + def on_init(self, view: sublime.View) -> None: ... def on_new(self, view: sublime.View) -> None: ... def on_new_async(self, view: sublime.View) -> None: ... def on_clone(self, view: sublime.View) -> None: ... @@ -86,24 +73,38 @@ class EventListener: def on_activated_async(self, view: sublime.View) -> None: ... def on_deactivated(self, view: sublime.View) -> None: ... def on_deactivated_async(self, view: sublime.View) -> None: ... - def on_hover(self, view: sublime.View, point: int, hover_zone: int) -> None: ... - def on_query_context(self, view: sublime.View, key: str, operator: int, operand: str, match_all: bool) -> Optional[bool]: ... - def on_query_completions(self, view: sublime.View, prefix: str, locations: List[int]) -> Union[None, List[Completion], Tuple[List[Completion], int]]: ... - def on_text_command(self, view: sublime.View, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_text_command(self, view: sublime.View, command_name: str, args: dict) -> None: ... - def on_window_command(self, view: sublime.Window, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_window_command(self, view: sublime.Window, command_name: str, args: dict) -> None: ... - + def on_hover(self, view: sublime.View, point: Point, hover_zone: sublime.HoverZone) -> None: ... + def on_query_context(self, view: sublime.View, key: str, operator: int, operand: str, match_all: bool) -> bool | None: ... + def on_query_completions(self, view: sublime.View, prefix: str, locations: list[Point]) -> (None | list[CompletionValue] | tuple[list[CompletionValue], sublime.AutoCompleteFlags] | sublime.CompletionList): ... + def on_text_command(self, view: sublime.View, command_name: str, args: CommandArgs) -> tuple[str, Value] | None: ... + def on_post_text_command(self, view: sublime.View, command_name: str, args: CommandArgs) -> None: ... + def on_window_command(self, view: sublime.Window, command_name: str, args: CommandArgs) -> tuple[str, Value] | None: ... + def on_post_window_command(self, view: sublime.Window, command_name: str, args: CommandArgs) -> None: ... + def on_new_buffer(self, buffer: sublime.Buffer) -> None: ... + def on_new_buffer_async(self, buffer: sublime.Buffer) -> None: ... + def on_associate_buffer(self, buffer: sublime.Buffer) -> None: ... + def on_associate_buffer_async(self, buffer: sublime.Buffer) -> None: ... + def on_close_buffer(self, buffer: sublime.Buffer) -> None: ... + def on_close_buffer_async(self, buffer: sublime.Buffer) -> None: ... + def on_new_project(self, window: sublime.Window) -> None: ... + def on_new_project_async(self, window: sublime.Window) -> None: ... + def on_load_project(self, window: sublime.Window) -> None: ... + def on_load_project_async(self, window: sublime.Window) -> None: ... + def on_pre_save_project(self, window: sublime.Window) -> None: ... + def on_post_save_project(self, window: sublime.Window) -> None: ... + def on_post_save_project_async(self, window: sublime.Window) -> None: ... + def on_pre_close_project(self, window: sublime.Window) -> None: ... + def on_new_window(self, window: sublime.Window) -> None: ... + def on_new_window_async(self, window: sublime.Window) -> None: ... + def on_pre_close_window(self, window: sublime.Window) -> None: ... + def on_exit(self) -> None: ... class ViewEventListener: view: sublime.View - @classmethod def is_applicable(cls, settings: sublime.Settings) -> bool: ... - @classmethod def applies_to_primary_view_only(cls) -> bool: ... - def on_load(self) -> None: ... def on_load_async(self) -> None: ... def on_pre_close(self) -> None: ... @@ -120,8 +121,23 @@ class ViewEventListener: def on_activated_modified_async(self) -> None: ... def on_deactivated_modified(self) -> None: ... def on_deactivated_modified_async(self) -> None: ... - def on_hover(self, point: int, hover_zone: int) -> None: ... - def on_query_context(self, key: str, operator: int, operand: str, match_all: bool) -> Optional[bool]: ... - def on_query_completions(self, prefix: str, locations: List[int]) -> Union[None, List[Completion], Tuple[List[Completion], int]]: ... - def on_text_command(self, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_text_command(self, command_name: str, args: dict) -> None: ... + def on_hover(self, point: Point, hover_zone: sublime.HoverZone) -> None: ... + def on_query_context(self, key: str, operator: int, operand: str, match_all: bool) -> bool | None: ... + def on_query_completions(self, prefix: str, locations: list[Point]) -> (None | list[CompletionValue] | tuple[list[CompletionValue], sublime.AutoCompleteFlags] | sublime.CompletionList): ... + def on_text_command(self, command_name: str, args: CommandArgs) -> tuple[str, Value] | None: ... + def on_post_text_command(self, command_name: str, args: CommandArgs) -> None: ... + +class TextChangeListener: + buffer: sublime.Buffer | None + @classmethod + def is_applicable(cls, buffer: sublime.Buffer) -> None: ... + def __init__(self) -> None: ... + def detach(self) -> None: ... + def attach(self, buffer: sublime.Buffer) -> None: ... + def is_attached(self) -> bool: ... + def on_text_changed(self, changes: list[sublime.TextChange]) -> None: ... + def on_text_changed_async(self, changes: list[sublime.TextChange]) -> None: ... + def on_revert(self) -> None: ... + def on_revert_async(self) -> None: ... + def on_reload(self) -> None: ... + def on_reload_async(self) -> None: ... diff --git a/stubs/sublime_types.pyi b/stubs/sublime_types.pyi new file mode 100644 index 0000000..27845a7 --- /dev/null +++ b/stubs/sublime_types.pyi @@ -0,0 +1,11 @@ +from typing_extensions import TypeAlias +from sublime import KindId, CompletionItem + +DIP: TypeAlias = float +Vector: TypeAlias = tuple[DIP, DIP] +Point: TypeAlias = int +Value: TypeAlias = bool | str | int | float | list[Value] | dict[str, Value] | None +CommandArgs: TypeAlias = dict[str, Value] | None +Kind: TypeAlias = tuple[KindId, str, str] +Event: TypeAlias = dict[str, Value] +CompletionValue: TypeAlias = str | tuple[str, str] | CompletionItem diff --git a/sublime_lib/_util/collections.py b/sublime_lib/_util/collections.py index 802f2e3..6b68c77 100644 --- a/sublime_lib/_util/collections.py +++ b/sublime_lib/_util/collections.py @@ -1,21 +1,17 @@ from __future__ import annotations from collections.abc import Mapping, Sequence -from typing import Callable, Dict, Iterable, TypeVar, Union +from typing import Callable, Iterable, TypeVar _V = TypeVar('_V') -_Result = TypeVar('_Result') -_Default = TypeVar('_Default') -_Value = Union[bool, int, float, str, list, dict, None] - __all__ = ['projection', 'get_selector', 'isiterable', 'ismapping', 'is_sequence_not_str'] def projection( - d: Dict[str, _V], - keys: Union[Dict[str, str], Iterable[str]] -) -> Dict[str, _V]: + d: dict[str, _V], + keys: dict[str, str] | Iterable[str] +) -> dict[str, _V]: """ Return a new :class:`dict` with keys of ``d`` restricted to values in ``keys``. diff --git a/sublime_lib/_util/enum.py b/sublime_lib/_util/enum.py index 41b368b..629dbb5 100644 --- a/sublime_lib/_util/enum.py +++ b/sublime_lib/_util/enum.py @@ -1,7 +1,7 @@ from __future__ import annotations from enum import EnumMeta, Enum, Flag from functools import partial -from typing import Any, Callable, Optional +from typing import Any, Callable __all__ = ['ExtensibleConstructorMeta', 'construct_with_alternatives', 'construct_union'] @@ -15,7 +15,7 @@ def __call__(cls, *args: Any, **kwargs: Any) -> Any: def extend_constructor( constructor: Callable[..., Enum] ) -> Callable[[EnumMeta], EnumMeta]: - def decorator(cls: EnumMeta) -> EnumMeta: + def decorator(cls: Any) -> EnumMeta: next_constructor = partial(cls.__new__, cls) def __new__(cls: EnumMeta, *args: Any, **kwargs: Any) -> Enum: @@ -28,7 +28,7 @@ def __new__(cls: EnumMeta, *args: Any, **kwargs: Any) -> Enum: def construct_with_alternatives( - provider: Callable[..., Optional[Enum]] + provider: Callable[..., Enum | None] ) -> Callable[[EnumMeta], EnumMeta]: def constructor(next_constructor: Callable[..., Enum], cls: EnumMeta, *args: Any, **kwargs: Any) -> Enum: diff --git a/sublime_lib/_util/glob.py b/sublime_lib/_util/glob.py index b203dd0..ab49eac 100644 --- a/sublime_lib/_util/glob.py +++ b/sublime_lib/_util/glob.py @@ -1,8 +1,9 @@ from __future__ import annotations -import re from functools import lru_cache from typing import Callable +import re + __all__ = ['get_glob_matcher'] diff --git a/sublime_lib/_util/guard.py b/sublime_lib/_util/guard.py index 4c28e5f..33608f8 100644 --- a/sublime_lib/_util/guard.py +++ b/sublime_lib/_util/guard.py @@ -1,19 +1,18 @@ from __future__ import annotations from functools import wraps -from typing import Any, Callable, ContextManager, Optional, TypeVar +from typing import Any, Callable, ContextManager, TypeVar _Self = TypeVar('_Self') -_R = TypeVar('_R') -_WrappedType = Callable[..., _R] +_WrappedType = Callable[..., Any] def define_guard( - guard_fn: Callable[[_Self], Optional[ContextManager]] + guard_fn: Callable[[_Self], ContextManager | None] ) -> Callable[[_WrappedType], _WrappedType]: def decorator(wrapped: _WrappedType) -> _WrappedType: @wraps(wrapped) - def wrapper_guards(self: _Self, *args: Any, **kwargs: Any) -> _R: + def wrapper_guards(self: _Self, *args: Any, **kwargs: Any) -> Any: ret_val = guard_fn(self) if ret_val is not None: with ret_val: diff --git a/sublime_lib/_util/weak_method.py b/sublime_lib/_util/weak_method.py index cad4070..ed32b97 100644 --- a/sublime_lib/_util/weak_method.py +++ b/sublime_lib/_util/weak_method.py @@ -1,10 +1,9 @@ from __future__ import annotations - -import weakref - from types import MethodType from typing import Callable, Any +import weakref + __all__ = ['weak_method'] diff --git a/sublime_lib/activity_indicator.py b/sublime_lib/activity_indicator.py index dd9c91e..896832a 100644 --- a/sublime_lib/activity_indicator.py +++ b/sublime_lib/activity_indicator.py @@ -1,15 +1,13 @@ from __future__ import annotations -import sublime - -from uuid import uuid4 - -from typing import Optional, Union -from types import TracebackType from abc import ABCMeta, abstractmethod from functools import partial -from ._util.weak_method import weak_method - from threading import Lock +from types import TracebackType +from uuid import uuid4 + +import sublime + +from ._util.weak_method import weak_method __all__ = ['ActivityIndicator'] @@ -37,7 +35,7 @@ def clear(self) -> None: class ViewTarget(StatusTarget): - def __init__(self, view: sublime.View, key: Optional[str] = None) -> None: + def __init__(self, view: sublime.View, key: str | None = None) -> None: self.view = view if key is None: self.key = '_{!s}'.format(uuid4()) @@ -63,19 +61,19 @@ class ActivityIndicator: .. versionadded:: 1.4 """ - width = 10 # type: int - interval = 100 # type: int + width: int = 10 + interval: int = 100 - _target = None # type: StatusTarget - _ticks = 0 # type: int - _lock = None # type: Lock - _running = False # type: bool - _invocation_id = 0 # type: int + _lock: Lock + _target: StatusTarget + _ticks: int = 0 + _running: bool = False + _invocation_id: int = 0 def __init__( self, - target: Union[StatusTarget, sublime.View, sublime.Window], - label: Optional[str] = None, + target: StatusTarget | sublime.View | sublime.Window, + label: str | None = None, ) -> None: self.label = label diff --git a/sublime_lib/flags.py b/sublime_lib/flags.py index 92b905b..4d5d68b 100644 --- a/sublime_lib/flags.py +++ b/sublime_lib/flags.py @@ -27,15 +27,13 @@ and `IntFlag` constructors accept multiple arguments. """ from __future__ import annotations - -import sublime - from enum import IntEnum, IntFlag, EnumMeta from inspect import getdoc, cleandoc -from typing import Callable, Optional +from typing import Callable import operator import re +import sublime from ._util.enum import ExtensibleConstructorMeta, construct_union, construct_with_alternatives @@ -47,7 +45,7 @@ ] -def autodoc(prefix: Optional[str] = None) -> Callable[[EnumMeta], EnumMeta]: +def autodoc(prefix: str | None = None) -> Callable[[EnumMeta], EnumMeta]: if prefix is None: prefix_str = '' else: @@ -273,12 +271,10 @@ def on_query_context(self, view, key, operator, operand, match_all): REGEX_CONTAINS = (sublime.OP_REGEX_CONTAINS, regex_contains) NOT_REGEX_CONTAINS = (sublime.OP_NOT_REGEX_CONTAINS, not_regex_contains) - # _apply_ = None # type: Callable[[str, str], bool] - - def __new__(cls, value: int, operator: Callable[[str, str], bool]) -> 'QueryContextOperator': - obj = int.__new__(cls, value) # type: ignore - obj._value_ = value - obj._apply_ = operator + def __new__(cls, value: int, operator: Callable[[str, str], bool]) -> QueryContextOperator: + obj = int.__new__(cls, value) + setattr(obj, '_value_', value) + setattr(obj, '_apply_', operator) return obj def apply(self, value: str, operand: str) -> bool: diff --git a/sublime_lib/panel.py b/sublime_lib/panel.py index e1fcf68..9d42675 100644 --- a/sublime_lib/panel.py +++ b/sublime_lib/panel.py @@ -1,9 +1,8 @@ from __future__ import annotations +from typing import Any import sublime -from typing import Any - from .view_stream import ViewStream from .view_utils import set_view_options, validate_view_options from ._util.guard import define_guard @@ -28,8 +27,8 @@ class Panel(): """ def __init__(self, window: sublime.Window, panel_name: str): - self.window = window - self.panel_name = panel_name + self.window: sublime.Window = window + self.panel_name: str = panel_name self._checkExists() @@ -93,7 +92,7 @@ def create( follow_cursor: bool = False, unlisted: bool = False, **kwargs: Any - ) -> 'OutputPanel': + ) -> OutputPanel: """Create a new output panel with the given `name` in the given `window`. If `kwargs` are given, @@ -122,7 +121,7 @@ def __init__( ViewStream.__init__(self, view, force_writes=force_writes, follow_cursor=follow_cursor) Panel.__init__(self, window, "output." + name) - self.name = name + self.name: str = name @property def full_name(self) -> str: diff --git a/sublime_lib/region_manager.py b/sublime_lib/region_manager.py index dce7c4d..bab54de 100644 --- a/sublime_lib/region_manager.py +++ b/sublime_lib/region_manager.py @@ -1,19 +1,18 @@ from __future__ import annotations +from typing import TYPE_CHECKING -import sublime +if TYPE_CHECKING: + from typing import TypeVar + T = TypeVar('T') -from typing import Optional, List, TypeVar, Collection +import sublime from .flags import RegionOption - __all__ = ['RegionManager'] -T = TypeVar('T') - - -def _coalesce(*values: Optional[T]) -> T: +def _coalesce(*values: T | None) -> T: return next(value for value in values if value is not None) @@ -34,33 +33,33 @@ class RegionManager: def __init__( self, view: sublime.View, - key: Optional[str] = None, + key: str | None = None, *, - scope: Optional[str] = None, - icon: Optional[str] = None, - flags: Optional[RegionOption] = None + scope: str | None = None, + icon: str | None = None, + flags: type[RegionOption] | None = None ): - self.view = view + self.view: sublime.View = view if key is None: self.key = str(id(self)) else: self.key = key - self.scope = scope - self.icon = icon - self.flags = flags + self.scope: str | None = scope + self.icon: str | None = icon + self.flags: type[RegionOption] | None = flags def __del__(self) -> None: self.erase() def set( self, - regions: Collection[sublime.Region], + regions: list[sublime.Region], *, - scope: Optional[str] = None, - icon: Optional[str] = None, - flags: Optional[RegionOption] = None + scope: str | None = None, + icon: str | None = None, + flags: type[RegionOption] | None = None ) -> None: """Replace managed regions with the given regions. @@ -73,10 +72,10 @@ def set( regions, _coalesce(scope, self.scope, ''), _coalesce(icon, self.icon, ''), - _coalesce(flags, self.flags, 0), + _coalesce(flags, self.flags, RegionOption.NONE), # type: ignore ) - def get(self) -> List[sublime.Region]: + def get(self) -> list[sublime.Region]: """Return the list of managed regions.""" return self.view.get_regions(self.key) diff --git a/sublime_lib/resource_path.py b/sublime_lib/resource_path.py index cd69d51..98c3a72 100644 --- a/sublime_lib/resource_path.py +++ b/sublime_lib/resource_path.py @@ -1,13 +1,12 @@ from __future__ import annotations - -import sublime - -import posixpath -from collections import OrderedDict -import os from abc import ABCMeta, abstractmethod -from typing import List, Optional, Tuple, Iterable, Union +from collections import OrderedDict from pathlib import Path +from typing import Iterable + +import os +import posixpath +import sublime from ._util.glob import get_glob_matcher @@ -18,11 +17,12 @@ class ResourceRoot(metaclass=ABCMeta): """ Represents a directory containing packages. """ - def __init__(self, root: object, path: Union[Path, str]) -> None: - self.resource_root = ResourcePath(root) - self.file_root = Path(path) - def resource_to_file_path(self, resource_path: object) -> Path: + def __init__(self, root: object, path: Path | str) -> None: + self.resource_root: ResourcePath = ResourcePath(root) + self.file_root: Path = Path(path) + + def resource_to_file_path(self, resource_path: ResourcePath) -> Path: """ Given a :class:`ResourcePath`, return the corresponding :class:`Path` within this resource root. @@ -37,7 +37,7 @@ def resource_to_file_path(self, resource_path: object) -> Path: else: return self._package_file_path(*parts) - def file_to_resource_path(self, file_path: Union[Path, str]) -> Optional['ResourcePath']: + def file_to_resource_path(self, file_path: Path | str) -> ResourcePath | None: """ Given an absolute :class:`Path`, return the corresponging :class:`ResourcePath` within this resource root, @@ -61,11 +61,7 @@ def file_to_resource_path(self, file_path: Union[Path, str]) -> Optional['Resour return self._package_resource_path(*relpath.parts) @abstractmethod - def _package_file_path( - self, - package: str, - *parts: str - ) -> Path: # pragma: no cover + def _package_file_path(self, package: str, *rest: str) -> Path: """ Given a package name and zero or more path segments, return the corresponding :class:`Path` within this resource root. @@ -73,11 +69,7 @@ def _package_file_path( ... @abstractmethod - def _package_resource_path( - self, - package: str, - *parts: str - ) -> 'ResourcePath': # pragma: no cover + def _package_resource_path(self, package: str, *rest: str) -> ResourcePath: """ Given a package name and zero or more path segments, return the corresponding :class:`ResourcePath` within this resource root. @@ -89,46 +81,48 @@ class DirectoryResourceRoot(ResourceRoot): """ Represents a directory containing unzipped package directories. """ - def _package_file_path(self, *parts: str) -> Path: - return self.file_root.joinpath(*parts) - def _package_resource_path(self, *parts: str) -> 'ResourcePath': - return self.resource_root.joinpath(*parts) + def _package_file_path(self, package: str, *rest: str) -> Path: + return self.file_root.joinpath(package, *rest) + + def _package_resource_path(self, package: str, *rest: str) -> ResourcePath: + return self.resource_root.joinpath(package, *rest) class InstalledResourceRoot(ResourceRoot): """ Represents a directory containing zipped sublime-package files. """ + def _package_file_path(self, package: str, *rest: str) -> Path: # This is not currently called because there are no installed-only roots. return self.file_root.joinpath(package + '.sublime-package', *rest) - def _package_resource_path(self, package: str, *rest: str) -> 'ResourcePath': + def _package_resource_path(self, package: str, *rest: str) -> ResourcePath: package_path = (self.resource_root / package).remove_suffix('.sublime-package') return package_path.joinpath(*rest) -def wrap_path(p: Union[str, Path]) -> Path: +def wrap_path(p: Path | str) -> Path: if isinstance(p, Path): return p else: return Path(p) -_ROOTS = None # type: Optional[List[ResourceRoot]] +_roots: list[ResourceRoot] | None = None -def get_roots() -> List[ResourceRoot]: - global _ROOTS - if _ROOTS is None: - _ROOTS = [ +def get_roots() -> list[ResourceRoot]: + global _roots + if _roots is None: + _roots = [ DirectoryResourceRoot('Cache', sublime.cache_path()), DirectoryResourceRoot('Packages', sublime.packages_path()), InstalledResourceRoot('Packages', sublime.installed_packages_path()), InstalledResourceRoot('Packages', Path(sublime.executable_path()).parent / 'Packages'), ] - return _ROOTS + return _roots class ResourcePath(): @@ -165,7 +159,7 @@ class ResourcePath(): """ @classmethod - def glob_resources(cls, pattern: str) -> List['ResourcePath']: + def glob_resources(cls, pattern: str) -> list[ResourcePath]: """ Find all resources that match the given pattern and return them as :class:`ResourcePath` objects. @@ -177,7 +171,7 @@ def glob_resources(cls, pattern: str) -> List['ResourcePath']: ] @classmethod - def from_file_path(cls, file_path: Union[Path, str]) -> 'ResourcePath': + def from_file_path(cls, file_path: Path | str) -> ResourcePath: """ Return a :class:`ResourcePath` corresponding to the given file path. @@ -229,7 +223,7 @@ def __init__(self, *pathsegments: object): if self._parts == (): raise ValueError("Empty path.") - def _parse_segments(self, pathsegments: Iterable[object]) -> Tuple[str, ...]: + def _parse_segments(self, pathsegments: Iterable[object]) -> tuple[str, ...]: return tuple( part for segment in pathsegments if segment @@ -248,18 +242,18 @@ def __str__(self) -> str: def __eq__(self, other: object) -> bool: return isinstance(other, ResourcePath) and self._parts == other.parts - def __truediv__(self, other: object) -> 'ResourcePath': + def __truediv__(self, other: object) -> ResourcePath: return self.joinpath(other) @property - def parts(self) -> Tuple[str, ...]: + def parts(self) -> tuple[str, ...]: """ A tuple giving access to the path’s various components. """ return self._parts @property - def parent(self) -> 'ResourcePath': + def parent(self) -> ResourcePath: """ The logical parent of the path. A root path is its own parent. """ @@ -269,7 +263,7 @@ def parent(self) -> 'ResourcePath': return self.__class__(*self._parts[:-1]) @property - def parents(self) -> Tuple['ResourcePath', ...]: + def parents(self) -> tuple[ResourcePath, ...]: """ An immutable sequence providing access to the path's logical ancestors. """ @@ -299,7 +293,7 @@ def suffix(self) -> str: return '' @property - def suffixes(self) -> List[str]: + def suffixes(self) -> list[str]: """ A list of the final component's suffixes, if any. """ @@ -329,7 +323,7 @@ def root(self) -> str: return self._parts[0] @property - def package(self) -> Optional[str]: + def package(self) -> str | None: """ The name of the package the path is within, or ``None`` if the path is a root path. @@ -349,13 +343,13 @@ def match(self, pattern: str) -> bool: match = get_glob_matcher(pattern) return match(str(self)) - def joinpath(self, *other: object) -> 'ResourcePath': + def joinpath(self, *other: object) -> ResourcePath: """ Combine this path with all of the given strings. """ return self.__class__(self, *other) - def relative_to(self, *other: object) -> Tuple[str, ...]: + def relative_to(self, *other: object) -> tuple[str, ...]: """ Compute a tuple `parts` of path components such that ``self == other.joinpath(*parts)``. @@ -373,7 +367,7 @@ def relative_to(self, *other: object) -> Tuple[str, ...]: else: raise ValueError("{!s} does not start with {!s}".format(self, other_path)) - def with_name(self, name: str) -> 'ResourcePath': + def with_name(self, name: str) -> ResourcePath: """ Return a new path with the name changed. """ @@ -382,7 +376,7 @@ def with_name(self, name: str) -> 'ResourcePath': else: return self.parent / name - def add_suffix(self, suffix: str) -> 'ResourcePath': + def add_suffix(self, suffix: str) -> ResourcePath: """ Return a new path with the suffix added. @@ -391,8 +385,8 @@ def add_suffix(self, suffix: str) -> 'ResourcePath': return self.with_name(self.name + suffix) def remove_suffix( - self, suffix: Optional[str] = None, *, must_remove: bool = True - ) -> 'ResourcePath': + self, suffix: Iterable[str] | str | None = None, *, must_remove: bool = True + ) -> ResourcePath: """ Return a new path with the suffix removed. @@ -432,7 +426,7 @@ def remove_suffix( else: return self - def with_suffix(self, suffix: str) -> 'ResourcePath': + def with_suffix(self, suffix: str) -> ResourcePath: """ Return a new path with the suffix changed. @@ -498,7 +492,7 @@ def read_bytes(self) -> bytes: except IOError as err: raise FileNotFoundError(str(self)) from err - def glob(self, pattern: str) -> List['ResourcePath']: + def glob(self, pattern: str) -> list[ResourcePath]: """ Glob the given pattern at this path, returning all matching resources. @@ -507,7 +501,7 @@ def glob(self, pattern: str) -> List['ResourcePath']: base = '/' + str(self) + '/' if self._parts else '' return ResourcePath.glob_resources(base + pattern) - def rglob(self, pattern: str) -> List['ResourcePath']: + def rglob(self, pattern: str) -> list[ResourcePath]: """ Shorthand for ``path.glob('**/' + pattern)``. @@ -520,7 +514,7 @@ def rglob(self, pattern: str) -> List['ResourcePath']: return self.glob('**/' + pattern) - def children(self) -> List['ResourcePath']: + def children(self) -> list[ResourcePath]: """ Return a list of paths that are direct children of this path and point to a resource at or beneath that path. @@ -559,7 +553,7 @@ def copy(self, target: object, exist_ok: bool = True) -> None: with open(str(target), mode + 'b') as file: file.write(data) - def copytree(self, target: Union[Path, str], exist_ok: bool = False) -> None: + def copytree(self, target: Path | str, exist_ok: bool = False) -> None: """ Copy all resources beneath this path into a directory tree rooted at `target`. diff --git a/sublime_lib/settings_dict.py b/sublime_lib/settings_dict.py index 6764dec..54b8600 100644 --- a/sublime_lib/settings_dict.py +++ b/sublime_lib/settings_dict.py @@ -1,20 +1,21 @@ from __future__ import annotations +from collections.abc import Mapping +from functools import partial +from typing import TYPE_CHECKING +from uuid import uuid4 import sublime -from uuid import uuid4 -from functools import partial -from collections.abc import Mapping -from typing import Any, Callable, Iterable, NoReturn, TypeVar, Union, Mapping as _Mapping - from ._util.collections import get_selector from ._util.named_value import NamedValue -_Default = TypeVar('_Default') -Value = Union[bool, int, float, str, list, dict, None] - __all__ = ['SettingsDict', 'NamedSettingsDict'] +if TYPE_CHECKING: + from typing import Any, Callable, Iterable + from typing_extensions import TypeAlias + + Value: TypeAlias = bool | str | int | float | list[Any] | dict[str, Any] | None _NO_DEFAULT = NamedValue('SettingsDict.NO_DEFAULT') @@ -44,9 +45,9 @@ class SettingsDict(): NO_DEFAULT = _NO_DEFAULT def __init__(self, settings: sublime.Settings): - self.settings = settings + self.settings: sublime.Settings = settings - def __iter__(self) -> NoReturn: + def __iter__(self) -> None: """Raise NotImplementedError.""" raise NotImplementedError() @@ -101,16 +102,14 @@ def __contains__(self, item: str) -> bool: """Return ``True`` if `self` has a setting named `key`, else ``False``.""" return self.settings.has(item) - def get(self, key: str, default: _Default = None) -> Union[Value, _Default]: + def get(self, key: str, default: Value | None = None) -> Value: """Return the value for `key` if `key` is in the dictionary, or `default` otherwise. If `default` is not given, it defaults to ``None``, so that this method never raises :exc:`KeyError`.""" return self.settings.get(key, default) - def pop( - self, key: str, default: Union[_Default, NamedValue] = _NO_DEFAULT - ) -> Union[Value, _Default]: + def pop(self, key: str, default: Value | NamedValue = _NO_DEFAULT) -> Value: """Remove the setting `self[key]` and return its value or `default`. :raise KeyError: if `key` is not in the dictionary @@ -139,7 +138,7 @@ def setdefault(self, key: str, default: Value = None) -> Value: def update( self, - other: Union[_Mapping[str, Value], Iterable[Iterable[str]]] = [], + other: dict[str, Value] | Iterable[Iterable[str]] = [], **kwargs: Value ) -> None: """Update the dictionary with the key/value pairs from `other`, @@ -157,11 +156,14 @@ def update( for key, value in other: self[key] = value - for key, value in kwargs.items(): + for key, value in kwargs.items(): # type: ignore self[key] = value def subscribe( - self, selector: Any, callback: Callable, default_value: Any = None + self, + selector: Value, + callback: Callable[[Value, Value], None], + default_value: Value = None ) -> Callable[[], None]: """Register a callback to be invoked when the value derived from the settings object changes diff --git a/sublime_lib/show_selection_panel.py b/sublime_lib/show_selection_panel.py index 786cb99..2386807 100644 --- a/sublime_lib/show_selection_panel.py +++ b/sublime_lib/show_selection_panel.py @@ -1,12 +1,12 @@ from __future__ import annotations +from collections.abc import Sequence +from typing import Callable, TypeVar import sublime from ._util.collections import isiterable from ._util.named_value import NamedValue from .flags import QuickPanelOption -from collections.abc import Sequence -from typing import Any, Callable, List, Optional, TypeVar, Union, Sequence as _Sequence _ItemType = TypeVar('_ItemType') @@ -18,14 +18,14 @@ def show_selection_panel( window: sublime.Window, - items: _Sequence[_ItemType], + items: Sequence[_ItemType], *, - flags: Any = 0, - labels: Union[_Sequence[object], Callable[[_ItemType], object]] = None, - selected: Union[NamedValue, _ItemType] = NO_SELECTION, - on_select: Optional[Callable[[_ItemType], object]] = None, - on_cancel: Optional[Callable[[], object]] = None, - on_highlight: Optional[Callable[[_ItemType], object]] = None + flags: QuickPanelOption = QuickPanelOption.NONE, + labels: Sequence[object] | Callable[[_ItemType], object] | None = None, + selected: NamedValue | _ItemType = NO_SELECTION, + on_select: Callable[[_ItemType], object] | None = None, + on_cancel: Callable[[], object] | None = None, + on_highlight: Callable[[_ItemType], object] | None = None ) -> None: """Open a quick panel in the given window to select an item from a list. @@ -92,7 +92,7 @@ def show_selection_panel( elif len(items) != len(labels): raise ValueError("The lengths of `items` and `labels` must match.") - def normalize_label(label: object) -> List[str]: + def normalize_label(label: object) -> list[str]: if isinstance(label, Sequence) and not isinstance(label, str): return list(map(str, label)) else: @@ -114,9 +114,7 @@ def on_done(index: int) -> None: else: selected_index = items.index(selected) - on_highlight_callback = None - if on_highlight: - on_highlight_callback = lambda index: on_highlight(items[index]) + on_highlight_callback = lambda index: on_highlight(items[index]) if on_highlight else None if isiterable(flags) and not isinstance(flags, str): flags = QuickPanelOption(*flags) @@ -128,7 +126,7 @@ def on_done(index: int) -> None: window.show_quick_panel( items=label_strings, on_select=on_done, - flags=flags, + flags=flags, # type: ignore selected_index=selected_index, - on_highlight=on_highlight_callback + on_highlight=on_highlight_callback # type: ignore ) diff --git a/sublime_lib/view_stream.py b/sublime_lib/view_stream.py index 3d9354c..09baea0 100644 --- a/sublime_lib/view_stream.py +++ b/sublime_lib/view_stream.py @@ -1,13 +1,12 @@ from __future__ import annotations +from contextlib import contextmanager +from io import SEEK_SET, SEEK_CUR, SEEK_END, TextIOBase +from typing import Any, Generator import sublime from sublime import Region -from contextlib import contextmanager -from io import SEEK_SET, SEEK_CUR, SEEK_END, TextIOBase - from ._util.guard import define_guard -from typing import Any, Generator class ViewStream(TextIOBase): @@ -76,9 +75,9 @@ def guard_selection(self) -> None: def __init__( self, view: sublime.View, *, force_writes: bool = False, follow_cursor: bool = False ): - self.view = view - self.force_writes = force_writes - self.follow_cursor = follow_cursor + self.view: sublime.View = view + self.force_writes: bool = force_writes + self.follow_cursor: bool = follow_cursor @guard_validity @guard_selection diff --git a/sublime_lib/view_utils.py b/sublime_lib/view_utils.py index 374f09d..a821efc 100644 --- a/sublime_lib/view_utils.py +++ b/sublime_lib/view_utils.py @@ -1,26 +1,27 @@ from __future__ import annotations - -import sublime - -import inspect from contextlib import contextmanager from enum import Enum -from typing import Any, Optional, Mapping, Iterable, Generator, Type, TypeVar +from typing import TYPE_CHECKING -from ._util.enum import ExtensibleConstructorMeta, construct_with_alternatives -from .syntax import get_syntax_for_scope -from .encodings import to_sublime +if TYPE_CHECKING: + from typing import Any, Generator, Iterable, TypeVar + from sublime_types import Value + EnumType = TypeVar('EnumType', bound=Enum) -EnumType = TypeVar('EnumType', bound=Enum) +import inspect +import sublime +from ._util.enum import ExtensibleConstructorMeta, construct_with_alternatives +from .encodings import to_sublime +from .syntax import get_syntax_for_scope __all__ = [ 'LineEnding', 'new_view', 'close_view', ] -def case_insensitive_value(cls: Type[EnumType], value: str) -> Optional[EnumType]: +def case_insensitive_value(cls: type[EnumType], value: str) -> EnumType | None: return next(( member for name, member in cls.__members__.items() if name.lower() == value.lower() @@ -155,7 +156,7 @@ def close_view(view: sublime.View, *, force: bool = False) -> None: raise ValueError('The view could not be closed.') -def validate_view_options(options: Mapping[str, Any]) -> None: +def validate_view_options(options: dict[str, Value]) -> None: unknown = set(options) - VIEW_OPTIONS if unknown: raise ValueError('Unknown view options: %s.' % ', '.join(list(unknown))) @@ -170,16 +171,16 @@ def validate_view_options(options: Mapping[str, Any]) -> None: def set_view_options( view: sublime.View, *, - name: Optional[str] = None, - settings: Optional[dict] = None, - read_only: Optional[bool] = None, - scratch: Optional[bool] = None, - overwrite: Optional[bool] = None, - syntax: Optional[str] = None, - scope: Optional[str] = None, - encoding: Optional[str] = None, - content: Optional[str] = None, - line_endings: Optional[str] = None + name: str | None = None, + settings: dict[str, Value] | None = None, + read_only: bool | None = None, + scratch: bool | None = None, + overwrite: bool | None = None, + syntax: str | None = None, + scope: str | None = None, + encoding: str | None = None, + content: str | None = None, + line_endings: str | None = None ) -> None: if name is not None: view.set_name(name) diff --git a/sublime_lib/window_utils.py b/sublime_lib/window_utils.py index 9a870c7..368634f 100644 --- a/sublime_lib/window_utils.py +++ b/sublime_lib/window_utils.py @@ -1,8 +1,10 @@ from __future__ import annotations +from typing import TYPE_CHECKING import sublime -from typing import Optional +if TYPE_CHECKING: + from .settings_dict import Value from .view_utils import _temporarily_scratch_unsaved_views @@ -11,12 +13,12 @@ def new_window( *, - menu_visible: Optional[bool] = None, - sidebar_visible: Optional[bool] = None, - tabs_visible: Optional[bool] = None, - minimap_visible: Optional[bool] = None, - status_bar_visible: Optional[bool] = None, - project_data: Optional[dict] = None + menu_visible: bool | None = None, + sidebar_visible: bool | None = None, + tabs_visible: bool | None = None, + minimap_visible: bool | None = None, + status_bar_visible: bool | None = None, + project_data: dict[str, Value] | None = None ) -> sublime.Window: """Open a new window, returning the :class:`~sublime.Window` object.