dotfiles/talon/cursorless-talon/src/modifiers/ordinal_scope.py

91 lines
2.7 KiB
Python

from typing import Any
from talon import Module
from ..targets.range_target import RangeConnective
mod = Module()
mod.list("cursorless_first_modifier", desc="Cursorless first modifiers")
mod.list("cursorless_last_modifier", desc="Cursorless last modifiers")
@mod.capture(
rule="<user.ordinals_small> | [<user.ordinals_small>] {user.cursorless_last_modifier}"
)
def ordinal_or_last(m) -> int:
"""An ordinal or the word 'last'"""
if m[-1] == "last":
return -getattr(m, "ordinals_small", 1)
return m.ordinals_small - 1
@mod.capture(
rule="<user.ordinal_or_last> [<user.cursorless_range_connective> <user.ordinal_or_last>] <user.cursorless_scope_type>"
)
def cursorless_ordinal_range(m) -> dict[str, Any]:
"""Ordinal range"""
anchor = create_ordinal_scope_modifier(
m.cursorless_scope_type, m.ordinal_or_last_list[0]
)
if len(m.ordinal_or_last_list) > 1:
active = create_ordinal_scope_modifier(
m.cursorless_scope_type, m.ordinal_or_last_list[1]
)
range_connective: RangeConnective = m.cursorless_range_connective
return {
"type": "range",
"anchor": anchor,
"active": active,
"excludeAnchor": range_connective.excludeAnchor,
"excludeActive": range_connective.excludeActive,
}
return anchor
@mod.capture(
rule=(
"[{user.cursorless_every_scope_modifier}] "
"({user.cursorless_first_modifier} | {user.cursorless_last_modifier}) "
"<user.private_cursorless_number_small> <user.cursorless_scope_type_plural>"
),
)
def cursorless_first_last(m) -> dict[str, Any]:
"""First/last `n` scopes; eg "first three funks"""
is_every = hasattr(m, "cursorless_every_scope_modifier")
if hasattr(m, "cursorless_first_modifier"):
return create_ordinal_scope_modifier(
m.cursorless_scope_type_plural,
0,
m.private_cursorless_number_small,
is_every,
)
return create_ordinal_scope_modifier(
m.cursorless_scope_type_plural,
-m.private_cursorless_number_small,
m.private_cursorless_number_small,
is_every,
)
@mod.capture(rule="<user.cursorless_ordinal_range> | <user.cursorless_first_last>")
def cursorless_ordinal_scope(m) -> dict[str, Any]:
"""Ordinal ranges such as subwords or characters"""
return m[0]
def create_ordinal_scope_modifier(
scope_type: dict,
start: int,
length: int = 1,
is_every: bool = False,
):
res = {
"type": "ordinalScope",
"scopeType": scope_type,
"start": start,
"length": length,
}
if is_every:
res["isEvery"] = True
return res