Skip to content

Commit 91b58ff

Browse files
committed
Live-updating regex scopes
1 parent 3e8b231 commit 91b58ff

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

packages/cursorless-vscode/src/extension.ts

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
} from "./ScopeVisualizerCommandApi";
4444
import { StatusBarItem } from "./StatusBarItem";
4545
import { vscodeApi } from "./vscodeApi";
46+
import { revisualizeOnCustomRegexChange } from "./revisualizeOnCustomRegexChange";
4647

4748
/**
4849
* Extension entrypoint called by VSCode on Cursorless startup.
@@ -97,6 +98,9 @@ export async function activate(
9798
const statusBarItem = StatusBarItem.create("cursorless.showQuickPick");
9899
const keyboardCommands = KeyboardCommands.create(context, statusBarItem);
99100
const scopeVisualizer = createScopeVisualizer(normalizedIde, scopeProvider);
101+
context.subscriptions.push(
102+
revisualizeOnCustomRegexChange(scopeVisualizer, scopeProvider),
103+
);
100104

101105
ScopeTreeProvider.create(
102106
vscodeApi,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
Disposable,
3+
Disposer,
4+
ScopeProvider,
5+
ScopeTypeInfo,
6+
} from "@cursorless/common";
7+
import {
8+
ScopeVisualizer,
9+
VisualizationType,
10+
} from "./ScopeVisualizerCommandApi";
11+
import { isEqual } from "lodash";
12+
13+
/**
14+
* Attempts to ensure that the scope visualizer is still visualizing the same
15+
* scope type after the user changes one of their custom regexes. Because custom
16+
* regexes don't have a unique identifier, we have to do some guesswork to
17+
* figure out which custom regex the user changed. This function look for a
18+
* custom regex with the same spoken form as the one that was changed, and if it
19+
* finds one, it starts visualizing that one instead.
20+
*
21+
* @param scopeVisualizer The scope visualizer to listen to
22+
* @param scopeProvider Provides scope information
23+
* @returns A {@link Disposable} which will stop the callback from running
24+
*/
25+
export function revisualizeOnCustomRegexChange(
26+
scopeVisualizer: ScopeVisualizer,
27+
scopeProvider: ScopeProvider,
28+
): Disposable {
29+
let currentRegexScopeInfo: ScopeTypeInfo | undefined;
30+
let currentVisualizationType: VisualizationType | undefined;
31+
32+
return new Disposer(
33+
scopeVisualizer.onDidChangeScopeType((scopeType, visualizationType) => {
34+
currentRegexScopeInfo =
35+
scopeType?.type === "customRegex"
36+
? scopeProvider.getScopeInfo(scopeType)
37+
: undefined;
38+
currentVisualizationType = visualizationType;
39+
}),
40+
41+
scopeProvider.onDidChangeScopeInfo((scopeInfos) => {
42+
if (
43+
currentRegexScopeInfo != null &&
44+
!scopeInfos.some((scopeInfo) =>
45+
isEqual(scopeInfo.scopeType, currentRegexScopeInfo!.scopeType),
46+
)
47+
) {
48+
const replacement = scopeInfos.find(
49+
(scopeInfo) =>
50+
scopeInfo.scopeType.type === "customRegex" &&
51+
isEqual(scopeInfo.spokenForm, currentRegexScopeInfo!.spokenForm),
52+
);
53+
if (replacement != null) {
54+
scopeVisualizer.start(
55+
replacement.scopeType,
56+
currentVisualizationType!,
57+
);
58+
}
59+
}
60+
}),
61+
);
62+
}

0 commit comments

Comments
 (0)