Skip to content

Commit 41e0c26

Browse files
AndreasArvidssonpokeypre-commit-ci-lite[bot]
authored
Added destination and v6 api to Talon (#1717)
Depends on #1637 - Fixes #725 - Partially addresses #1440 - Fixes #1319 ## Checklist - [/] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [x] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [x] Update cheatsheet spoken form defaults - [x] Manually test the various snippet terms - [x] Manually test the snippet apis - [ ] I have not broken the cheatsheet --------- Co-authored-by: Pokey Rule <[email protected]> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent b0666d8 commit 41e0c26

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+850
-592
lines changed
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
1+
from typing import Any
2+
13
from talon import Module, actions
24

35
mod = Module()
46

57

68
@mod.action_class
79
class Actions:
8-
def cursorless_record_navigation_test():
10+
def private_cursorless_record_navigation_test():
911
"""Start / stop recording Cursorless navigation tests"""
1012
actions.user.run_rpc_command(
1113
"cursorless.recordTestCase", {"isHatTokenMapTest": True}
1214
)
1315

14-
def cursorless_record_error_test():
16+
def private_cursorless_record_error_test():
1517
"""Start recording Cursorless error tests"""
1618
actions.user.run_rpc_command(
1719
"cursorless.recordTestCase", {"recordErrors": True}
1820
)
1921

20-
def cursorless_record_highlights_test():
22+
def private_cursorless_record_highlights_test():
2123
"""Start recording Cursorless decoration tests"""
2224
actions.user.run_rpc_command(
2325
"cursorless.recordTestCase", {"isDecorationsTest": True}
2426
)
2527

26-
def cursorless_record_that_mark_test():
28+
def private_cursorless_record_that_mark_test():
2729
"""Start recording Cursorless that mark tests"""
2830
actions.user.run_rpc_command(
2931
"cursorless.recordTestCase", {"captureFinalThatMark": True}
@@ -32,3 +34,9 @@ def cursorless_record_that_mark_test():
3234
def cursorless_record_silent_test():
3335
"""Start recording Cursorless tests, without confirmation popup windows"""
3436
actions.user.run_rpc_command("cursorless.recordTestCase", {"isSilent": True})
37+
38+
def private_cursorless_make_snippet_test(target: Any):
39+
"""Test generating a snippet"""
40+
actions.user.private_cursorless_command_no_wait(
41+
{"name": "generateSnippet", "snippetName": "testSnippet", "target": target}
42+
)

cursorless-talon-dev/src/cursorless_dev.talon

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@ tag: user.cursorless
1414
user.run_rpc_command("cursorless.resumeRecording")
1515

1616
{user.cursorless_homophone} record navigation:
17-
user.cursorless_record_navigation_test()
18-
{user.cursorless_homophone} record error: user.cursorless_record_error_test()
17+
user.private_cursorless_record_navigation_test()
18+
{user.cursorless_homophone} record error:
19+
user.private_cursorless_record_error_test()
1920
{user.cursorless_homophone} record highlights:
20-
user.cursorless_record_highlights_test()
21+
user.private_cursorless_record_highlights_test()
2122
{user.cursorless_homophone} record that mark:
22-
user.cursorless_record_that_mark_test()
23+
user.private_cursorless_record_that_mark_test()
2324
{user.cursorless_homophone} record silent: user.cursorless_record_silent_test()
2425

2526
{user.cursorless_homophone} update cheatsheet:
26-
user.cursorless_cheat_sheet_update_json()
27+
user.private_cursorless_cheat_sheet_update_json()
2728

2829
test snippet make <user.cursorless_target>:
29-
user.cursorless_single_target_command_no_wait("generateSnippet", cursorless_target, "testSnippet")
30+
user.private_cursorless_make_snippet_test(cursorless_target)

cursorless-talon/src/actions/actions.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
from talon import Module, actions, app
22

33
from ..csv_overrides import init_csv_and_watch_changes
4-
from ..primitive_target import create_implicit_target
4+
from ..targets.target_types import CursorlessTarget, ImplicitDestination
55
from .actions_callback import callback_action_defaults, callback_action_map
66
from .actions_simple import (
77
no_wait_actions,
88
no_wait_actions_post_sleep,
9-
positional_action_defaults,
109
simple_action_defaults,
1110
)
11+
from .bring_move import BringMoveTargets
12+
from .execute_command import cursorless_execute_command_action
1213

1314
mod = Module()
1415

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

4041
@mod.action_class
4142
class Actions:
42-
def cursorless_command(action_id: str, target: dict):
43+
def cursorless_command(action_name: str, target: CursorlessTarget):
4344
"""Perform cursorless command on target"""
44-
if action_id in callback_action_map:
45-
return callback_action_map[action_id](target)
46-
elif action_id in no_wait_actions:
47-
actions.user.cursorless_single_target_command_no_wait(action_id, target)
48-
if action_id in no_wait_actions_post_sleep:
49-
actions.sleep(no_wait_actions_post_sleep[action_id])
50-
elif action_id in ["replaceWithTarget", "moveToTarget"]:
51-
actions.user.cursorless_multiple_target_command(
52-
action_id, [target, create_implicit_target()]
45+
if action_name in callback_action_map:
46+
callback_action_map[action_name](target)
47+
elif action_name in ["replaceWithTarget", "moveToTarget"]:
48+
actions.user.cursorless_bring_move(
49+
action_name, BringMoveTargets(target, ImplicitDestination())
5350
)
51+
elif action_name in no_wait_actions:
52+
action = {"name": action_name, "target": target}
53+
actions.user.private_cursorless_command_no_wait(action)
54+
if action_name in no_wait_actions_post_sleep:
55+
actions.sleep(no_wait_actions_post_sleep[action_name])
5456
else:
55-
return actions.user.cursorless_single_target_command(action_id, target)
57+
action = {"name": action_name, "target": target}
58+
actions.user.private_cursorless_command_and_wait(action)
5659

57-
def cursorless_vscode_command(command_id: str, target: dict):
60+
def cursorless_vscode_command(command_id: str, target: CursorlessTarget):
5861
"""
5962
Perform vscode command on cursorless target
6063
6164
Deprecated: prefer `cursorless_ide_command`
6265
"""
6366
return actions.user.cursorless_ide_command(command_id, target)
6467

65-
def cursorless_ide_command(command_id: str, target: dict):
68+
def cursorless_ide_command(command_id: str, target: CursorlessTarget):
6669
"""Perform ide command on cursorless target"""
67-
return ide_command(command_id, target)
70+
return cursorless_execute_command_action(command_id, target)
6871

69-
def cursorless_action_or_ide_command(instruction: dict, target: dict):
72+
def private_cursorless_action_or_ide_command(
73+
instruction: dict, target: CursorlessTarget
74+
):
7075
"""Perform cursorless action or ide command on target (internal use only)"""
7176
type = instruction["type"]
7277
value = instruction["value"]
7378
if type == "cursorless_action":
74-
return actions.user.cursorless_command(value, target)
79+
actions.user.cursorless_command(value, target)
7580
elif type == "ide_command":
76-
return actions.user.cursorless_ide_command(value, target)
77-
78-
79-
def ide_command(command_id: str, target: dict, command_options: dict = {}):
80-
return actions.user.cursorless_single_target_command(
81-
"executeCommand", target, command_id, command_options
82-
)
81+
actions.user.cursorless_ide_command(value, target)
8382

8483

8584
default_values = {
8685
"simple_action": simple_action_defaults,
87-
"positional_action": positional_action_defaults,
8886
"callback_action": callback_action_defaults,
87+
"paste_action": {"paste": "pasteFromClipboard"},
88+
"bring_move_action": {"bring": "replaceWithTarget", "move": "moveToTarget"},
8989
"swap_action": {"swap": "swapTargets"},
90-
"move_bring_action": {"bring": "replaceWithTarget", "move": "moveToTarget"},
9190
"wrap_action": {"wrap": "wrapWithPairedDelimiter", "repack": "rewrap"},
9291
"insert_snippet_action": {"snippet": "insertSnippet"},
9392
"reformat_action": {"format": "applyFormatter"},

cursorless-talon/src/actions/actions_callback.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
from talon import Module, actions
66

7-
from .call import run_call_action
8-
from .homophones import run_homophones_action
7+
from .call import cursorless_call_action
8+
from .homophones import cursorless_homophones_action
99

1010

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

2826
callback_action_defaults = {

cursorless-talon/src/actions/actions_simple.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@
4444
"unfold": "unfoldRegion",
4545
}
4646

47-
# NOTE: Please do not change these dicts. Use the CSVs for customization.
48-
# See https://www.cursorless.org/docs/user/customization/
49-
positional_action_defaults = {
50-
"paste": "pasteFromClipboard",
51-
}
52-
5347
# Don't wait for these actions to finish, usually because they hang on some kind of user interaction
5448
no_wait_actions = [
5549
"generateSnippet",
@@ -66,7 +60,3 @@
6660
"cursorless_simple_action",
6761
desc="Supported simple actions for cursorless navigation",
6862
)
69-
mod.list(
70-
"cursorless_positional_action",
71-
desc="Supported actions for cursorless that expect a positional target",
72-
)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from dataclasses import dataclass
2+
3+
from talon import Module, actions
4+
5+
from ..targets.target_types import (
6+
CursorlessDestination,
7+
CursorlessTarget,
8+
ImplicitDestination,
9+
)
10+
11+
12+
@dataclass
13+
class BringMoveTargets:
14+
source: CursorlessTarget
15+
destination: CursorlessDestination
16+
17+
18+
mod = Module()
19+
20+
21+
mod.list("cursorless_bring_move_action", desc="Cursorless bring or move actions")
22+
23+
24+
@mod.capture(rule="<user.cursorless_target> [<user.cursorless_destination>]")
25+
def cursorless_bring_move_targets(m) -> BringMoveTargets:
26+
source = m.cursorless_target
27+
28+
try:
29+
destination = m.cursorless_destination
30+
except AttributeError:
31+
destination = ImplicitDestination()
32+
33+
return BringMoveTargets(source, destination)
34+
35+
36+
@mod.action_class
37+
class Actions:
38+
def private_cursorless_bring_move(action_name: str, targets: BringMoveTargets):
39+
"""Execute Cursorless move/bring action"""
40+
actions.user.private_cursorless_command_and_wait(
41+
{
42+
"name": action_name,
43+
"source": targets.source,
44+
"destination": targets.destination,
45+
}
46+
)

cursorless-talon/src/actions/call.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
from talon import Module, actions
1+
from talon import actions
22

3-
from ..primitive_target import create_implicit_target
3+
from ..targets.target_types import CursorlessTarget, ImplicitTarget
44

5-
mod = Module()
65

7-
8-
def run_call_action(target: dict):
9-
targets = [target, create_implicit_target()]
10-
actions.user.cursorless_multiple_target_command("callAsFunction", targets)
6+
def cursorless_call_action(target: CursorlessTarget):
7+
actions.user.private_cursorless_command_and_wait(
8+
{
9+
"name": "callAsFunction",
10+
"callee": target,
11+
"argument": ImplicitTarget(),
12+
}
13+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from talon import actions
2+
3+
from ..targets.target_types import CursorlessTarget
4+
5+
6+
def cursorless_execute_command_action(
7+
command_id: str, target: CursorlessTarget, command_options: dict = {}
8+
):
9+
"""Execute Cursorless execute command action"""
10+
actions.user.private_cursorless_command_and_wait(
11+
{
12+
"name": "executeCommand",
13+
"commandId": command_id,
14+
"options": command_options,
15+
"target": target,
16+
}
17+
)

cursorless-talon/src/actions/find.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from talon import Module
22

3+
from ..targets.target_types import CursorlessTarget
4+
35
mod = Module()
46

57

68
@mod.action_class
79
class Actions:
8-
def cursorless_private_run_find_action(target: dict):
9-
"""Find text of target in editor"""
10+
def private_cursorless_find(target: CursorlessTarget):
11+
"""Execute Cursorless find action. Find text of target in editor"""

cursorless-talon/src/actions/get_text.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22

33
from talon import actions
44

5+
from ..targets.target_types import CursorlessTarget
56

6-
def get_text(
7-
target: dict,
7+
8+
def cursorless_get_text_action(
9+
target: CursorlessTarget,
810
show_decorations: Optional[bool] = None,
911
ensure_single_target: Optional[bool] = None,
10-
):
12+
) -> list[str]:
1113
"""Get target texts"""
12-
return actions.user.cursorless_single_target_command_get(
13-
"getText",
14-
target,
14+
return actions.user.private_cursorless_command_get(
1515
{
16-
"showDecorations": show_decorations,
17-
"ensureSingleTarget": ensure_single_target,
18-
},
16+
"name": "getText",
17+
"options": {
18+
"showDecorations": show_decorations,
19+
"ensureSingleTarget": ensure_single_target,
20+
},
21+
"target": target,
22+
}
1923
)

cursorless-talon/src/actions/homophones.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
from talon import actions, app
22

3-
from .get_text import get_text
3+
from .get_text import cursorless_get_text_action
4+
from .replace import cursorless_replace_action
45

56

6-
def run_homophones_action(target: dict):
7+
def cursorless_homophones_action(target: dict):
78
"""Replaced target with next homophone"""
8-
texts = get_text(target, show_decorations=False)
9+
texts = cursorless_get_text_action(target, show_decorations=False)
910
try:
1011
updated_texts = list(map(get_next_homophone, texts))
1112
except LookupError as e:
1213
app.notify(str(e))
1314
return
14-
actions.user.cursorless_replace(target, updated_texts)
15+
cursorless_replace_action(target, updated_texts)
1516

1617

1718
def get_next_homophone(word: str):

cursorless-talon/src/actions/move_bring.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)