diff --git a/CSS/.python-version b/CSS/.python-version
index 98fccd6d02..24ee5b1be9 100644
--- a/CSS/.python-version
+++ b/CSS/.python-version
@@ -1 +1 @@
-3.8
\ No newline at end of file
+3.13
diff --git a/CSS/css_completions.py b/CSS/css_completions.py
index 77d2679c00..a9a506c40d 100644
--- a/CSS/css_completions.py
+++ b/CSS/css_completions.py
@@ -1,6 +1,7 @@
-import re
import sublime
import sublime_plugin
+
+import re
import timeit
from functools import cached_property, wraps
@@ -17,63 +18,63 @@
def timing(func):
- @wraps(func)
+ @wraps(wrapped=func)
def wrap(*args, **kw):
if ENABLE_TIMING:
- ts = timeit.default_timer()
+ ts: float = timeit.default_timer()
result = func(*args, **kw)
if ENABLE_TIMING:
- te = timeit.default_timer()
+ te: float = timeit.default_timer()
print(f"{func.__name__}({args}, {kw}) took: {1000.0 * (te - ts):2.3f} ms")
return result
return wrap
-def match_selector(view, pt, scope):
+def match_selector(view: sublime.View, pt: int, scope: str) -> bool:
# This will catch scenarios like:
# - .foo {font-style: |}
# -
- return any(view.match_selector(p, scope) for p in (pt, pt - 1))
+ return any(view.match_selector(pt=p, selector=scope) for p in (pt, pt - 1))
-def next_none_whitespace(view, pt):
+def next_none_whitespace(view: sublime.View, pt: int) -> str | None:
for pt in range(pt, view.size()):
ch = view.substr(pt)
if ch not in ' \t':
return ch
+ return None
class CSSCompletions(sublime_plugin.EventListener):
@cached_property
- def func_args(self):
+ def func_args(self) -> dict:
return completions.get_func_args()
@cached_property
- def props(self):
+ def props(self) -> dict:
return completions.get_properties()
@cached_property
- def re_name(self):
+ def re_name(self) -> re.Pattern[str]:
return re.compile(r"([a-zA-Z-]+)\s*:[^:;{}]*$")
@cached_property
- def re_value(self):
+ def re_value(self) -> re.Pattern[str]:
return re.compile(r"^(?:\s*(:)|([ \t]*))([^:]*)([;}])")
@timing
- def on_query_completions(self, view, prefix, locations):
-
- settings = sublime.load_settings('CSS.sublime-settings')
- if settings.get('disable_default_completions'):
+ def on_query_completions(self, view: sublime.View, prefix: str, locations: list[int]) -> sublime.CompletionList | None:
+ settings: sublime.Settings = sublime.load_settings(base_name='CSS.sublime-settings')
+ if settings.get(key='disable_default_completions'):
return None
- selector = settings.get('default_completions_selector', '')
+ selector = settings.get(key='default_completions_selector', default='')
if isinstance(selector, list):
selector = ''.join(selector)
- pt = locations[0]
- if not match_selector(view, pt, selector):
+ pt: int = locations[0]
+ if not match_selector(view, pt, scope=selector):
return None
if match_selector(view, pt, "meta.property-value.css meta.function-call.arguments"):
@@ -84,11 +85,11 @@ def on_query_completions(self, view, prefix, locations):
items = self.complete_property_name(view, prefix, pt)
if items:
- return sublime.CompletionList(items)
+ return sublime.CompletionList(completions=items)
return None
- def complete_property_name(self, view, prefix, pt):
- text = view.substr(sublime.Region(pt, view.line(pt).end()))
+ def complete_property_name(self, view: sublime.View, prefix: str, pt: int) -> list[sublime.CompletionItem]:
+ text = view.substr(x=sublime.Region(a=pt, b=view.line(x=pt).end()))
matches = self.re_value.search(text)
if matches:
colon, space, value, term = matches.groups()
@@ -99,28 +100,28 @@ def complete_property_name(self, view, prefix, pt):
term = ""
# don't append anything if next character is a colon
- suffix = ""
+ suffix: str = ""
if not colon:
# add space after colon if smart typing is enabled
- if not space and view.settings().get("auto_complete_trailing_spaces"):
+ if not space and view.settings().get(key="auto_complete_trailing_spaces"):
suffix = ": $0"
else:
suffix = ":$0"
# terminate empty value if not within parentheses
- if not value and not term and not match_selector(view, pt, "meta.group"):
+ if not value and not term and not match_selector(view, pt, scope="meta.group"):
suffix += ";"
- return (
+ return [
sublime.CompletionItem(
trigger=prop,
completion=prop + suffix,
completion_format=sublime.COMPLETION_FORMAT_SNIPPET,
kind=KIND_CSS_PROPERTY
) for prop in self.props
- )
+ ]
- def complete_property_value(self, view, prefix, pt):
+ def complete_property_value(self, view: sublime.View, prefix: str, pt: int) -> list[sublime.CompletionItem]:
completions = [
sublime.CompletionItem(
trigger="!important",
@@ -129,7 +130,7 @@ def complete_property_value(self, view, prefix, pt):
details="override any other declaration"
)
]
- text = view.substr(sublime.Region(view.line(pt).begin(), pt - len(prefix)))
+ text: str = view.substr(x=sublime.Region(a=view.line(x=pt).begin(), b=pt - len(prefix)))
matches = self.re_name.search(text)
if matches:
prop = matches.group(1)
@@ -137,7 +138,7 @@ def complete_property_value(self, view, prefix, pt):
if values:
details = f"{prop} property-value"
- if match_selector(view, pt, "meta.group") or next_none_whitespace(view, pt) == ";":
+ if match_selector(view, pt, scope="meta.group") or next_none_whitespace(view, pt) == ";":
suffix = ""
else:
suffix = "$0;"
@@ -161,25 +162,25 @@ def complete_property_value(self, view, prefix, pt):
return completions
- def complete_function_argument(self, view: sublime.View, prefix, pt):
+ def complete_function_argument(self, view: sublime.View, prefix: str, pt: int) -> list[sublime.CompletionItem]:
func_name = ""
nest_level = 1
# Look for the beginning of the current function call's arguments list,
# while ignoring any nested function call or group.
for i in range(pt - 1, pt - 32 * 1024, -1):
- ch = view.substr(i)
+ ch: str = view.substr(x=i)
# end of nested arguments list or group before caret
- if ch == ")" and not view.match_selector(i, "string, comment"):
+ if ch == ")" and not view.match_selector(pt=i, selector="string, comment"):
nest_level += 1
continue
# begin of maybe nested arguments list or group before caret
- if ch == "(" and not view.match_selector(i, "string, comment"):
+ if ch == "(" and not view.match_selector(pt=i, selector="string, comment"):
nest_level -= 1
# Stop, if nesting level drops below start value as this indicates the
# beginning of the arguments list the function name is of interest for.
if nest_level <= 0:
- func_name = view.substr(view.expand_by_class(
- i - 1, sublime.CLASS_WORD_START | sublime.CLASS_WORD_END))
+ func_name: str = view.substr(x=view.expand_by_class(
+ x=i - 1, classes=sublime.CLASS_WORD_START | sublime.CLASS_WORD_END))
break
if func_name == "var":
@@ -191,18 +192,18 @@ def complete_function_argument(self, view: sublime.View, prefix, pt):
details="var() argument"
)
for symbol in set(
- view.substr(symbol_region)
- for symbol_region in view.find_by_selector("entity.other.custom-property")
+ view.substr(x=symbol_region)
+ for symbol_region in view.find_by_selector(selector="entity.other.custom-property")
)
if not prefix or symbol.startswith(prefix)
]
args = self.func_args.get(func_name)
if not args:
- return None
+ return []
completions = []
- details = f"{func_name}() argument"
+ details: str = f"{func_name}() argument"
for arg in args:
if isinstance(arg, list):
completions.append(sublime.CompletionItem(