Skip to content

Commit

Permalink
Scope info provider
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey committed Oct 16, 2023
1 parent 84d2f1d commit 1c6435b
Show file tree
Hide file tree
Showing 24 changed files with 1,081 additions and 99 deletions.
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export * from "./types/TextEditorOptions";
export * from "./types/TextLine";
export * from "./types/Token";
export * from "./types/HatTokenMap";
export * from "./types/ScopeProvider";
export * from "./types/SpokenForm";
export * from "./util/textFormatters";
export * from "./types/snippet.types";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import {
GeneralizedRange,
Range,
ScopeType,
SpokenForm,
TextEditor,
} from "@cursorless/common";
} from "..";

export interface ScopeProvider {
/**
Expand Down Expand Up @@ -75,6 +76,34 @@ export interface ScopeProvider {
editor: TextEditor,
scopeType: ScopeType,
) => ScopeSupport;

/**
* Registers a callback to be run when the scope support changes for the active
* editor. The callback will be run immediately once with the current support
* levels for the active editor.
* @param callback The callback to run when the scope support changes
* @returns A {@link Disposable} which will stop the callback from running
*/
onDidChangeScopeSupport: (callback: ScopeSupportEventCallback) => Disposable;

/**
* Registers a callback to be run when the scope support changes for the active
* editor. The callback will be run immediately once with the current support
* levels for the active editor.
* @param callback The callback to run when the scope support changes
* @returns A {@link Disposable} which will stop the callback from running
*/
onDidChangeScopeInfo(callback: ScopeTypeInfoEventCallback): Disposable;

/**
* Determine the level of support for the iteration scope of {@link scopeType}
* in {@link editor}, as determined by its language id.
* @param editor The editor to check
* @param scopeType The scope type to check
* @returns The level of support for the iteration scope of {@link scopeType}
* in {@link editor}
*/
getScopeInfo: (scopeType: ScopeType) => ScopeTypeInfo;
}

interface ScopeRangeConfigBase {
Expand Down Expand Up @@ -108,6 +137,26 @@ export type IterationScopeChangeEventCallback = (
scopeRanges: IterationScopeRanges[],
) => void;

export interface ScopeSupportInfo extends ScopeTypeInfo {
support: ScopeSupport;
iterationScopeSupport: ScopeSupport;
}

export type ScopeSupportLevels = ScopeSupportInfo[];

export type ScopeSupportEventCallback = (
supportLevels: ScopeSupportLevels,
) => void;

export interface ScopeTypeInfo {
scopeType: ScopeType;
spokenForm: SpokenForm;
humanReadableName: string;
isLanguageSpecific: boolean;
}

export type ScopeTypeInfoEventCallback = (scopeInfos: ScopeTypeInfo[]) => void;

/**
* Contains the ranges that define a given scope, eg its {@link domain} and the
* ranges for its {@link targets}.
Expand Down
165 changes: 92 additions & 73 deletions packages/common/src/types/command/PartialTargetDescriptor.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,88 +75,107 @@ export type PartialMark =
| RangeMark
| ExplicitMark;

export const simpleSurroundingPairNames = [
"angleBrackets",
"backtickQuotes",
"curlyBrackets",
"doubleQuotes",
"escapedDoubleQuotes",
"escapedParentheses",
"escapedSquareBrackets",
"escapedSingleQuotes",
"parentheses",
"singleQuotes",
"squareBrackets",
] as const;
export const complexSurroundingPairNames = [
"string",
"any",
"collectionBoundary",
] as const;
export const surroundingPairNames = [
...simpleSurroundingPairNames,
...complexSurroundingPairNames,
];
export type SimpleSurroundingPairName =
| "angleBrackets"
| "backtickQuotes"
| "curlyBrackets"
| "doubleQuotes"
| "escapedDoubleQuotes"
| "escapedParentheses"
| "escapedSquareBrackets"
| "escapedSingleQuotes"
| "parentheses"
| "singleQuotes"
| "squareBrackets";
(typeof simpleSurroundingPairNames)[number];
export type ComplexSurroundingPairName =
| "string"
| "any"
| "collectionBoundary";
(typeof complexSurroundingPairNames)[number];
export type SurroundingPairName =
| SimpleSurroundingPairName
| ComplexSurroundingPairName;

export type SimpleScopeTypeType =
| "argumentOrParameter"
| "anonymousFunction"
| "attribute"
| "branch"
| "class"
| "className"
| "collectionItem"
| "collectionKey"
| "comment"
| "functionCall"
| "functionCallee"
| "functionName"
| "ifStatement"
| "instance"
| "list"
| "map"
| "name"
| "namedFunction"
| "regularExpression"
| "statement"
| "string"
| "type"
| "value"
| "condition"
| "section"
| "sectionLevelOne"
| "sectionLevelTwo"
| "sectionLevelThree"
| "sectionLevelFour"
| "sectionLevelFive"
| "sectionLevelSix"
| "selector"
| "switchStatementSubject"
| "unit"
| "xmlBothTags"
| "xmlElement"
| "xmlEndTag"
| "xmlStartTag"
| "notebookCell"
export const simpleScopeTypeTypes = [
"argumentOrParameter",
"anonymousFunction",
"attribute",
"branch",
"class",
"className",
"collectionItem",
"collectionKey",
"comment",
"functionCall",
"functionCallee",
"functionName",
"ifStatement",
"instance",
"list",
"map",
"name",
"namedFunction",
"regularExpression",
"statement",
"string",
"type",
"value",
"condition",
"section",
"sectionLevelOne",
"sectionLevelTwo",
"sectionLevelThree",
"sectionLevelFour",
"sectionLevelFive",
"sectionLevelSix",
"selector",
"switchStatementSubject",
"unit",
"xmlBothTags",
"xmlElement",
"xmlEndTag",
"xmlStartTag",
// Latex scope types
| "part"
| "chapter"
| "subSection"
| "subSubSection"
| "namedParagraph"
| "subParagraph"
| "environment"
"part",
"chapter",
"subSection",
"subSubSection",
"namedParagraph",
"subParagraph",
"environment",
// Text based scopes
| "character"
| "word"
| "token"
| "identifier"
| "line"
| "sentence"
| "paragraph"
| "document"
| "nonWhitespaceSequence"
| "boundedNonWhitespaceSequence"
| "url"
"character",
"word",
"token",
"identifier",
"line",
"sentence",
"paragraph",
"document",
"nonWhitespaceSequence",
"boundedNonWhitespaceSequence",
"url",
"notebookCell",
// Talon
| "command";
"command",
] as const;

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

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

export interface SimpleScopeType {
type: SimpleScopeTypeType;
Expand Down
7 changes: 4 additions & 3 deletions packages/cursorless-engine/src/core/Debouncer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class Debouncer {
constructor(
/** The callback to debounce */
private callback: () => void,
private debounceDelayMs?: number,
) {
this.run = this.run.bind(this);
}
Expand All @@ -19,9 +20,9 @@ export class Debouncer {
clearTimeout(this.timeoutHandle);
}

const decorationDebounceDelayMs = ide().configuration.getOwnConfiguration(
"decorationDebounceDelayMs",
);
const decorationDebounceDelayMs =
this.debounceDelayMs ??
ide().configuration.getOwnConfiguration("decorationDebounceDelayMs");

this.timeoutHandle = setTimeout(() => {
this.callback();
Expand Down
25 changes: 21 additions & 4 deletions packages/cursorless-engine/src/cursorlessEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import {
FileSystem,
Hats,
IDE,
ScopeProvider,
} from "@cursorless/common";
import { StoredTargetMap, TestCaseRecorder, TreeSitter } from ".";
import { CursorlessEngine } from "./api/CursorlessEngineApi";
import { ScopeProvider } from "./api/ScopeProvider";
import { ScopeRangeProvider } from "./ScopeVisualizer/ScopeRangeProvider";
import { ScopeSupportChecker } from "./ScopeVisualizer/ScopeSupportChecker";
import { Debug } from "./core/Debug";
import { HatTokenMapImpl } from "./core/HatTokenMapImpl";
import { Snippets } from "./core/Snippets";
Expand All @@ -21,9 +19,13 @@ import { ModifierStageFactoryImpl } from "./processTargets/ModifierStageFactoryI
import { ScopeHandlerFactoryImpl } from "./processTargets/modifiers/scopeHandlers";
import { runCommand } from "./runCommand";
import { runIntegrationTests } from "./runIntegrationTests";
import { ScopeInfoProvider } from "./scopeProviders/ScopeInfoProvider";
import { ScopeRangeProvider } from "./scopeProviders/ScopeRangeProvider";
import { ScopeRangeWatcher } from "./scopeProviders/ScopeRangeWatcher";
import { ScopeSupportChecker } from "./scopeProviders/ScopeSupportChecker";
import { ScopeSupportWatcher } from "./scopeProviders/ScopeSupportWatcher";
import { TalonSpokenFormsJsonReader } from "./scopeProviders/TalonSpokenFormsJsonReader";
import { injectIde } from "./singletons/ide.singleton";
import { ScopeRangeWatcher } from "./ScopeVisualizer/ScopeRangeWatcher";

export function createCursorlessEngine(
treeSitter: TreeSitter,
Expand Down Expand Up @@ -93,6 +95,11 @@ export function createCursorlessEngine(
);
},
},
scopeProvider: createScopeProvider(
languageDefinitions,
storedTargets,
customSpokenFormGenerator,
),
customSpokenFormGenerator,
testCaseRecorder,
storedTargets,
Expand All @@ -108,6 +115,7 @@ export function createCursorlessEngine(
function createScopeProvider(
languageDefinitions: LanguageDefinitions,
storedTargets: StoredTargetMap,
customSpokenFormGenerator: CustomSpokenFormGeneratorImpl,
): ScopeProvider {
const scopeHandlerFactory = new ScopeHandlerFactoryImpl(languageDefinitions);

Expand All @@ -125,6 +133,12 @@ function createScopeProvider(
rangeProvider,
);
const supportChecker = new ScopeSupportChecker(scopeHandlerFactory);
const infoProvider = new ScopeInfoProvider(customSpokenFormGenerator);
const supportWatcher = new ScopeSupportWatcher(
languageDefinitions,
supportChecker,
infoProvider,
);

return {
provideScopeRanges: rangeProvider.provideScopeRanges,
Expand All @@ -134,5 +148,8 @@ function createScopeProvider(
rangeWatcher.onDidChangeIterationScopeRanges,
getScopeSupport: supportChecker.getScopeSupport,
getIterationScopeSupport: supportChecker.getIterationScopeSupport,
onDidChangeScopeSupport: supportWatcher.onDidChangeScopeSupport,
getScopeInfo: infoProvider.getScopeTypeInfo,
onDidChangeScopeInfo: infoProvider.onDidChangeScopeInfo,
};
}
1 change: 0 additions & 1 deletion packages/cursorless-engine/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ export * from "./core/StoredTargets";
export * from "./typings/TreeSitter";
export * from "./cursorlessEngine";
export * from "./api/CursorlessEngineApi";
export * from "./api/ScopeProvider";
Loading

0 comments on commit 1c6435b

Please sign in to comment.