Skip to content

Commit 0479eea

Browse files
committed
Fixes; support custom regex spoken forms
1 parent fbb31f1 commit 0479eea

File tree

11 files changed

+74
-14
lines changed

11 files changed

+74
-14
lines changed

.vscode/launch.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,23 @@
156156
"!**/node_modules/**"
157157
]
158158
},
159+
{
160+
"name": "Update fixtures, unit tests only",
161+
"type": "node",
162+
"request": "launch",
163+
"program": "${workspaceFolder}/packages/test-harness/out/scripts/runUnitTestsOnly",
164+
"env": {
165+
"CURSORLESS_TEST": "true",
166+
"CURSORLESS_TEST_UPDATE_FIXTURES": "true",
167+
"CURSORLESS_REPO_ROOT": "${workspaceFolder}"
168+
},
169+
"outFiles": ["${workspaceFolder}/**/out/**/*.js"],
170+
"preLaunchTask": "${defaultBuildTask}",
171+
"resolveSourceMapLocations": [
172+
"${workspaceFolder}/**",
173+
"!**/node_modules/**"
174+
]
175+
},
159176
{
160177
"name": "Docusaurus start",
161178
"type": "node",

packages/cursorless-engine/src/generateSpokenForm/generateSpokenForm.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ suite("Generate spoken forms", () => {
1616
getRecordedTestPaths().forEach(({ name, path }) =>
1717
test(name, () => runTest(path)),
1818
);
19+
20+
test("generate spoken form for custom regex", () => {
21+
const generator = new SpokenFormGenerator({
22+
...defaultSpokenFormMap,
23+
customRegex: { foo: ["bar"] },
24+
});
25+
26+
const spokenForm = generator.scopeType({
27+
type: "customRegex",
28+
regex: "foo",
29+
});
30+
31+
assert(spokenForm.type === "success");
32+
assert.equal(spokenForm.preferred, "bar");
33+
});
1934
});
2035

2136
async function runTest(file: string) {

packages/cursorless-engine/src/generateSpokenForm/generateSpokenForm.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,12 @@ function constructSpokenForms(component: SpokenFormComponent): string[] {
250250
}
251251

252252
if (Array.isArray(component)) {
253+
if (component.length === 0) {
254+
return [""];
255+
}
256+
253257
return cartesianProduct(component.map(constructSpokenForms)).map((words) =>
254-
words.join(" "),
258+
words.filter((word) => word.length !== 0).join(" "),
255259
);
256260
}
257261

packages/cursorless-engine/src/generateSpokenForm/primitiveTargetToSpokenForm.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ export class PrimitiveTargetSpokenFormGenerator {
209209
handleScopeType(scopeType: ScopeType): SpokenFormComponent {
210210
switch (scopeType.type) {
211211
case "oneOf":
212-
case "customRegex":
213212
case "switchStatementSubject":
214213
case "string":
215214
throw new NoSpokenFormError(`Scope type '${scopeType.type}'`);
@@ -221,15 +220,26 @@ export class PrimitiveTargetSpokenFormGenerator {
221220
}
222221
const pair = this.spokenFormMap.pairedDelimiter[scopeType.delimiter];
223222
if (scopeType.forceDirection != null) {
224-
const direction =
225-
scopeType.forceDirection === "left"
226-
? this.spokenFormMap.surroundingPairForceDirection.left
227-
: this.spokenFormMap.surroundingPairForceDirection.right;
228-
return `${direction} ${pair}`;
223+
return [
224+
this.spokenFormMap.surroundingPairForceDirection[
225+
scopeType.forceDirection
226+
],
227+
pair,
228+
];
229229
}
230230
return pair;
231231
}
232232

233+
case "customRegex":
234+
return (
235+
this.spokenFormMap.customRegex[scopeType.regex] ?? {
236+
type: "singleTerm",
237+
spokenForms: [],
238+
spokenFormType: "customRegex",
239+
id: scopeType.regex,
240+
}
241+
);
242+
233243
default:
234244
return this.spokenFormMap.simpleScopeTypeType[scopeType.type];
235245
}

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/customRegex/clearWhite.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ command:
99
scopeType: {type: customRegex, regex: '\p{Zs}+'}
1010
usePrePhraseSnapshot: true
1111
action: {name: clearAndSetSelection}
12-
spokenFormError: Scope type 'customRegex'
12+
spokenFormError: >-
13+
custom regex with id \p{Zs}+; please see
14+
https://www.cursorless.org/docs/user/customization/ for more information
1315
initialState:
1416
documentContents: "\" \""
1517
selections:

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/ordinalScopes/clearFirstPaint.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ command:
1111
length: 1
1212
usePrePhraseSnapshot: true
1313
action: {name: clearAndSetSelection}
14-
spokenFormError: Scope type 'customRegex'
14+
spokenFormError: >-
15+
custom regex with id [^\s"'`]+; please see
16+
https://www.cursorless.org/docs/user/customization/ for more information
1517
initialState:
1618
documentContents: aaa-bbb ccc-ddd eee-fff ggg-hhh
1719
selections:

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/ordinalScopes/clearFirstPaint2.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ command:
1111
length: 1
1212
usePrePhraseSnapshot: true
1313
action: {name: clearAndSetSelection}
14-
spokenFormError: Scope type 'customRegex'
14+
spokenFormError: >-
15+
custom regex with id [^\s"'`]+; please see
16+
https://www.cursorless.org/docs/user/customization/ for more information
1517
initialState:
1618
documentContents: aaa-bbb ccc-ddd eee-fff ggg-hhh
1719
selections:

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/ordinalScopes/clearLastPaint.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ command:
1111
length: 1
1212
usePrePhraseSnapshot: true
1313
action: {name: clearAndSetSelection}
14-
spokenFormError: Scope type 'customRegex'
14+
spokenFormError: >-
15+
custom regex with id [^\s"'`]+; please see
16+
https://www.cursorless.org/docs/user/customization/ for more information
1517
initialState:
1618
documentContents: aaa-bbb ccc-ddd eee-fff ggg-hhh
1719
selections:

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/ordinalScopes/clearLastPaint2.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ command:
1111
length: 1
1212
usePrePhraseSnapshot: true
1313
action: {name: clearAndSetSelection}
14-
spokenFormError: Scope type 'customRegex'
14+
spokenFormError: >-
15+
custom regex with id [^\s"'`]+; please see
16+
https://www.cursorless.org/docs/user/customization/ for more information
1517
initialState:
1618
documentContents: aaa-bbb ccc-ddd eee-fff ggg-hhh
1719
selections:

packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/selectionTypes/clearCustomRegex.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ command:
99
scopeType: {type: customRegex, regex: '[\w/_.]+'}
1010
usePrePhraseSnapshot: true
1111
action: {name: clearAndSetSelection}
12-
spokenFormError: Scope type 'customRegex'
12+
spokenFormError: >-
13+
custom regex with id [\w/_.]+; please see
14+
https://www.cursorless.org/docs/user/customization/ for more information
1315
initialState:
1416
documentContents: aa.bb/cc_dd123( )
1517
selections:

0 commit comments

Comments
 (0)