-
-
Notifications
You must be signed in to change notification settings - Fork 94
Expand file tree
/
Copy pathcaptureNames.ts
More file actions
108 lines (89 loc) · 3.14 KB
/
Copy pathcaptureNames.ts
File metadata and controls
108 lines (89 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { pseudoScopeTypes, simpleScopeTypeTypes } from "@cursorless/lib-common";
const scopeCaptureNames = simpleScopeTypeTypes.filter(
(s) => !pseudoScopeTypes.has(s),
);
export type ScopeCaptureName = (typeof scopeCaptureNames)[number];
const wildcard = "_";
const captureNames = [...scopeCaptureNames, wildcard];
const positionRelationships = ["prefix", "leading", "trailing"];
const positionSuffixes = [
"startOf",
"endOf",
"start.startOf",
"start.endOf",
"end.startOf",
"end.endOf",
];
const rangeRelationships = [
"domain",
"removal",
"iteration",
"iteration.domain",
];
const rangeSuffixes = [
"start",
"end",
"start.startOf",
"start.endOf",
"end.startOf",
"end.endOf",
];
const allowedCaptures = new Set<string>();
for (const captureName of captureNames) {
// Wildcard is not allowed by itself without a relationship
if (captureName !== wildcard) {
// eg: statement
allowedCaptures.add(captureName);
// eg: statement.start | statement.start.endOf
for (const suffix of rangeSuffixes) {
allowedCaptures.add(`${captureName}.${suffix}`);
}
}
for (const relationship of positionRelationships) {
// eg: statement.leading
allowedCaptures.add(`${captureName}.${relationship}`);
for (const suffix of positionSuffixes) {
// eg: statement.leading.endOf
allowedCaptures.add(`${captureName}.${relationship}.${suffix}`);
}
}
for (const relationship of rangeRelationships) {
// eg: statement.domain
allowedCaptures.add(`${captureName}.${relationship}`);
for (const suffix of rangeSuffixes) {
// eg: statement.domain.start | statement.domain.start.endOf
allowedCaptures.add(`${captureName}.${relationship}.${suffix}`);
}
}
}
const normalizedCaptureNamesMap = new Map<string, string>();
const normalizedCaptureIndexMap = new Map<string, number>();
const captureNameIndex = Object.fromEntries(captureNames.map((n, i) => [n, i]));
for (const captureName of allowedCaptures) {
const normalizedCaptureName = normalizeCaptureName(captureName);
normalizedCaptureNamesMap.set(captureName, normalizedCaptureName);
const scopeName = getScopeName(captureName);
const index = captureNameIndex[scopeName];
if (index == null) {
throw new Error(`No scope index for capture name ${captureName}`);
}
normalizedCaptureIndexMap.set(captureName, index);
}
function normalizeCaptureName(name: string): string {
return name.replace(/(\.(start|end))?(\.(startOf|endOf))?$/u, "");
}
// eg: for `statement.start.endOf`, returns `statement`
function getScopeName(captureName: string): string {
return /^(private\.[^.]*|[^.]*)/u.exec(captureName)![0];
}
export function isCaptureAllowed(captureName: string): boolean {
return allowedCaptures.has(captureName);
}
// Capture names missing normalized name can be things like '@_dummy'
export function getNormalizedCaptureName(captureName: string): string {
return normalizedCaptureNamesMap.get(captureName) ?? captureName;
}
// Capture names missing normalized index can be things like '@_dummy'
export function getNormalizedCaptureIndex(captureName: string): number {
return normalizedCaptureIndexMap.get(captureName) ?? -1;
}