Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/app-vscode/src/createScopeVisualizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import type {
ScopeProvider,
ScopeType,
} from "@cursorless/lib-common";
import { createVscodeScopeVisualizer } from "./ide/vscode/VSCodeScopeVisualizer";
import { isPseudoScope } from "@cursorless/lib-common";
import type { VscodeScopeVisualizer } from "./ide/vscode/VSCodeScopeVisualizer";
import { createVscodeScopeVisualizer } from "./ide/vscode/VSCodeScopeVisualizer";
import type {
ScopeVisualizer,
ScopeVisualizerListener,
Expand All @@ -24,6 +25,12 @@ export function createScopeVisualizer(

return {
start(scopeType: ScopeType, visualizationType: VisualizationType) {
if (isPseudoScope(scopeType)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow interior scopes to be visualized

When the requested scope is {type: "interior"}, this guard now throws because isPseudoScope includes interior in pseudoScopes. Unlike instance/className/functionName, interior has a real handler (ScopeHandlerFactoryImpl has a dedicated case "interior" backed by language @interior captures), so cursorless.showScopeVisualizer for interior content/removal no longer works for custom spoken forms or contributor debugging even though the renderer can handle it. Exclude interior from this visualizer guard and only reject pseudo scopes without handlers.

Useful? React with 👍 / 👎.

throw new Error(
`Can't visualize pseudo scopes like '${scopeType.type}'`,
);
}

scopeVisualizer?.dispose();
scopeVisualizer = createVscodeScopeVisualizer(
ide,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,7 @@ export const simpleScopeTypeTypes = [
"interior",
] as const;

export function isSimpleScopeType(
scopeType: ScopeType,
): scopeType is SimpleScopeType {
return (simpleScopeTypeTypes as readonly string[]).includes(scopeType.type);
}
const simpleScopeTypeTypesSet = new Set(simpleScopeTypeTypes);

export type SimpleScopeTypeType = (typeof simpleScopeTypeTypes)[number];

Expand All @@ -226,6 +222,16 @@ export const pseudoScopes = new Set<SimpleScopeTypeType>([
"functionName",
]);

export function isSimpleScopeType(
scopeType: ScopeType,
): scopeType is SimpleScopeType {
return (simpleScopeTypeTypesSet as Set<string>).has(scopeType.type);
}

export function isPseudoScope(scopeType: ScopeType): boolean {
return isSimpleScopeType(scopeType) && pseudoScopes.has(scopeType.type);
}

export interface SimpleScopeType {
type: SimpleScopeTypeType;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { pseudoScopes, UnsupportedScopeError } from "@cursorless/lib-common";
import type { IDE, ScopeType } from "@cursorless/lib-common";
import { isPseudoScope, UnsupportedScopeError } from "@cursorless/lib-common";
import type { LanguageDefinitions } from "../../../languages/LanguageDefinitions";
import {
BoundedNonWhitespaceSequenceScopeHandler,
Expand Down Expand Up @@ -139,8 +139,8 @@ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory {
return ConditionalScopeHandler.maybeCreate(this, scopeType, languageId);
default:
// Pseudoscopes are handled separately in their own modifiers.
if (pseudoScopes.has(scopeType.type)) {
throw new Error(`Unexpected scope type '${scopeType.type}'`);
if (isPseudoScope(scopeType)) {
throw new Error(`Unexpected pseudo scope type '${scopeType.type}'`);
}
return this.languageDefinitions
.get(languageId)
Expand Down
11 changes: 5 additions & 6 deletions packages/lib-engine/src/scopeProviders/ScopeInfoProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
SurroundingPairScopeType,
} from "@cursorless/lib-common";
import {
pseudoScopes,
isPseudoScope,
simpleScopeTypeTypes,
surroundingPairNames,
} from "@cursorless/lib-common";
Expand Down Expand Up @@ -67,11 +67,10 @@ export class ScopeInfoProvider {
private updateScopeTypeInfos(): void {
const scopeTypes: ScopeType[] = [
...simpleScopeTypeTypes
// Ignore instance pseudo-scope because it's not really a scope
.filter((scopeTypeType) => !pseudoScopes.has(scopeTypeType))
.map((scopeTypeType) => ({
type: scopeTypeType,
})),
// Create simple scope types from simple scope type types
.map((scopeTypeType) => ({ type: scopeTypeType }))
// Ignore pseudo-scope because it's not really a scope
.filter((scopeType) => !isPseudoScope(scopeType)),

...surroundingPairNames.map(
(surroundingPairName): SurroundingPairScopeType => ({
Expand Down
11 changes: 9 additions & 2 deletions packages/lib-tutorial/src/setupStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,15 @@ export async function setupStep(
throw new Error("No current tutorial found");
}

const { initialState: snapshot, languageId = "plaintext" } =
currentTutorial.steps[state.stepNumber];
const step = currentTutorial.steps[state.stepNumber];

if (step == null) {
throw new Error(
`No tutorial step found for step number ${state.stepNumber}`,
);
}

const { initialState: snapshot, languageId = "plaintext" } = step;

if (snapshot == null) {
return { editor, highlightRanges: [] };
Expand Down
Loading