Skip to content

Commit 368f891

Browse files
Make cheat sheet handle missing spoken forms
1 parent 57acd6c commit 368f891

File tree

9 files changed

+459
-307
lines changed

9 files changed

+459
-307
lines changed

cursorless-talon/src/cheatsheet/get_list.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,23 @@ def get_raw_list(name: str) -> Mapping[str, str]:
4141
return typing.cast(dict[str, str], registry.lists[cursorless_list_name][0]).copy()
4242

4343

44-
def get_spoken_form_from_list(list_name: str, value: str) -> str:
44+
def get_spoken_form_from_list(list_name: str, value: str) -> str | None:
4545
"""Get the spoken form of a value from a list.
4646
4747
Args:
4848
list_name (str): The name of the list.
4949
value (str): The value to look up.
5050
5151
Returns:
52-
str: The spoken form of the value.
52+
str: The spoken form of the value if found, otherwise None.
5353
"""
5454
return next(
55-
spoken_form for spoken_form, v in get_raw_list(list_name).items() if v == value
55+
(
56+
spoken_form
57+
for spoken_form, v in get_raw_list(list_name).items()
58+
if v == value
59+
),
60+
None,
5661
)
5762

5863

Lines changed: 140 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from ...actions.actions import ACTION_LIST_NAMES
2-
from ..get_list import get_raw_list, make_dict_readable
2+
from ..get_list import ListItemDescriptor, get_raw_list, make_dict_readable
33

44

5-
def get_actions():
5+
def get_actions() -> list[ListItemDescriptor]:
66
all_actions = {}
77
for name in ACTION_LIST_NAMES:
88
all_actions.update(get_raw_list(name))
@@ -28,111 +28,144 @@ def get_actions():
2828
if value in multiple_target_action_names
2929
}
3030

31-
swap_connective = list(get_raw_list("swap_connective").keys())[0]
31+
swap_connectives = list(get_raw_list("swap_connective").keys())
32+
swap_connective = swap_connectives[0] if swap_connectives else None
3233

33-
return [
34-
*make_dict_readable(
35-
"action",
36-
simple_actions,
37-
{
38-
"editNewLineAfter": "Edit new line/scope after",
39-
"editNewLineBefore": "Edit new line/scope before",
40-
},
41-
),
42-
{
43-
"id": "replaceWithTarget",
44-
"type": "action",
45-
"variations": [
46-
{
47-
"spokenForm": f"{complex_actions['replaceWithTarget']} <target> <destination>",
48-
"description": "Copy <target> to <destination>",
49-
},
50-
{
51-
"spokenForm": f"{complex_actions['replaceWithTarget']} <target>",
52-
"description": "Insert copy of <target> at cursor",
53-
},
54-
],
55-
},
56-
{
57-
"id": "pasteFromClipboard",
58-
"type": "action",
59-
"variations": [
60-
{
61-
"spokenForm": f"{complex_actions['pasteFromClipboard']} <destination>",
62-
"description": "Paste from clipboard at <destination>",
63-
}
64-
],
65-
},
66-
{
67-
"id": "moveToTarget",
68-
"type": "action",
69-
"variations": [
70-
{
71-
"spokenForm": f"{complex_actions['moveToTarget']} <target> <destination>",
72-
"description": "Move <target> to <destination>",
73-
},
74-
{
75-
"spokenForm": f"{complex_actions['moveToTarget']} <target>",
76-
"description": "Move <target> to cursor position",
77-
},
78-
],
79-
},
80-
{
81-
"id": "swapTargets",
82-
"type": "action",
83-
"variations": [
84-
{
85-
"spokenForm": f"{complex_actions['swapTargets']} <target 1> {swap_connective} <target 2>",
86-
"description": "Swap <target 1> with <target 2>",
87-
},
88-
{
89-
"spokenForm": f"{complex_actions['swapTargets']} {swap_connective} <target>",
90-
"description": "Swap selection with <target>",
91-
},
92-
],
93-
},
34+
items = make_dict_readable(
35+
"action",
36+
simple_actions,
9437
{
95-
"id": "applyFormatter",
96-
"type": "action",
97-
"variations": [
98-
{
99-
"spokenForm": f"{complex_actions['applyFormatter']} <formatter> at <target>",
100-
"description": "Reformat <target> as <formatter>",
101-
}
102-
],
38+
"editNewLineAfter": "Edit new line/scope after",
39+
"editNewLineBefore": "Edit new line/scope before",
10340
},
104-
{
105-
"id": "callAsFunction",
106-
"type": "action",
107-
"variations": [
108-
{
109-
"spokenForm": f"{complex_actions['callAsFunction']} <target>",
110-
"description": "Call <target> on selection",
111-
},
112-
{
113-
"spokenForm": f"{complex_actions['callAsFunction']} <target 1> on <target 2>",
114-
"description": "Call <target 1> on <target 2>",
115-
},
116-
],
117-
},
118-
{
119-
"id": "wrapWithPairedDelimiter",
120-
"type": "action",
121-
"variations": [
122-
{
123-
"spokenForm": f"<pair> {complex_actions['wrapWithPairedDelimiter']} <target>",
124-
"description": "Wrap <target> with <pair>",
125-
}
126-
],
127-
},
128-
{
129-
"id": "rewrap",
130-
"type": "action",
131-
"variations": [
132-
{
133-
"spokenForm": f"<pair> {complex_actions['rewrap']} <target>",
134-
"description": "Rewrap <target> with <pair>",
135-
}
136-
],
137-
},
138-
]
41+
)
42+
43+
if "replaceWithTarget" in complex_actions:
44+
items.append(
45+
{
46+
"id": "replaceWithTarget",
47+
"type": "action",
48+
"variations": [
49+
{
50+
"spokenForm": f"{complex_actions['replaceWithTarget']} <target> <destination>",
51+
"description": "Copy <target> to <destination>",
52+
},
53+
{
54+
"spokenForm": f"{complex_actions['replaceWithTarget']} <target>",
55+
"description": "Insert copy of <target> at cursor",
56+
},
57+
],
58+
}
59+
)
60+
61+
if "pasteFromClipboard" in complex_actions:
62+
items.append(
63+
{
64+
"id": "pasteFromClipboard",
65+
"type": "action",
66+
"variations": [
67+
{
68+
"spokenForm": f"{complex_actions['pasteFromClipboard']} <destination>",
69+
"description": "Paste from clipboard at <destination>",
70+
}
71+
],
72+
}
73+
)
74+
75+
if "moveToTarget" in complex_actions:
76+
items.append(
77+
{
78+
"id": "moveToTarget",
79+
"type": "action",
80+
"variations": [
81+
{
82+
"spokenForm": f"{complex_actions['moveToTarget']} <target> <destination>",
83+
"description": "Move <target> to <destination>",
84+
},
85+
{
86+
"spokenForm": f"{complex_actions['moveToTarget']} <target>",
87+
"description": "Move <target> to cursor position",
88+
},
89+
],
90+
}
91+
)
92+
93+
if "swapTargets" in complex_actions and swap_connective:
94+
items.append(
95+
{
96+
"id": "swapTargets",
97+
"type": "action",
98+
"variations": [
99+
{
100+
"spokenForm": f"{complex_actions['swapTargets']} <target 1> {swap_connective} <target 2>",
101+
"description": "Swap <target 1> with <target 2>",
102+
},
103+
{
104+
"spokenForm": f"{complex_actions['swapTargets']} {swap_connective} <target>",
105+
"description": "Swap selection with <target>",
106+
},
107+
],
108+
}
109+
)
110+
111+
if "applyFormatter" in complex_actions:
112+
items.append(
113+
{
114+
"id": "applyFormatter",
115+
"type": "action",
116+
"variations": [
117+
{
118+
"spokenForm": f"{complex_actions.get('applyFormatter')} <formatter> at <target>",
119+
"description": "Reformat <target> as <formatter>",
120+
}
121+
],
122+
}
123+
)
124+
125+
if "callAsFunction" in complex_actions:
126+
items.append(
127+
{
128+
"id": "callAsFunction",
129+
"type": "action",
130+
"variations": [
131+
{
132+
"spokenForm": f"{complex_actions['callAsFunction']} <target>",
133+
"description": "Call <target> on selection",
134+
},
135+
{
136+
"spokenForm": f"{complex_actions['callAsFunction']} <target 1> on <target 2>",
137+
"description": "Call <target 1> on <target 2>",
138+
},
139+
],
140+
}
141+
)
142+
143+
if "wrapWithPairedDelimiter" in complex_actions:
144+
items.append(
145+
{
146+
"id": "wrapWithPairedDelimiter",
147+
"type": "action",
148+
"variations": [
149+
{
150+
"spokenForm": f"<pair> {complex_actions['wrapWithPairedDelimiter']} <target>",
151+
"description": "Wrap <target> with <pair>",
152+
}
153+
],
154+
}
155+
)
156+
157+
if "rewrap" in complex_actions:
158+
items.append(
159+
{
160+
"id": "rewrap",
161+
"type": "action",
162+
"variations": [
163+
{
164+
"spokenForm": f"<pair> {complex_actions['rewrap']} <target>",
165+
"description": "Rewrap <target> with <pair>",
166+
}
167+
],
168+
}
169+
)
170+
171+
return items

cursorless-talon/src/cheatsheet/sections/compound_targets.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ..get_list import get_raw_list, get_spoken_form_from_list
1+
from ..get_list import ListItemDescriptor, get_raw_list, get_spoken_form_from_list
22

33
FORMATTERS = {
44
"rangeExclusive": lambda start, end: f"between {start} and {end}",
@@ -9,32 +9,42 @@
99
}
1010

1111

12-
def get_compound_targets():
12+
def get_compound_targets() -> list[ListItemDescriptor]:
1313
list_connective_term = get_spoken_form_from_list(
1414
"list_connective", "listConnective"
1515
)
1616
vertical_range_term = get_spoken_form_from_list("range_type", "verticalRange")
1717

18-
return [
19-
{
20-
"id": "listConnective",
21-
"type": "compoundTargetConnective",
22-
"variations": [
23-
{
24-
"spokenForm": f"<target 1> {list_connective_term} <target 2>",
25-
"description": "<target 1> and <target 2>",
26-
},
27-
],
28-
},
29-
*[
18+
items: list[ListItemDescriptor] = []
19+
20+
if list_connective_term:
21+
items.append(
22+
{
23+
"id": "listConnective",
24+
"type": "compoundTargetConnective",
25+
"variations": [
26+
{
27+
"spokenForm": f"<target 1> {list_connective_term} <target 2>",
28+
"description": "<target 1> and <target 2>",
29+
},
30+
],
31+
}
32+
)
33+
34+
items.extend(
35+
[
3036
get_entry(spoken_form, id)
3137
for spoken_form, id in get_raw_list("range_connective").items()
32-
],
33-
get_entry(vertical_range_term, "verticalRange"),
34-
]
38+
]
39+
)
40+
41+
if vertical_range_term:
42+
items.append(get_entry(vertical_range_term, "verticalRange"))
43+
44+
return items
3545

3646

37-
def get_entry(spoken_form, id):
47+
def get_entry(spoken_form, id) -> ListItemDescriptor:
3848
formatter = FORMATTERS[id]
3949

4050
return {

cursorless-talon/src/cheatsheet/sections/destinations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from ..get_list import get_raw_list
1+
from ..get_list import ListItemDescriptor, get_raw_list
22

33

4-
def get_destinations():
4+
def get_destinations() -> list[ListItemDescriptor]:
55
insertion_modes = {
66
**{p: "to" for p in get_raw_list("insertion_mode_to")},
77
**get_raw_list("insertion_mode_before_after"),

0 commit comments

Comments
 (0)