Skip to content

Commit 49c3931

Browse files
committed
Scope info provider
1 parent 896bbe4 commit 49c3931

24 files changed

+1083
-100
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

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

162181
export interface SimpleScopeType {
163182
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 "./nodeCommon/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)