Skip to content

Commit

Permalink
Live-updating regex scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey committed Oct 27, 2023
1 parent a2c90ec commit 5ab3909
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/cursorless-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
import { KeyboardCommands } from "./keyboard/KeyboardCommands";
import { registerCommands } from "./registerCommands";
import { ReleaseNotes } from "./ReleaseNotes";
import { revisualizeOnCustomRegexChange } from "./revisualizeOnCustomRegexChange";
import { ScopeTreeProvider } from "./ScopeTreeProvider";
import {
ScopeVisualizer,
Expand Down Expand Up @@ -100,6 +101,9 @@ export async function activate(
const statusBarItem = StatusBarItem.create("cursorless.showQuickPick");
const keyboardCommands = KeyboardCommands.create(context, statusBarItem);
const scopeVisualizer = createScopeVisualizer(normalizedIde, scopeProvider);
context.subscriptions.push(
revisualizeOnCustomRegexChange(scopeVisualizer, scopeProvider),
);

new ScopeTreeProvider(
vscodeApi,
Expand Down
62 changes: 62 additions & 0 deletions packages/cursorless-vscode/src/revisualizeOnCustomRegexChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
Disposable,
ScopeProvider,
ScopeTypeInfo,
disposableFrom,
} from "@cursorless/common";
import { isEqual } from "lodash";
import {
ScopeVisualizer,
VisualizationType,
} from "./ScopeVisualizerCommandApi";

/**
* Attempts to ensure that the scope visualizer is still visualizing the same
* scope type after the user changes one of their custom regexes. Because custom
* regexes don't have a unique identifier, we have to do some guesswork to
* figure out which custom regex the user changed. This function look for a
* custom regex with the same spoken form as the one that was changed, and if it
* finds one, it starts visualizing that one instead.
*
* @param scopeVisualizer The scope visualizer to listen to
* @param scopeProvider Provides scope information
* @returns A {@link Disposable} which will stop the callback from running
*/
export function revisualizeOnCustomRegexChange(
scopeVisualizer: ScopeVisualizer,
scopeProvider: ScopeProvider,
): Disposable {
let currentRegexScopeInfo: ScopeTypeInfo | undefined;
let currentVisualizationType: VisualizationType | undefined;

return disposableFrom(
scopeVisualizer.onDidChangeScopeType((scopeType, visualizationType) => {
currentRegexScopeInfo =
scopeType?.type === "customRegex"
? scopeProvider.getScopeInfo(scopeType)
: undefined;
currentVisualizationType = visualizationType;
}),

scopeProvider.onDidChangeScopeInfo((scopeInfos) => {
if (
currentRegexScopeInfo != null &&
!scopeInfos.some((scopeInfo) =>
isEqual(scopeInfo.scopeType, currentRegexScopeInfo!.scopeType),
)
) {
const replacement = scopeInfos.find(
(scopeInfo) =>
scopeInfo.scopeType.type === "customRegex" &&
isEqual(scopeInfo.spokenForm, currentRegexScopeInfo!.spokenForm),
);
if (replacement != null) {
scopeVisualizer.start(
replacement.scopeType,
currentVisualizationType!,
);
}
}
}),
);
}

0 comments on commit 5ab3909

Please sign in to comment.