Skip to content

Commit 9251a02

Browse files
authored
Add cursorless_create_destination action to talon api (#2402)
This came up during a pairing session. I wanted to do something like: ```talon transform <user.cursorless_target>: old = user.cursorless_get_text(cursorless_target, 1) new = some_transformation(old) destination = user.cursorless_create_destination(cursorless_target) user.cursorless_insert(destination, new) ``` Notice I can't use our existing `user.cursorless_insert` out of the box because it expects a destination, so we need a way to make a destination from a target ## 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] I have not broken the cheatsheet
1 parent 3a0d9c8 commit 9251a02

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
tags: [enhancement, talon]
3+
pullRequest: 2402
4+
---
5+
6+
- Add `user.cursorless_create_destination` to the public API. See the [Talon-side api docs](../docs/user/customization.md#cursorless-public-api) and the example code in the [How do I run a custom Python transformation on a target?](../docs/user/how-to.md#how-do-i-run-a-custom-python-transformation-on-a-target) section for more information.

cursorless-talon/src/public_api.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from talon import Module
2+
3+
from .targets.target_types import (
4+
CursorlessDestination,
5+
InsertionMode,
6+
ListTarget,
7+
PrimitiveDestination,
8+
PrimitiveTarget,
9+
RangeTarget,
10+
)
11+
12+
mod = Module()
13+
14+
15+
@mod.action_class
16+
class Actions:
17+
def cursorless_create_destination(
18+
target: ListTarget | RangeTarget | PrimitiveTarget, # pyright: ignore [reportGeneralTypeIssues]
19+
insertion_mode: InsertionMode = "to",
20+
) -> CursorlessDestination:
21+
"""Cursorless: Create destination from target"""
22+
return PrimitiveDestination(insertion_mode, target)

cursorless-talon/src/targets/target_types.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ class ListTarget:
4646
PrimitiveTarget,
4747
]
4848

49+
InsertionMode = Literal["to", "before", "after"]
50+
4951

5052
@dataclass
5153
class PrimitiveDestination:
5254
type = "primitive"
53-
insertionMode: Literal["to", "before", "after"]
55+
insertionMode: InsertionMode
5456
target: Union[ListTarget, RangeTarget, PrimitiveTarget]
5557

5658

docs/user/customization.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ Cursorless exposes a couple talon actions and captures that you can use to defin
142142
- `<user.cursorless_target>`
143143
Represents a cursorless target, such as `"air"`, `"this"`, `"air past bat"`, `"air and bat"`, `"funk air past token bat and class cap"`, etc
144144

145+
- `<user.cursorless_destination>`
146+
Represents a cursorless destination, such as `"to air"`, `"before this"`, `"after air and bat"`, etc
147+
145148
### Public Talon actions
146149

147150
- `user.cursorless_command(action_id: str, target: cursorless_target)`:
@@ -158,6 +161,8 @@ Cursorless exposes a couple talon actions and captures that you can use to defin
158161
- `user.cursorless_insert(destination: CursorlessDestination, text: Union[str, List[str]])`:
159162
Insert text at destination.
160163
eg: `user.cursorless_insert(cursorless_destination, "hello")`
164+
- `user.cursorless_create_destination(target: CursorlessTarget, insertion_mode: Literal["to", "before", "after"] = "to") -> CursorlessDestination`:
165+
Create a destination from a target. The insertion mode can be `to`, `before`, or `after`, and defaults to `to`, which will replace the target. See [How do I run a custom Python transformation on a target?](./how-to.md#how-do-i-run-a-custom-python-transformation-on-a-target) for example usage.
161166
- `user.cursorless_reformat(target: CursorlessTarget, formatters: str)`
162167
Reformat target with specified formatters.
163168
eg: `user.cursorless_reformat(cursorless_target, "ALL_CAPS")`

docs/user/how-to.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,44 @@ You can now say eg `"echo air past bat"`.
4646
See the [Talon-side api docs](./customization.md#cursorless-public-api) for more on creating custom Cursorless commands
4747

4848
:::
49+
50+
## How do I run a custom Python transformation on a target?
51+
52+
1. Add the transformation to a Python file in your Talon user directory:
53+
54+
```python
55+
from talon import Module
56+
57+
mod = Module()
58+
59+
60+
@mod.action_class
61+
class Actions:
62+
def hello(text: str) -> str:
63+
"""Returns a greeting for the given text."""
64+
return f"Hello, {text}!"
65+
```
66+
67+
2. Add a spoken form to your `vscode.talon`:
68+
69+
```talon
70+
hello <user.cursorless_target>:
71+
old = user.cursorless_get_text(cursorless_target, true)
72+
new = user.hello(old)
73+
destination = user.cursorless_create_destination(cursorless_target)
74+
user.cursorless_insert(destination, new)
75+
```
76+
77+
Now, for example if you have a target `aardvark` with a hat over the `a`, you can say `"hello air"` to replace it with `Hello, aardvark!`.
78+
79+
:::info
80+
81+
See the [Talon-side api docs](./customization.md#cursorless-public-api) for more on creating custom Cursorless commands
82+
83+
:::
84+
85+
:::info
86+
87+
Notice how we use `cursorless_create_destination` to create a destination for the result of the transformation. The `cursorless_insert` action expects a destination, so that it knows whether to replace, insert before, or insert after the target. See [Destinations](reference/destinations.md) for more information.
88+
89+
:::

0 commit comments

Comments
 (0)