Skip to content

Update Talon side for new destination types #1632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions cursorless-talon-dev/src/cursorless_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,32 @@

@mod.action_class
class Actions:
def cursorless_record_navigation_test():
def private_cursorless_record_navigation_test():
"""Start / stop recording Cursorless navigation tests"""
actions.user.run_rpc_command(
"cursorless.recordTestCase", {"isHatTokenMapTest": True}
)

def cursorless_record_error_test():
def private_cursorless_record_error_test():
"""Start recording Cursorless error tests"""
actions.user.run_rpc_command(
"cursorless.recordTestCase", {"recordErrors": True}
)

def cursorless_record_highlights_test():
def private_cursorless_record_highlights_test():
"""Start recording Cursorless decoration tests"""
actions.user.run_rpc_command(
"cursorless.recordTestCase", {"isDecorationsTest": True}
)

def cursorless_record_that_mark_test():
def private_cursorless_record_that_mark_test():
"""Start recording Cursorless that mark tests"""
actions.user.run_rpc_command(
"cursorless.recordTestCase", {"captureFinalThatMark": True}
)

def private_cursorless_makes_snippet_test(target):
"""Test generating a snippet"""
actions.user.private_cursorless_command_no_wait(
{"name": "generateSnippet", "snippetName": "testSnippet", "target": target}
)
13 changes: 7 additions & 6 deletions cursorless-talon-dev/src/cursorless_dev.talon
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ tag: user.cursorless
user.run_rpc_command("cursorless.resumeRecording")

{user.cursorless_homophone} record navigation:
user.cursorless_record_navigation_test()
{user.cursorless_homophone} record error: user.cursorless_record_error_test()
user.private_cursorless_record_navigation_test()
{user.cursorless_homophone} record error:
user.private_cursorless_record_error_test()
{user.cursorless_homophone} record highlights:
user.cursorless_record_highlights_test()
user.private_cursorless_record_highlights_test()
{user.cursorless_homophone} record that mark:
user.cursorless_record_that_mark_test()
user.private_cursorless_record_that_mark_test()

{user.cursorless_homophone} update cheatsheet:
user.cursorless_cheat_sheet_update_json()
user.private_cursorless_cheat_sheet_update_json()

test snippet make <user.cursorless_target>:
user.cursorless_single_target_command_no_wait("generateSnippet", cursorless_target, "testSnippet")
user.private_cursorless_makes_snippet_test(cursorless_target)
53 changes: 26 additions & 27 deletions cursorless-talon/src/actions/actions.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from talon import Module, actions, app

from ..csv_overrides import init_csv_and_watch_changes
from ..primitive_target import create_implicit_target
from ..targets.target_types import CursorlessTarget, ImplicitTarget
from .actions_callback import callback_action_defaults, callback_action_map
from .actions_simple import (
no_wait_actions,
no_wait_actions_post_sleep,
positional_action_defaults,
simple_action_defaults,
)
from .bring_move import BringMoveTargets
from .execute_command import cursorless_execute_command_action

mod = Module()

Expand Down Expand Up @@ -39,55 +40,53 @@ def cursorless_action_or_ide_command(m) -> dict:

@mod.action_class
class Actions:
def cursorless_command(action_id: str, target: dict):
def cursorless_command(action_name: str, target: CursorlessTarget):
"""Perform cursorless command on target"""
if action_id in callback_action_map:
return callback_action_map[action_id](target)
elif action_id in no_wait_actions:
actions.user.cursorless_single_target_command_no_wait(action_id, target)
if action_id in no_wait_actions_post_sleep:
actions.sleep(no_wait_actions_post_sleep[action_id])
elif action_id in ["replaceWithTarget", "moveToTarget"]:
actions.user.cursorless_multiple_target_command(
action_id, [target, create_implicit_target()]
if action_name in callback_action_map:
callback_action_map[action_name](target)
elif action_name in ["replaceWithTarget", "moveToTarget"]:
actions.user.cursorless_bring_move(
action_name, BringMoveTargets(target, ImplicitTarget())
)
elif action_name in no_wait_actions:
action = {"name": action_name, "target": target}
actions.user.private_cursorless_command_no_wait(action)
if action_name in no_wait_actions_post_sleep:
actions.sleep(no_wait_actions_post_sleep[action_name])
else:
return actions.user.cursorless_single_target_command(action_id, target)
action = {"name": action_name, "target": target}
actions.user.private_cursorless_command_and_wait(action)

def cursorless_vscode_command(command_id: str, target: dict):
def cursorless_vscode_command(command_id: str, target: CursorlessTarget):
"""
Perform vscode command on cursorless target

Deprecated: prefer `cursorless_ide_command`
"""
return actions.user.cursorless_ide_command(command_id, target)

def cursorless_ide_command(command_id: str, target: dict):
def cursorless_ide_command(command_id: str, target: CursorlessTarget):
"""Perform ide command on cursorless target"""
return ide_command(command_id, target)
return cursorless_execute_command_action(command_id, target)

def cursorless_action_or_ide_command(instruction: dict, target: dict):
def private_cursorless_action_or_ide_command(
instruction: dict, target: CursorlessTarget
):
"""Perform cursorless action or ide command on target (internal use only)"""
type = instruction["type"]
value = instruction["value"]
if type == "cursorless_action":
return actions.user.cursorless_command(value, target)
actions.user.cursorless_command(value, target)
elif type == "ide_command":
return actions.user.cursorless_ide_command(value, target)


def ide_command(command_id: str, target: dict, command_options: dict = {}):
return actions.user.cursorless_single_target_command(
"executeCommand", target, command_id, command_options
)
actions.user.cursorless_ide_command(value, target)


default_values = {
"simple_action": simple_action_defaults,
"positional_action": positional_action_defaults,
"callback_action": callback_action_defaults,
"paste_action": {"paste": "pasteFromClipboard"},
"bring_move_action": {"bring": "replaceWithTarget", "move": "moveToTarget"},
"swap_action": {"swap": "swapTargets"},
"move_bring_action": {"bring": "replaceWithTarget", "move": "moveToTarget"},
"wrap_action": {"wrap": "wrapWithPairedDelimiter", "repack": "rewrap"},
"insert_snippet_action": {"snippet": "insertSnippet"},
"reformat_action": {"format": "applyFormatter"},
Expand Down
12 changes: 5 additions & 7 deletions cursorless-talon/src/actions/actions_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

from talon import Module, actions

from .call import run_call_action
from .homophones import run_homophones_action
from .call import cursorless_call_action
from .homophones import cursorless_homophones_action


@dataclass
Expand All @@ -18,11 +18,9 @@ class CallbackAction:
# NOTE: Please do not change these dicts. Use the CSVs for customization.
# See https://www.cursorless.org/docs/user/customization/
callbacks = [
CallbackAction("call", "callAsFunction", run_call_action),
CallbackAction(
"scout", "findInDocument", actions.user.cursorless_private_run_find_action
),
CallbackAction("phones", "nextHomophone", run_homophones_action),
CallbackAction("call", "callAsFunction", cursorless_call_action),
CallbackAction("scout", "findInDocument", actions.user.private_cursorless_find),
CallbackAction("phones", "nextHomophone", cursorless_homophones_action),
]

callback_action_defaults = {
Expand Down
13 changes: 3 additions & 10 deletions cursorless-talon/src/actions/actions_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
simple_action_defaults = {
"bottom": "scrollToBottom",
"break point": "toggleLineBreakpoint",
"call": "callAsFunction",
"carve": "cutToClipboard",
"center": "scrollToCenter",
"change": "clearAndSetSelection",
Expand All @@ -27,6 +28,7 @@
"hover": "showHover",
"indent": "indentLine",
"inspect": "showDebugHover",
"phones": "nextHomophone",
"post": "setSelectionAfter",
"pour": "editNewLineAfter",
"pre": "setSelectionBefore",
Expand All @@ -36,6 +38,7 @@
"rename": "rename",
"reverse": "reverseTargets",
"scout all": "findInWorkspace",
"scout": "findInDocument",
"shuffle": "randomizeTargets",
"snippet make": "generateSnippet",
"sort": "sortTargets",
Expand All @@ -44,12 +47,6 @@
"unfold": "unfoldRegion",
}

# NOTE: Please do not change these dicts. Use the CSVs for customization.
# See https://www.cursorless.org/docs/user/customization/
positional_action_defaults = {
"paste": "pasteFromClipboard",
}

# Don't wait for these actions to finish, usually because they hang on some kind of user interaction
no_wait_actions = [
"generateSnippet",
Expand All @@ -66,7 +63,3 @@
"cursorless_simple_action",
desc="Supported simple actions for cursorless navigation",
)
mod.list(
"cursorless_positional_action",
desc="Supported actions for cursorless that expect a positional target",
)
46 changes: 46 additions & 0 deletions cursorless-talon/src/actions/bring_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from dataclasses import dataclass

from talon import Module, actions

from ..targets.target_types import (
CursorlessDestination,
CursorlessTarget,
ImplicitDestination,
)


@dataclass
class BringMoveTargets:
source: CursorlessTarget
destination: CursorlessDestination


mod = Module()


mod.list("cursorless_bring_move_action", desc="Cursorless bring or move actions")


@mod.capture(rule="<user.cursorless_target> [<user.cursorless_destination>]")
def cursorless_bring_move_targets(m) -> BringMoveTargets:
source = m.cursorless_target

try:
destination = m.cursorless_destination
except AttributeError:
destination = ImplicitDestination()

return BringMoveTargets(source, destination)


@mod.action_class
class Actions:
def private_cursorless_bring_move(action_name: str, targets: BringMoveTargets):
"""Execute Cursorless move/bring action"""
actions.user.private_cursorless_command_and_wait(
{
"name": action_name,
"source": targets.source,
"destination": targets.destination,
}
)
17 changes: 10 additions & 7 deletions cursorless-talon/src/actions/call.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from talon import Module, actions
from talon import actions

from ..primitive_target import create_implicit_target
from ..targets.target_types import CursorlessTarget, ImplicitTarget

mod = Module()


def run_call_action(target: dict):
targets = [target, create_implicit_target()]
actions.user.cursorless_multiple_target_command("callAsFunction", targets)
def cursorless_call_action(target: CursorlessTarget):
actions.user.private_cursorless_command_and_wait(
{
"name": "callAsFunction",
"callee": target,
"argument": ImplicitTarget(),
}
)
17 changes: 17 additions & 0 deletions cursorless-talon/src/actions/execute_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from talon import actions

from ..targets.target_types import CursorlessTarget


def cursorless_execute_command_action(
command_id: str, target: CursorlessTarget, command_options: dict = {}
):
"""Execute Cursorless execute command action"""
actions.user.private_cursorless_command_and_wait(
{
"name": "executeCommand",
"commandId": command_id,
"options": command_options,
"target": target,
}
)
6 changes: 4 additions & 2 deletions cursorless-talon/src/actions/find.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from talon import Module

from ..targets.target_types import CursorlessTarget

mod = Module()


@mod.action_class
class Actions:
def cursorless_private_run_find_action(target: dict):
"""Find text of target in editor"""
def private_cursorless_find(target: CursorlessTarget):
"""Execute Cursorless find action. Find text of target in editor"""
22 changes: 13 additions & 9 deletions cursorless-talon/src/actions/get_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

from talon import actions

from ..targets.target_types import CursorlessTarget

def get_text(
target: dict,

def cursorless_get_text(
target: CursorlessTarget,
show_decorations: Optional[bool] = None,
ensure_single_target: Optional[bool] = None,
):
) -> list[str]:
"""Get target texts"""
return actions.user.cursorless_single_target_command_get(
"getText",
target,
return actions.user.private_cursorless_command_get(
{
"showDecorations": show_decorations,
"ensureSingleTarget": ensure_single_target,
},
"name": "getText",
"options": {
"showDecorations": show_decorations,
"ensureSingleTarget": ensure_single_target,
},
"target": target,
}
)
9 changes: 5 additions & 4 deletions cursorless-talon/src/actions/homophones.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from talon import actions, app

from .get_text import get_text
from .get_text import cursorless_get_text
from .replace import cursorless_replace_action


def run_homophones_action(target: dict):
def cursorless_homophones_action(target: dict):
"""Replaced target with next homophone"""
texts = get_text(target, show_decorations=False)
texts = cursorless_get_text(target, show_decorations=False)
try:
updated_texts = list(map(get_next_homophone, texts))
except LookupError as e:
app.notify(str(e))
return
actions.user.cursorless_replace(target, updated_texts)
cursorless_replace_action(target, updated_texts)


def get_next_homophone(word: str):
Expand Down
Loading