Skip to content

Commit 9b9e6ff

Browse files
committed
Use spoken forms for tree view
1 parent 44de631 commit 9b9e6ff

File tree

16 files changed

+556
-62
lines changed

16 files changed

+556
-62
lines changed

cursorless-talon/src/csv_overrides.py

+33-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections.abc import Container
44
from datetime import datetime
55
from pathlib import Path
6-
from typing import Optional
6+
from typing import Callable, Optional
77

88
from talon import Context, Module, actions, app, fs
99

@@ -32,6 +32,9 @@
3232
"""
3333

3434

35+
GetType = Callable[[str, str], str]
36+
37+
3538
def init_csv_and_watch_changes(
3639
filename: str,
3740
default_values: dict[str, dict[str, str]],
@@ -42,6 +45,7 @@ def init_csv_and_watch_changes(
4245
ctx: Context = Context(),
4346
no_update_file: bool = False,
4447
pluralize_lists: list[str] = [],
48+
get_type: Optional[GetType] = None,
4549
):
4650
"""
4751
Initialize a cursorless settings csv, creating it if necessary, and watch
@@ -106,6 +110,7 @@ def on_watch(path, flags):
106110
default_list_name,
107111
pluralize_lists,
108112
output_file_path,
113+
get_type,
109114
ctx,
110115
)
111116

@@ -128,6 +133,7 @@ def on_watch(path, flags):
128133
default_list_name,
129134
pluralize_lists,
130135
output_file_path,
136+
get_type,
131137
ctx,
132138
)
133139
else:
@@ -141,6 +147,7 @@ def on_watch(path, flags):
141147
default_list_name,
142148
pluralize_lists,
143149
output_file_path,
150+
get_type,
144151
ctx,
145152
)
146153

@@ -188,6 +195,7 @@ def update_dicts(
188195
default_list_name: Optional[str],
189196
pluralize_lists: list[str],
190197
output_file_path: Path,
198+
get_type: Optional[GetType],
191199
ctx: Context,
192200
):
193201
# Create map with all default values
@@ -214,29 +222,24 @@ def update_dicts(
214222

215223
# Convert result map back to result list
216224
results = {res["list"]: {} for res in results_map.values()}
217-
output_file_dict = {}
225+
output_file_entries = []
218226
for obj in results_map.values():
219227
value = obj["value"]
220228
key = obj["key"]
221-
if not is_removed(key):
222-
for k in key.split("|"):
223-
if value == "pasteFromClipboard" and k.endswith(" to"):
224-
# FIXME: This is a hack to work around the fact that the
225-
# spoken form of the `pasteFromClipboard` action used to be
226-
# "paste to", but now the spoken form is just "paste" and
227-
# the "to" is part of the positional target. Users who had
228-
# cursorless before this change would have "paste to" as
229-
# their spoken form and so would need to say "paste to to".
230-
k = k[:-3]
231-
results[obj["list"]][k.strip()] = value
232-
output_file_dict[value] = k.strip()
229+
spoken_forms = list(get_spoken_forms(value, key))
230+
for spoken_form in spoken_forms:
231+
results[obj["list"]][spoken_form] = value
232+
if get_type is not None and (entry_type := get_type(obj["list"], value)):
233+
output_file_entries.append(
234+
{"type": entry_type, "id": value, "spokenForms": spoken_forms}
235+
)
233236

234237
# Assign result to talon context list
235238
assign_lists_to_context(ctx, results, pluralize_lists)
236239

237240
with open(output_file_path, "w") as out:
238241
try:
239-
out.write(json.dumps(output_file_dict))
242+
out.write(json.dumps({"version": 0, "entries": output_file_entries}))
240243
except Exception:
241244
error_message = f"Error writing spoken form json {output_file_path}"
242245
print(error_message)
@@ -256,6 +259,21 @@ def assign_lists_to_context(
256259
ctx.lists[list_plural_name] = {pluralize(k): v for k, v in dict.items()}
257260

258261

262+
def get_spoken_forms(id: str, spoken_form: str):
263+
if not is_removed(spoken_form):
264+
for k in spoken_form.split("|"):
265+
if id == "pasteFromClipboard" and k.endswith(" to"):
266+
# FIXME: This is a hack to work around the fact that the
267+
# spoken form of the `pasteFromClipboard` action used to be
268+
# "paste to", but now the spoken form is just "paste" and
269+
# the "to" is part of the positional target. Users who had
270+
# cursorless before this change would have "paste to" as
271+
# their spoken form and so would need to say "paste to to".
272+
k = k[:-3]
273+
274+
yield k.strip()
275+
276+
259277
def update_file(
260278
path: Path,
261279
headers: list[str],

cursorless-talon/src/spoken_forms.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,15 @@ def update():
6464
handle_csv("target_connectives.csv"),
6565
handle_csv("modifiers.csv"),
6666
handle_csv("positions.csv"),
67-
handle_csv("paired_delimiters.csv"),
6867
handle_csv("special_marks.csv"),
6968
handle_csv("scope_visualizer.csv"),
7069
handle_csv("experimental/experimental_actions.csv"),
7170
handle_csv("experimental/miscellaneous.csv"),
71+
handle_csv("paired_delimiters.csv", get_type=lambda _1, _2: "pairedDelimiter"),
7272
handle_csv(
7373
"modifier_scope_types.csv",
7474
pluralize_lists=["scope_type"],
75+
get_type=get_type,
7576
),
7677
handle_csv(
7778
"experimental/wrapper_snippets.csv",
@@ -100,6 +101,7 @@ def update():
100101
allow_unknown_values=True,
101102
default_list_name="custom_regex_scope_type",
102103
pluralize_lists=["custom_regex_scope_type"],
104+
get_type=lambda _1, _2: "customRegex",
103105
),
104106
init_marks(
105107
spoken_forms["hat_styles.csv"]["hat_color"],
@@ -108,6 +110,10 @@ def update():
108110
]
109111

110112

113+
def get_type(list_name: str, id: str):
114+
return "simpleScopeTypeType" if list_name == "scope_type" else "pairedDelimiter"
115+
116+
111117
def on_watch(path, flags):
112118
if JSON_FILE.match(path):
113119
update()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Disposable } from "./ide.types";
2+
3+
export type PathChangeListener = () => void;
4+
5+
export interface FileSystem {
6+
watchDir(path: string, onDidChange: PathChangeListener): Disposable;
7+
}

packages/common/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export * from "./ide/types/Events";
3030
export * from "./ide/types/QuickPickOptions";
3131
export * from "./ide/types/events.types";
3232
export * from "./ide/types/Paths";
33+
export * from "./ide/types/FileSystem.types";
3334
export * from "./types/RangeExpansionBehavior";
3435
export * from "./types/InputBoxOptions";
3536
export * from "./types/Position";

packages/common/src/types/command/PartialTargetDescriptor.types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const simpleSurroundingPairNames = [
8080
"backtickQuotes",
8181
"curlyBrackets",
8282
"doubleQuotes",
83-
"escapedDoubleQuomes",
83+
"escapedDoubleQuotes",
8484
"escapedParentheses",
8585
"escapedSquareBrackets",
8686
"escapedSingleQuotes",
@@ -169,6 +169,12 @@ export const simpleScopeTypeTypes = [
169169
"command",
170170
] as const;
171171

172+
export function isSimpleScopeType(
173+
scopeType: ScopeType,
174+
): scopeType is SimpleScopeType {
175+
return simpleScopeTypeTypes.includes(scopeType.type as any);
176+
}
177+
172178
export type SimpleScopeTypeType = (typeof simpleScopeTypeTypes)[number];
173179

174180
export interface SimpleScopeType {

0 commit comments

Comments
 (0)