Skip to content

Commit 1c6435b

Browse files
committed
Scope info provider
1 parent 84d2f1d commit 1c6435b

24 files changed

+1081
-99
lines changed

packages/common/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export * from "./types/TextEditorOptions";
4444
export * from "./types/TextLine";
4545
export * from "./types/Token";
4646
export * from "./types/HatTokenMap";
47+
export * from "./types/ScopeProvider";
4748
export * from "./types/SpokenForm";
4849
export * from "./util/textFormatters";
4950
export * from "./types/snippet.types";

packages/cursorless-engine/src/api/ScopeProvider.ts renamed to packages/common/src/types/ScopeProvider.ts

+50-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import {
33
GeneralizedRange,
44
Range,
55
ScopeType,
6+
SpokenForm,
67
TextEditor,
7-
} from "@cursorless/common";
8+
} from "..";
89

910
export interface ScopeProvider {
1011
/**
@@ -75,6 +76,34 @@ export interface ScopeProvider {
7576
editor: TextEditor,
7677
scopeType: ScopeType,
7778
) => ScopeSupport;
79+
80+
/**
81+
* Registers a callback to be run when the scope support changes for the active
82+
* editor. The callback will be run immediately once with the current support
83+
* levels for the active editor.
84+
* @param callback The callback to run when the scope support changes
85+
* @returns A {@link Disposable} which will stop the callback from running
86+
*/
87+
onDidChangeScopeSupport: (callback: ScopeSupportEventCallback) => Disposable;
88+
89+
/**
90+
* Registers a callback to be run when the scope support changes for the active
91+
* editor. The callback will be run immediately once with the current support
92+
* levels for the active editor.
93+
* @param callback The callback to run when the scope support changes
94+
* @returns A {@link Disposable} which will stop the callback from running
95+
*/
96+
onDidChangeScopeInfo(callback: ScopeTypeInfoEventCallback): Disposable;
97+
98+
/**
99+
* Determine the level of support for the iteration scope of {@link scopeType}
100+
* in {@link editor}, as determined by its language id.
101+
* @param editor The editor to check
102+
* @param scopeType The scope type to check
103+
* @returns The level of support for the iteration scope of {@link scopeType}
104+
* in {@link editor}
105+
*/
106+
getScopeInfo: (scopeType: ScopeType) => ScopeTypeInfo;
78107
}
79108

80109
interface ScopeRangeConfigBase {
@@ -108,6 +137,26 @@ export type IterationScopeChangeEventCallback = (
108137
scopeRanges: IterationScopeRanges[],
109138
) => void;
110139

140+
export interface ScopeSupportInfo extends ScopeTypeInfo {
141+
support: ScopeSupport;
142+
iterationScopeSupport: ScopeSupport;
143+
}
144+
145+
export type ScopeSupportLevels = ScopeSupportInfo[];
146+
147+
export type ScopeSupportEventCallback = (
148+
supportLevels: ScopeSupportLevels,
149+
) => void;
150+
151+
export interface ScopeTypeInfo {
152+
scopeType: ScopeType;
153+
spokenForm: SpokenForm;
154+
humanReadableName: string;
155+
isLanguageSpecific: boolean;
156+
}
157+
158+
export type ScopeTypeInfoEventCallback = (scopeInfos: ScopeTypeInfo[]) => void;
159+
111160
/**
112161
* Contains the ranges that define a given scope, eg its {@link domain} and the
113162
* ranges for its {@link targets}.

packages/common/src/types/command/PartialTargetDescriptor.types.ts

+92-73
Original file line numberDiff line numberDiff line change
@@ -75,88 +75,107 @@ export type PartialMark =
7575
| RangeMark
7676
| ExplicitMark;
7777

78+
export const simpleSurroundingPairNames = [
79+
"angleBrackets",
80+
"backtickQuotes",
81+
"curlyBrackets",
82+
"doubleQuotes",
83+
"escapedDoubleQuotes",
84+
"escapedParentheses",
85+
"escapedSquareBrackets",
86+
"escapedSingleQuotes",
87+
"parentheses",
88+
"singleQuotes",
89+
"squareBrackets",
90+
] as const;
91+
export const complexSurroundingPairNames = [
92+
"string",
93+
"any",
94+
"collectionBoundary",
95+
] as const;
96+
export const surroundingPairNames = [
97+
...simpleSurroundingPairNames,
98+
...complexSurroundingPairNames,
99+
];
78100
export type SimpleSurroundingPairName =
79-
| "angleBrackets"
80-
| "backtickQuotes"
81-
| "curlyBrackets"
82-
| "doubleQuotes"
83-
| "escapedDoubleQuotes"
84-
| "escapedParentheses"
85-
| "escapedSquareBrackets"
86-
| "escapedSingleQuotes"
87-
| "parentheses"
88-
| "singleQuotes"
89-
| "squareBrackets";
101+
(typeof simpleSurroundingPairNames)[number];
90102
export type ComplexSurroundingPairName =
91-
| "string"
92-
| "any"
93-
| "collectionBoundary";
103+
(typeof complexSurroundingPairNames)[number];
94104
export type SurroundingPairName =
95105
| SimpleSurroundingPairName
96106
| ComplexSurroundingPairName;
97107

98-
export type SimpleScopeTypeType =
99-
| "argumentOrParameter"
100-
| "anonymousFunction"
101-
| "attribute"
102-
| "branch"
103-
| "class"
104-
| "className"
105-
| "collectionItem"
106-
| "collectionKey"
107-
| "comment"
108-
| "functionCall"
109-
| "functionCallee"
110-
| "functionName"
111-
| "ifStatement"
112-
| "instance"
113-
| "list"
114-
| "map"
115-
| "name"
116-
| "namedFunction"
117-
| "regularExpression"
118-
| "statement"
119-
| "string"
120-
| "type"
121-
| "value"
122-
| "condition"
123-
| "section"
124-
| "sectionLevelOne"
125-
| "sectionLevelTwo"
126-
| "sectionLevelThree"
127-
| "sectionLevelFour"
128-
| "sectionLevelFive"
129-
| "sectionLevelSix"
130-
| "selector"
131-
| "switchStatementSubject"
132-
| "unit"
133-
| "xmlBothTags"
134-
| "xmlElement"
135-
| "xmlEndTag"
136-
| "xmlStartTag"
137-
| "notebookCell"
108+
export const simpleScopeTypeTypes = [
109+
"argumentOrParameter",
110+
"anonymousFunction",
111+
"attribute",
112+
"branch",
113+
"class",
114+
"className",
115+
"collectionItem",
116+
"collectionKey",
117+
"comment",
118+
"functionCall",
119+
"functionCallee",
120+
"functionName",
121+
"ifStatement",
122+
"instance",
123+
"list",
124+
"map",
125+
"name",
126+
"namedFunction",
127+
"regularExpression",
128+
"statement",
129+
"string",
130+
"type",
131+
"value",
132+
"condition",
133+
"section",
134+
"sectionLevelOne",
135+
"sectionLevelTwo",
136+
"sectionLevelThree",
137+
"sectionLevelFour",
138+
"sectionLevelFive",
139+
"sectionLevelSix",
140+
"selector",
141+
"switchStatementSubject",
142+
"unit",
143+
"xmlBothTags",
144+
"xmlElement",
145+
"xmlEndTag",
146+
"xmlStartTag",
138147
// Latex scope types
139-
| "part"
140-
| "chapter"
141-
| "subSection"
142-
| "subSubSection"
143-
| "namedParagraph"
144-
| "subParagraph"
145-
| "environment"
148+
"part",
149+
"chapter",
150+
"subSection",
151+
"subSubSection",
152+
"namedParagraph",
153+
"subParagraph",
154+
"environment",
146155
// Text based scopes
147-
| "character"
148-
| "word"
149-
| "token"
150-
| "identifier"
151-
| "line"
152-
| "sentence"
153-
| "paragraph"
154-
| "document"
155-
| "nonWhitespaceSequence"
156-
| "boundedNonWhitespaceSequence"
157-
| "url"
156+
"character",
157+
"word",
158+
"token",
159+
"identifier",
160+
"line",
161+
"sentence",
162+
"paragraph",
163+
"document",
164+
"nonWhitespaceSequence",
165+
"boundedNonWhitespaceSequence",
166+
"url",
167+
"notebookCell",
158168
// Talon
159-
| "command";
169+
"command",
170+
] as const;
171+
172+
export function isSimpleScopeType(
173+
scopeType: ScopeType,
174+
): scopeType is SimpleScopeType {
175+
return (simpleScopeTypeTypes as readonly string[]).includes(scopeType.type);
176+
}
177+
178+
export type SimpleScopeTypeType = (typeof simpleScopeTypeTypes)[number];
160179

161180
export interface SimpleScopeType {
162181
type: SimpleScopeTypeType;

packages/cursorless-engine/src/core/Debouncer.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export class Debouncer {
1010
constructor(
1111
/** The callback to debounce */
1212
private callback: () => void,
13+
private debounceDelayMs?: number,
1314
) {
1415
this.run = this.run.bind(this);
1516
}
@@ -19,9 +20,9 @@ export class Debouncer {
1920
clearTimeout(this.timeoutHandle);
2021
}
2122

22-
const decorationDebounceDelayMs = ide().configuration.getOwnConfiguration(
23-
"decorationDebounceDelayMs",
24-
);
23+
const decorationDebounceDelayMs =
24+
this.debounceDelayMs ??
25+
ide().configuration.getOwnConfiguration("decorationDebounceDelayMs");
2526

2627
this.timeoutHandle = setTimeout(() => {
2728
this.callback();

packages/cursorless-engine/src/cursorlessEngine.ts

+21-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ import {
44
FileSystem,
55
Hats,
66
IDE,
7+
ScopeProvider,
78
} from "@cursorless/common";
89
import { StoredTargetMap, TestCaseRecorder, TreeSitter } from ".";
910
import { CursorlessEngine } from "./api/CursorlessEngineApi";
10-
import { ScopeProvider } from "./api/ScopeProvider";
11-
import { ScopeRangeProvider } from "./ScopeVisualizer/ScopeRangeProvider";
12-
import { ScopeSupportChecker } from "./ScopeVisualizer/ScopeSupportChecker";
1311
import { Debug } from "./core/Debug";
1412
import { HatTokenMapImpl } from "./core/HatTokenMapImpl";
1513
import { Snippets } from "./core/Snippets";
@@ -21,9 +19,13 @@ import { ModifierStageFactoryImpl } from "./processTargets/ModifierStageFactoryI
2119
import { ScopeHandlerFactoryImpl } from "./processTargets/modifiers/scopeHandlers";
2220
import { runCommand } from "./runCommand";
2321
import { runIntegrationTests } from "./runIntegrationTests";
22+
import { ScopeInfoProvider } from "./scopeProviders/ScopeInfoProvider";
23+
import { ScopeRangeProvider } from "./scopeProviders/ScopeRangeProvider";
24+
import { ScopeRangeWatcher } from "./scopeProviders/ScopeRangeWatcher";
25+
import { ScopeSupportChecker } from "./scopeProviders/ScopeSupportChecker";
26+
import { ScopeSupportWatcher } from "./scopeProviders/ScopeSupportWatcher";
2427
import { TalonSpokenFormsJsonReader } from "./scopeProviders/TalonSpokenFormsJsonReader";
2528
import { injectIde } from "./singletons/ide.singleton";
26-
import { ScopeRangeWatcher } from "./ScopeVisualizer/ScopeRangeWatcher";
2729

2830
export function createCursorlessEngine(
2931
treeSitter: TreeSitter,
@@ -93,6 +95,11 @@ export function createCursorlessEngine(
9395
);
9496
},
9597
},
98+
scopeProvider: createScopeProvider(
99+
languageDefinitions,
100+
storedTargets,
101+
customSpokenFormGenerator,
102+
),
96103
customSpokenFormGenerator,
97104
testCaseRecorder,
98105
storedTargets,
@@ -108,6 +115,7 @@ export function createCursorlessEngine(
108115
function createScopeProvider(
109116
languageDefinitions: LanguageDefinitions,
110117
storedTargets: StoredTargetMap,
118+
customSpokenFormGenerator: CustomSpokenFormGeneratorImpl,
111119
): ScopeProvider {
112120
const scopeHandlerFactory = new ScopeHandlerFactoryImpl(languageDefinitions);
113121

@@ -125,6 +133,12 @@ function createScopeProvider(
125133
rangeProvider,
126134
);
127135
const supportChecker = new ScopeSupportChecker(scopeHandlerFactory);
136+
const infoProvider = new ScopeInfoProvider(customSpokenFormGenerator);
137+
const supportWatcher = new ScopeSupportWatcher(
138+
languageDefinitions,
139+
supportChecker,
140+
infoProvider,
141+
);
128142

129143
return {
130144
provideScopeRanges: rangeProvider.provideScopeRanges,
@@ -134,5 +148,8 @@ function createScopeProvider(
134148
rangeWatcher.onDidChangeIterationScopeRanges,
135149
getScopeSupport: supportChecker.getScopeSupport,
136150
getIterationScopeSupport: supportChecker.getIterationScopeSupport,
151+
onDidChangeScopeSupport: supportWatcher.onDidChangeScopeSupport,
152+
getScopeInfo: infoProvider.getScopeTypeInfo,
153+
onDidChangeScopeInfo: infoProvider.onDidChangeScopeInfo,
137154
};
138155
}

packages/cursorless-engine/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ export * from "./core/StoredTargets";
66
export * from "./typings/TreeSitter";
77
export * from "./cursorlessEngine";
88
export * from "./api/CursorlessEngineApi";
9-
export * from "./api/ScopeProvider";

0 commit comments

Comments
 (0)