Skip to content

Commit d0803ac

Browse files
Handle multiple targets per scope
1 parent 8440a37 commit d0803ac

File tree

3 files changed

+20179
-8623
lines changed

3 files changed

+20179
-8623
lines changed

packages/cursorless-org-docs/scripts/prepare-assets.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@ import {
66
import * as fs from "node:fs";
77
import * as path from "node:path";
88

9-
interface Scope {
10-
content?: string;
11-
removal?: string;
12-
domain?: string;
13-
insertionDelimiter?: string;
14-
}
15-
169
interface Fixture {
1710
name: string;
1811
facet: string;
@@ -21,6 +14,17 @@ interface Fixture {
2114
scopes: Scope[];
2215
}
2316

17+
interface Scope {
18+
domain?: string;
19+
targets: Target[];
20+
}
21+
22+
interface Target {
23+
content?: string;
24+
removal?: string;
25+
insertionDelimiter?: string;
26+
}
27+
2428
const fixtures: Fixture[] = [];
2529

2630
for (const test of getScopeTestPaths()) {
@@ -48,23 +52,25 @@ function parseTest(test: ScopeTestPath) {
4852
const lines = fixture.substring(delimiterIndex + 4).split(/\n/);
4953
const scopes: Scope[] = [];
5054
const unprocessedTypes: string[] = [];
51-
let currentScopeIndex = "";
52-
let currentScope: Scope = {};
55+
let currentScopeIndex = "1";
56+
let currentTargetIndex = "1";
57+
let currentTarget: Target = {};
58+
let currentScope: Scope = { targets: [currentTarget] };
5359

5460
function processLine(type: string, value: string) {
5561
switch (type) {
62+
case "Domain":
63+
currentScope.domain = value;
64+
break;
5665
case "Content":
5766
case "Range":
58-
currentScope.content = value;
67+
currentTarget.content = value;
5968
break;
6069
case "Removal":
61-
currentScope.removal = value;
62-
break;
63-
case "Domain":
64-
currentScope.domain = value;
70+
currentTarget.removal = value;
6571
break;
6672
case "Insertion delimiter":
67-
currentScope.insertionDelimiter = value.substring(1, value.length - 1);
73+
currentTarget.insertionDelimiter = value.substring(1, value.length - 1);
6874
break;
6975
case "Leading delimiter":
7076
case "Leading delimiter: Content":
@@ -97,17 +103,16 @@ function parseTest(test: ScopeTestPath) {
97103

98104
const { scopeIndex, targetIndex, type, value } = parsedLine;
99105

100-
if (targetIndex != null) {
101-
// TODO: handle target index fixtures
102-
return;
103-
}
104-
105-
if (scopeIndex != null && scopeIndex !== currentScopeIndex) {
106-
if (currentScopeIndex !== "") {
107-
scopes.push(currentScope);
108-
}
106+
if (scopeIndex !== currentScopeIndex) {
107+
scopes.push(currentScope);
109108
currentScopeIndex = scopeIndex;
110-
currentScope = {};
109+
currentTargetIndex = "1";
110+
currentTarget = {};
111+
currentScope = { targets: [currentTarget] };
112+
} else if (targetIndex != null && targetIndex !== currentTargetIndex) {
113+
currentTargetIndex = targetIndex;
114+
currentTarget = {};
115+
currentScope.targets.push(currentTarget);
111116
}
112117

113118
if (value == null) {
@@ -125,9 +130,7 @@ function parseTest(test: ScopeTestPath) {
125130
processLine(type, value);
126131
}
127132

128-
if (currentScope != null) {
129-
scopes.push(currentScope);
130-
}
133+
scopes.push(currentScope);
131134

132135
const result: Fixture = {
133136
name: test.name,
@@ -158,7 +161,7 @@ function parseLine(line: string) {
158161
};
159162
}
160163
return {
161-
scopeIndex: undefined,
164+
scopeIndex: "1",
162165
targetIndex: undefined,
163166
type: header,
164167
};

packages/cursorless-org-docs/src/docs/user/languages/components/ScopeVisualizer.tsx

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@ import { Code, type Highlight } from "./Code";
55

66
type RangeType = "content" | "removal";
77

8-
interface Scope {
9-
content: string;
10-
removal?: string;
11-
domain?: string;
12-
insertionDelimiter?: string;
13-
}
14-
158
interface Fixture {
169
name: string;
1710
facet: string;
@@ -20,6 +13,17 @@ interface Fixture {
2013
scopes: Scope[];
2114
}
2215

16+
interface Scope {
17+
domain?: string;
18+
targets: Target[];
19+
}
20+
21+
interface Target {
22+
content: string;
23+
removal?: string;
24+
insertionDelimiter?: string;
25+
}
26+
2327
const scopeTests = scopeTestsExport as Fixture[];
2428

2529
interface Props {
@@ -63,42 +67,45 @@ function renderFixture(
6367
renderWhitespace: boolean,
6468
) {
6569
const highlights: Highlight[] = [];
66-
6770
let previousRange: Range | undefined;
6871

6972
for (const scope of fixture.scopes) {
70-
const conciseRange =
73+
const conciseRanges =
7174
rangeType === "content"
72-
? scope.content
73-
: (scope.removal ?? scope.content);
74-
let range = Range.fromConcise(conciseRange);
75+
? scope.targets.map((t) => t.content)
76+
: scope.targets.map((t) => t.removal ?? t.content);
77+
const ranges = conciseRanges.map((r) => Range.fromConcise(r));
7578

76-
if (scope.domain != null && scope.domain !== conciseRange) {
79+
if (scope.domain != null && conciseRanges.some((r) => r !== scope.domain)) {
7780
highlights.push({
7881
type: "domain",
7982
range: Range.fromConcise(scope.domain),
8083
});
8184
}
8285

83-
if (previousRange != null) {
84-
const intersection = previousRange.intersection(range);
86+
for (const r of ranges) {
87+
let range = r;
8588

86-
if (intersection != null && !intersection.isEmpty) {
87-
highlights.push({
88-
type: rangeType,
89-
range: intersection,
90-
});
89+
if (previousRange != null) {
90+
const intersection = previousRange.intersection(range);
9191

92-
range = new Range(intersection.end, range.end);
92+
if (intersection != null && !intersection.isEmpty) {
93+
highlights.push({
94+
type: rangeType,
95+
range: intersection,
96+
});
97+
98+
range = new Range(intersection.end, range.end);
99+
}
93100
}
94-
}
95101

96-
highlights.push({
97-
type: rangeType,
98-
range,
99-
});
102+
highlights.push({
103+
type: rangeType,
104+
range,
105+
});
100106

101-
previousRange = range;
107+
previousRange = range;
108+
}
102109
}
103110

104111
return (

0 commit comments

Comments
 (0)