Skip to content

Commit 6b8a2ea

Browse files
Extract calculate highlights into separate file
1 parent beb38fb commit 6b8a2ea

File tree

4 files changed

+84
-79
lines changed

4 files changed

+84
-79
lines changed

packages/cursorless-org-docs/src/docs/user/languages/components/Code.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
.code-container {
2525
position: relative;
2626
width: 100%;
27+
min-height: 50px;
2728
counter-reset: line;
2829
}
2930

3031
.code-container .line {
31-
margin-left: 1.5rem;
3232
position: relative;
33+
margin-left: 1.5rem;
3334
}
3435

3536
.code-container .line::before {

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

Lines changed: 4 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import {
2-
Range,
32
serializeScopeType,
4-
sortRanges,
53
type ScopeSupportFacetInfo,
64
type ScopeTypeType,
75
} from "@cursorless/common";
86
import { usePluginData } from "@docusaurus/useGlobalData";
97
import React, { useState } from "react";
10-
import { Code, type Highlight } from "./Code";
8+
import { calculateHighlights } from "./calculateHighlights";
9+
import { Code } from "./Code";
1110
import { H2, H3, H4 } from "./Header";
1211
import "./ScopeSupport.css";
13-
import type { FacetValue, Fixture, ScopeTests } from "./types";
12+
import type { FacetValue, Fixture, RangeType, ScopeTests } from "./types";
1413
import {
1514
getFacetInfo,
1615
isScopeInternal,
@@ -19,8 +18,6 @@ import {
1918
prettifyScopeType,
2019
} from "./util";
2120

22-
type RangeType = "content" | "removal";
23-
2421
interface Scopes {
2522
public: Scope[];
2623
internal: Scope[];
@@ -138,7 +135,7 @@ function renderFacet(
138135
key={fixture.name}
139136
languageId={languageId}
140137
renderWhitespace={renderWhitespace}
141-
highlights={getHighlights(fixture, rangeType)}
138+
highlights={calculateHighlights(fixture, rangeType)}
142139
>
143140
{fixture.code}
144141
</Code>
@@ -147,77 +144,6 @@ function renderFacet(
147144
);
148145
}
149146

150-
function getHighlights(fixture: Fixture, rangeType: RangeType): Highlight[] {
151-
const highlights: Highlight[] = [];
152-
const domainRanges: Range[] = [];
153-
154-
for (const scope of fixture.scopes) {
155-
const conciseRanges =
156-
rangeType === "content"
157-
? scope.targets.map((t) => t.content)
158-
: scope.targets.map((t) => t.removal ?? t.content);
159-
const ranges = sortRanges(conciseRanges.map((r) => Range.fromConcise(r)));
160-
161-
if (scope.domain != null && !conciseRanges.includes(scope.domain)) {
162-
domainRanges.push(Range.fromConcise(scope.domain));
163-
}
164-
165-
for (const r of ranges) {
166-
let range = r;
167-
168-
const overlap = highlights
169-
.map((h) => getOverlap(h.range, range))
170-
.find((o) => o != null);
171-
172-
if (overlap != null) {
173-
highlights.push({
174-
type: rangeType,
175-
range: overlap,
176-
});
177-
range = new Range(overlap.end, range.end);
178-
}
179-
180-
highlights.push({
181-
type: rangeType,
182-
range,
183-
});
184-
}
185-
}
186-
187-
for (const range of domainRanges) {
188-
if (highlights.every((h) => !hasOverlap(h.range, range))) {
189-
highlights.push({
190-
type: "domain",
191-
range,
192-
});
193-
}
194-
}
195-
196-
if (
197-
highlights.some((h) => highlights.some((o) => hasOverlap(h.range, o.range)))
198-
) {
199-
console.error("Overlapping highlights detected:");
200-
console.error(fixture);
201-
console.error(highlights);
202-
}
203-
204-
return highlights;
205-
}
206-
207-
function hasOverlap(a: Range, b: Range): boolean {
208-
return getOverlap(a, b) != null;
209-
}
210-
211-
function getOverlap(a: Range, b: Range): Range | null {
212-
const intersection = a.intersection(b);
213-
return intersection != null &&
214-
!intersection.isEmpty &&
215-
!a.contains(b) &&
216-
!b.contains(a)
217-
? intersection
218-
: null;
219-
}
220-
221147
function getScopeFixtures(scopeTests: ScopeTests, languageId: string): Scopes {
222148
const languageIds = new Set<string>(
223149
scopeTests.imports[languageId] ?? [languageId],
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Range, sortRanges } from "@cursorless/common";
2+
import { type Highlight } from "./Code";
3+
import type { Fixture, RangeType } from "./types";
4+
5+
export function calculateHighlights(
6+
fixture: Fixture,
7+
rangeType: RangeType,
8+
): Highlight[] {
9+
const highlights: Highlight[] = [];
10+
const domainRanges: Range[] = [];
11+
12+
for (const scope of fixture.scopes) {
13+
const conciseRanges =
14+
rangeType === "content"
15+
? scope.targets.map((t) => t.content)
16+
: scope.targets.map((t) => t.removal ?? t.content);
17+
const ranges = sortRanges(conciseRanges.map((r) => Range.fromConcise(r)));
18+
19+
if (scope.domain != null && !conciseRanges.includes(scope.domain)) {
20+
domainRanges.push(Range.fromConcise(scope.domain));
21+
}
22+
23+
for (const r of ranges) {
24+
let range = r;
25+
26+
const overlap = highlights
27+
.map((h) => getOverlap(h.range, range))
28+
.find((o) => o != null);
29+
30+
if (overlap != null) {
31+
highlights.push({
32+
type: rangeType,
33+
range: overlap,
34+
});
35+
range = new Range(overlap.end, range.end);
36+
}
37+
38+
highlights.push({
39+
type: rangeType,
40+
range,
41+
});
42+
}
43+
}
44+
45+
for (const range of domainRanges) {
46+
if (highlights.every((h) => !hasOverlap(h.range, range))) {
47+
highlights.push({
48+
type: "domain",
49+
range,
50+
});
51+
}
52+
}
53+
54+
if (
55+
highlights.some((h) => highlights.some((o) => hasOverlap(h.range, o.range)))
56+
) {
57+
console.error("Overlapping highlights detected:");
58+
console.error(fixture);
59+
console.error(highlights);
60+
}
61+
62+
return highlights;
63+
}
64+
65+
function hasOverlap(a: Range, b: Range): boolean {
66+
return getOverlap(a, b) != null;
67+
}
68+
69+
function getOverlap(a: Range, b: Range): Range | null {
70+
const intersection = a.intersection(b);
71+
return intersection != null &&
72+
!intersection.isEmpty &&
73+
!a.contains(b) &&
74+
!b.contains(a)
75+
? intersection
76+
: null;
77+
}

packages/cursorless-org-docs/src/docs/user/languages/components/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
PlaintextScopeSupportFacet,
44
} from "@cursorless/common";
55

6+
export type RangeType = "content" | "removal";
67
export type FacetValue = ScopeSupportFacet | PlaintextScopeSupportFacet;
78

89
export interface ScopeTests {

0 commit comments

Comments
 (0)