diff --git a/src/private_api/extract_decorated_marks.py b/src/private_api/extract_decorated_marks.py new file mode 100644 index 0000000000..230e5d18c2 --- /dev/null +++ b/src/private_api/extract_decorated_marks.py @@ -0,0 +1,47 @@ +from typing import Any + +from ..actions.bring_move import BringMoveTargets +from ..actions.swap import SwapTargets +from ..targets.target_types import ( + ImplicitDestination, + ImplicitTarget, + ListDestination, + ListTarget, + PrimitiveDestination, + PrimitiveTarget, + RangeTarget, +) + + +def extract_decorated_marks(capture: Any) -> list[Any]: + match capture: + case PrimitiveTarget(mark=mark): + if mark is None or mark["type"] != "decoratedSymbol": + return [] + return [mark] + case ImplicitTarget(): + return [] + case RangeTarget(anchor=anchor, active=active): + return extract_decorated_marks(anchor) + extract_decorated_marks(active) + case ListTarget(elements=elements): + return [ + mark for target in elements for mark in extract_decorated_marks(target) + ] + case PrimitiveDestination(target=target): + return extract_decorated_marks(target) + case ImplicitDestination(): + return [] + case ListDestination(destinations=destinations): + return [ + mark + for destination in destinations + for mark in extract_decorated_marks(destination) + ] + case BringMoveTargets(source=source, destination=destination): + return extract_decorated_marks(source) + extract_decorated_marks( + destination + ) + case SwapTargets(target1=target1, target2=target2): + return extract_decorated_marks(target1) + extract_decorated_marks(target2) + case _: + raise TypeError(f"Unknown capture type: {type(capture)}") diff --git a/src/private_api/private_api.py b/src/private_api/private_api.py new file mode 100644 index 0000000000..d6fd88e779 --- /dev/null +++ b/src/private_api/private_api.py @@ -0,0 +1,66 @@ +from typing import Any, Optional, Union + +from talon import Module, actions + +from ..targets.target_types import ( + CursorlessTarget, + ListTarget, + PrimitiveTarget, + RangeTarget, +) +from .extract_decorated_marks import extract_decorated_marks + +mod = Module() + + +@mod.action_class +class MiscActions: + def cursorless_private_extract_decorated_marks(capture: Any) -> list[dict]: + """Cursorless private api: Extract all decorated marks from a Talon capture""" + return extract_decorated_marks(capture) + + +@mod.action_class +class TargetBuilderActions: + """Cursorless private api low-level target builder actions""" + + def cursorless_private_build_primitive_target( + modifiers: list[dict], mark: Optional[dict] + ) -> PrimitiveTarget: + """Cursorless private api low-level target builder: Create a primitive target""" + return PrimitiveTarget(mark, modifiers) + + def cursorless_private_build_list_target( + elements: list[Union[PrimitiveTarget, RangeTarget]] + ) -> Union[PrimitiveTarget, ListTarget]: + """Cursorless private api low-level target builder: Create a list target""" + if len(elements) == 1: + return elements[0] + + return ListTarget(elements) + + +@mod.action_class +class TargetActions: + def cursorless_private_target_nothing() -> PrimitiveTarget: + """Cursorless private api: Creates the "nothing" target""" + return PrimitiveTarget({"type": "nothing"}, []) + + +@mod.action_class +class ActionActions: + def cursorless_private_action_highlight( + target: CursorlessTarget, highlightId: Optional[str] = None + ) -> None: + """Cursorless private api: Highlights a target""" + payload = { + "name": "highlight", + "target": target, + } + + if highlightId is not None: + payload["highlightId"] = highlightId + + actions.user.private_cursorless_command_and_wait( + payload, + )