Skip to content

Commit

Permalink
refactor: tidy codes
Browse files Browse the repository at this point in the history
Signed-off-by: Jack Cherng <[email protected]>
  • Loading branch information
jfcherng committed Apr 21, 2024
1 parent a13b324 commit 7ee9616
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 77 deletions.
7 changes: 4 additions & 3 deletions plugin/commands/auto_set_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def run_auto_set_syntax_on_view(
if event is ListenerEvent.EXEC:
return _assign_syntax_for_exec_output(view_snapshot, event)

# prerequsites
# prerequisites
if not (
(window := view.window())
and is_syntaxable_view(view, must_plaintext=must_plaintext)
Expand Down Expand Up @@ -84,10 +84,11 @@ def run_auto_set_syntax_on_view(
ListenerEvent.COMMAND,
ListenerEvent.INIT,
ListenerEvent.LOAD,
ListenerEvent.MODIFY,
ListenerEvent.PASTE,
ListenerEvent.SAVE,
ListenerEvent.UNTRANSIENTIZE,
# modify
ListenerEvent.MODIFY,
ListenerEvent.PASTE,
} and _assign_syntax_with_magika(view_snapshot, event):
return True

Expand Down
2 changes: 1 addition & 1 deletion plugin/libs/triegex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def __getitem__(self, key):
def __delitem__(self, key):
del self.children[key]

def to_regex(self):
def to_regex(self) -> str:
"""
RECURSIVE IMPLEMENTATION FOR REFERENCE
suffixes = [v.to_regex() for k, v in self.children.items()]
Expand Down
3 changes: 2 additions & 1 deletion plugin/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import math
import re
from collections.abc import Generator
from contextlib import contextmanager
from typing import Any, Final, Generator
from typing import Any, Final

import sublime
import sublime_plugin
Expand Down
7 changes: 4 additions & 3 deletions plugin/rules/constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import operator
from abc import ABC, abstractmethod
from collections.abc import Callable, Generator, Iterable
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Callable, Generator, Iterable, Pattern, TypeVar, final
from typing import Any, Pattern, TypeVar, final

from ..cache import clearable_lru_cache
from ..constants import PLUGIN_NAME, ST_PLATFORM
Expand Down Expand Up @@ -167,9 +168,9 @@ def find_parent_with_sibling(base: str | Path, sibling: str, *, use_exists: bool
if use_exists:
checker = Path.exists
elif sibling.endswith(("\\", "/")):
checker = Path.is_dir # type: ignore
checker = Path.is_dir
else:
checker = Path.is_file # type: ignore
checker = Path.is_file

return first_true(path.parents, pred=lambda p: checker(p / sibling))

Expand Down
3 changes: 2 additions & 1 deletion plugin/rules/match.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import Generator
from dataclasses import dataclass, field
from typing import Any, Generator, Union, final
from typing import Any, Union, final

from ..cache import clearable_lru_cache
from ..snapshot import ViewSnapshot
Expand Down
21 changes: 5 additions & 16 deletions plugin/shared.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Iterable, List
from typing import List

import sublime

from .rules import SyntaxRuleCollection
from .settings import get_merged_plugin_settings
from .types import Optimizable, WindowKeyedDict

if TYPE_CHECKING:
from .rules import SyntaxRuleCollection
_DroppedRules = List[Optimizable]

DroppedRules = List[Optimizable]
DroppedRulesArg = Iterable[Optimizable]

# `UserDict` is not subscriptable until Python 3.9...
if TYPE_CHECKING:
_WindowKeyedDict_DroppedRules = WindowKeyedDict[DroppedRules]
_WindowKeyedDict_SyntaxRuleCollection = WindowKeyedDict[SyntaxRuleCollection]
else:
_WindowKeyedDict_DroppedRules = WindowKeyedDict
_WindowKeyedDict_SyntaxRuleCollection = WindowKeyedDict


class DroppedRulesCollection(_WindowKeyedDict_DroppedRules):
class DroppedRulesCollection(WindowKeyedDict[_DroppedRules]):
pass


class SyntaxRuleCollections(_WindowKeyedDict_SyntaxRuleCollection):
class SyntaxRuleCollections(WindowKeyedDict[SyntaxRuleCollection]):
pass


Expand Down
100 changes: 62 additions & 38 deletions plugin/types.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,63 @@
from __future__ import annotations

import sys
from abc import ABC, abstractmethod
from collections import UserDict
from collections import UserDict as BuiltinUserDict
from collections.abc import Generator, Iterator, KeysView
from enum import Enum
from typing import TYPE_CHECKING, Any, Generator, KeysView, TypedDict, TypeVar, Union
from typing import Any, Generic, TypedDict, TypeVar, Union, overload

import sublime

SyntaxLike = Union[str, sublime.Syntax]
WindowId = int
WindowIdAble = Union[WindowId, sublime.Window]

_K = TypeVar("_K")
_T = TypeVar("_T")
_V = TypeVar("_V")

if sys.version_info < (3, 9):

class ListenerEvent(Enum):
class UserDict(BuiltinUserDict, Generic[_K, _V]):
"""Workaround class for the fact that `UserDict` is not subscriptable until Python 3.9..."""

def __init__(self, dict=None, /, **kwargs) -> None:
self.data: dict[_K, _V] = {}
super().__init__(dict, **kwargs)

def __getitem__(self, key: _K) -> _V:
return super().__getitem__(key)

def __setitem__(self, key: _K, item: _V) -> None:
super().__setitem__(key, item)

def __delitem__(self, key: _K) -> None:
super().__delitem__(key)

def __iter__(self) -> Iterator[_K]:
return super().__iter__()

@overload
def get(self, key: _K) -> _V | None: ...
@overload
def get(self, key: _K, default: _T) -> _V | _T: ...

def get(self, key: _K, default: _T | None = None) -> _V | _T | None:
return super().get(key, default)
else:
UserDict = BuiltinUserDict # noqa: F401

if sys.version_info < (3, 11):

class StrEnum(str, Enum):
__format__ = str.__format__ # type: ignore
__str__ = str.__str__ # type: ignore
else:
from enum import StrEnum # noqa: F401


class ListenerEvent(StrEnum):
"""Events used in AutoSetSyntax."""

COMMAND = "command"
Expand All @@ -29,9 +72,6 @@ class ListenerEvent(Enum):
SAVE = "save"
UNTRANSIENTIZE = "untransientize"

def __str__(self) -> str:
return str(self.value)

@classmethod
def from_value(cls, value: Any) -> ListenerEvent | None:
try:
Expand Down Expand Up @@ -68,7 +108,7 @@ class ST_MatchRule(TypedDict):
match: str
args: list[Any] | Any | None
kwargs: dict[str, Any] | None
rules: list[ST_MatchRule | ST_ConstraintRule] # type: ignore
rules: list[ST_MatchRule | ST_ConstraintRule]


class ST_SyntaxRule(ST_MatchRule):
Expand All @@ -80,38 +120,22 @@ class ST_SyntaxRule(ST_MatchRule):
on_events: str | list[str] | None


# `UserDict` is not subscriptable until Python 3.9...
if TYPE_CHECKING:

class WindowKeyedDict(UserDict[WindowIdAble, _T]):
def __setitem__(self, key: WindowIdAble, value: _T) -> None: ...

def __getitem__(self, key: WindowIdAble) -> _T: ...

def __delitem__(self, key: WindowIdAble) -> None: ...
class WindowKeyedDict(UserDict[WindowIdAble, _T]):
def __setitem__(self, key: WindowIdAble, value: _T) -> None:
key = self._to_window_id(key)
super().__setitem__(key, value)

def keys(self) -> KeysView[WindowId]: ...
@staticmethod
def _to_window_id(value: WindowIdAble) -> WindowId: ...
def __getitem__(self, key: WindowIdAble) -> _T:
key = self._to_window_id(key)
return super().__getitem__(key)

else:

class WindowKeyedDict(UserDict):
def __setitem__(self, key: WindowIdAble, value: _T) -> None:
key = self._to_window_id(key)
super().__setitem__(key, value)

def __getitem__(self, key: WindowIdAble) -> _T:
key = self._to_window_id(key)
return super().__getitem__(key)

def __delitem__(self, key: WindowIdAble) -> None:
key = self._to_window_id(key)
super().__delitem__(key)
def __delitem__(self, key: WindowIdAble) -> None:
key = self._to_window_id(key)
super().__delitem__(key)

def keys(self) -> KeysView[WindowId]:
return super().keys()
def keys(self) -> KeysView[WindowId]:
return super().keys()

@staticmethod
def _to_window_id(value: WindowIdAble) -> WindowId:
return value.id() if isinstance(value, sublime.Window) else value
@staticmethod
def _to_window_id(value: WindowIdAble) -> WindowId:
return value.id() if isinstance(value, sublime.Window) else value
26 changes: 12 additions & 14 deletions plugin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import sys
import tempfile
import threading
from collections.abc import Generator, Iterable
from collections.abc import Generator, Iterable, Mapping
from functools import cmp_to_key, lru_cache, reduce, wraps
from itertools import islice
from pathlib import Path
from typing import Any, Callable, Dict, List, Mapping, Pattern, Tuple, TypeVar, Union, cast, overload
from typing import Any, Callable, Pattern, TypeVar, Union, cast, overload

import sublime

Expand All @@ -25,15 +25,15 @@
_U = TypeVar("_U")

_T_Callable = TypeVar("_T_Callable", bound=Callable[..., Any])
_T_ExpandableVar = TypeVar("_T_ExpandableVar", bound=Union[None, bool, int, float, str, Dict, List, Tuple])
_T_ExpandableVar = TypeVar("_T_ExpandableVar", bound=Union[None, bool, int, float, str, dict, list, tuple])


def camel_to_snake(s: str) -> str:
"""Converts "CamelCase" to "snake_case"."""
return "".join(f"_{c}" if c.isupper() else c for c in s).strip("_").lower()


def snake_to_camel(s: str, upper_first: bool = True) -> str:
def snake_to_camel(s: str, *, upper_first: bool = True) -> str:
"""Converts "snake_case" to "CamelCase"."""
first, *others = s.split("_")
return (first.title() if upper_first else first.lower()) + "".join(map(str.title, others))
Expand Down Expand Up @@ -80,20 +80,18 @@ def merge_literals_to_regex(literals: Iterable[str]) -> str:
from .libs.triegex import Triegex

# this regex is enclosed by "(?:)"
return (
Triegex(*map(re.escape, literals)) # type: ignore
.to_regex()
.replace(r"\b", "") # type: ignore
.replace(r"|~^(?#match nothing)", "")
)
return Triegex(*map(re.escape, literals)).to_regex().replace(r"\b", "").replace(r"|~^(?#match nothing)", "")


def merge_regexes(regexes: Iterable[str]) -> str:
"""Merge regex strings into a single regex string."""
if not (regexes := tuple(regexes)):
regexes = tuple(regexes)
if len(regexes) == 0:
return ""

merged = "(?:" + ")|(?:".join(regexes) + ")" if len(regexes) > 1 else regexes[0]
if len(regexes) == 1:
merged = regexes[0]
else:
merged = "(?:" + ")|(?:".join(regexes) + ")"
return f"(?:{merged})"


Expand Down Expand Up @@ -271,7 +269,7 @@ def find_like(like: SyntaxLike) -> Generator[sublime.Syntax, None, None]:
# by name (case-insensitive)
yield from filter(lambda syntax: like_cf == get_syntax_name(syntax).casefold(), all_syntaxes)
# by partial path
yield from filter(lambda syntax: like in syntax.path, all_syntaxes) # type: ignore
yield from filter(lambda syntax: like in syntax.path, all_syntaxes)

def filter_like(syntax: sublime.Syntax) -> bool:
return (include_hidden or not syntax.hidden) and (include_plaintext or not is_plaintext_syntax(syntax))
Expand Down

0 comments on commit 7ee9616

Please sign in to comment.