Skip to content

Commit db385da

Browse files
Cleanup
1 parent 71b7b6c commit db385da

File tree

5 files changed

+47
-47
lines changed

5 files changed

+47
-47
lines changed

packages/common/src/util/regex.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,20 @@ function makeCache<T, U>(func: (arg: T) => U) {
3030
export const rightAnchored = makeCache(_rightAnchored);
3131
export const leftAnchored = makeCache(_leftAnchored);
3232

33+
export function matchAllIterator(text: string, regex: RegExp) {
34+
// Reset the regex to start at the beginning of string, in case the regex has
35+
// been used before.
36+
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#finding_successive_matches
37+
regex.lastIndex = 0;
38+
return text.matchAll(regex);
39+
}
40+
3341
export function matchAll<T>(
3442
text: string,
3543
regex: RegExp,
3644
mapfn: (v: RegExpMatchArray, k: number) => T,
3745
) {
38-
// Reset the regex to start at the beginning of string, in case the regex has
39-
// been used before.
40-
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#finding_successive_matches
41-
regex.lastIndex = 0;
42-
return Array.from(text.matchAll(regex), mapfn);
46+
return Array.from(matchAllIterator(text, regex), mapfn);
4347
}
4448

4549
export function testRegex(regex: RegExp, text: string): boolean {

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/RangeIterator.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,26 @@ import type { Range } from "@cursorless/common";
22

33
/**
44
* An iterator that allows for efficient lookup of ranges that contain a search item.
5+
* The items must be sorted in document order.
56
*/
67
export class RangeIterator<T extends { range: Range }> {
78
private index = 0;
89

9-
constructor(
10-
public items: T[],
11-
sortItems = false,
12-
) {
13-
if (sortItems) {
14-
this.items.sort((a, b) => a.range.start.compareTo(b.range.start));
15-
}
16-
}
10+
/**
11+
* @param items The items to iterate over. Must be sorted in document order.
12+
*/
13+
constructor(public items: T[]) {}
1714

1815
contains(searchItem: Range): boolean {
1916
return this.advance(searchItem);
2017
}
2118

2219
getContaining(searchItem: Range): T | undefined {
23-
if (!this.advance(searchItem)) {
24-
return undefined;
20+
if (this.advance(searchItem)) {
21+
return this.items[this.index];
2522
}
2623

27-
return this.items[this.index];
24+
return undefined;
2825
}
2926

3027
private advance(searchItem: Range): boolean {

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/getDelimiterOccurrences.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { matchAll, Range, type TextDocument } from "@cursorless/common";
1+
import { matchAllIterator, Range, type TextDocument } from "@cursorless/common";
22
import type { LanguageDefinition } from "../../../../languages/LanguageDefinition";
3+
import type { QueryCapture } from "../../../../languages/TreeSitterQuery/QueryCapture";
34
import { getDelimiterRegex } from "./getDelimiterRegex";
45
import { RangeIterator } from "./RangeIterator";
56
import type { DelimiterOccurrence, IndividualDelimiter } from "./types";
@@ -21,20 +22,14 @@ export function getDelimiterOccurrences(
2122
return [];
2223
}
2324

24-
const delimiterRegex = getDelimiterRegex(individualDelimiters);
25-
2625
const captures = languageDefinition?.getMultipleCaptures(document, [
2726
"disqualifyDelimiter",
2827
"textFragment",
2928
]);
30-
const disqualifyDelimitersIterator = new RangeIterator(
31-
captures?.disqualifyDelimiter ?? [],
32-
true, // Sort items
33-
);
34-
const textFragmentsIterator = new RangeIterator(
35-
captures?.textFragment ?? [],
36-
true,
29+
const disqualifyDelimitersIterator = createRangeIterator(
30+
captures?.disqualifyDelimiter,
3731
);
32+
const textFragmentsIterator = createRangeIterator(captures?.textFragment);
3833

3934
const delimiterTextToDelimiterInfoMap = Object.fromEntries(
4035
individualDelimiters.map((individualDelimiter) => [
@@ -52,20 +47,36 @@ export function getDelimiterOccurrences(
5247
return textFragmentsIterator.getContaining(range)?.range;
5348
};
5449

55-
const text = document.getText();
50+
const matchIterator = matchAllIterator(
51+
document.getText(),
52+
getDelimiterRegex(individualDelimiters),
53+
);
54+
55+
const results: DelimiterOccurrence[] = [];
5656

57-
return matchAll(text, delimiterRegex, (match): DelimiterOccurrence => {
57+
for (const match of matchIterator) {
5858
const text = match[0];
5959
const range = new Range(
6060
document.positionAt(match.index!),
6161
document.positionAt(match.index! + text.length),
6262
);
6363

64-
return {
65-
delimiterInfo: delimiterTextToDelimiterInfoMap[text],
66-
isDisqualified: isDisqualified(range),
67-
textFragmentRange: getTextFragmentRange(range),
68-
range,
69-
};
70-
});
64+
if (!isDisqualified(range)) {
65+
results.push({
66+
delimiterInfo: delimiterTextToDelimiterInfoMap[text],
67+
textFragmentRange: getTextFragmentRange(range),
68+
range,
69+
});
70+
}
71+
}
72+
73+
return results;
74+
}
75+
76+
function createRangeIterator(
77+
captures: QueryCapture[] | undefined,
78+
): RangeIterator<QueryCapture> {
79+
const items = captures ?? [];
80+
items.sort((a, b) => a.range.start.compareTo(b.range.start));
81+
return new RangeIterator(items);
7182
}

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/getSurroundingPairOccurrences.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,10 @@ export function getSurroundingPairOccurrences(
2525
for (const occurrence of delimiterOccurrences) {
2626
const {
2727
delimiterInfo: { delimiterName, side, isSingleLine },
28-
isDisqualified,
2928
textFragmentRange,
3029
range,
3130
} = occurrence;
3231

33-
if (isDisqualified) {
34-
continue;
35-
}
36-
3732
let openingDelimiters = openingDelimiterOccurrences.get(delimiterName);
3833

3934
if (isSingleLine) {

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/types.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ export interface DelimiterOccurrence {
4848
*/
4949
range: Range;
5050

51-
/**
52-
* If `true`, this delimiter is disqualified from being considered as a
53-
* surrounding pair delimiter, because it has been tagged as such based on a
54-
* parse tree query.
55-
*/
56-
isDisqualified: boolean;
57-
5851
/**
5952
* If the delimiter is part of a text fragment, eg a string or comment, this
6053
* will be the range of the text fragment.

0 commit comments

Comments
 (0)