Skip to content
Draft
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
3 changes: 2 additions & 1 deletion cursorless-talon/src/spoken_forms.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@
"short paint": "boundedNonWhitespaceSequence",
"short block": "boundedParagraph",
"link": "url",
"cell": "notebookCell"
"cell": "notebookCell",
"that": "that"
},
"surrounding_pair_scope_type": {
"string": "string"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export const simpleScopeTypeTypes = [
"boundedNonWhitespaceSequence",
"url",
"notebookCell",
"that",
// Talon
"command",
// Private scope types
Expand Down
6 changes: 5 additions & 1 deletion packages/cursorless-engine/src/cursorlessEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ function createScopeProvider(
storedTargets: StoredTargetMap,
customSpokenFormGenerator: CustomSpokenFormGeneratorImpl,
): ScopeProvider {
const scopeHandlerFactory = new ScopeHandlerFactoryImpl(languageDefinitions);
const scopeHandlerFactory = new ScopeHandlerFactoryImpl(
languageDefinitions,
storedTargets,
);

const rangeProvider = new ScopeRangeProvider(
scopeHandlerFactory,
Expand All @@ -164,6 +167,7 @@ function createScopeProvider(
const rangeWatcher = new ScopeRangeWatcher(
languageDefinitions,
rangeProvider,
storedTargets,
);
const supportChecker = new ScopeSupportChecker(scopeHandlerFactory);
const infoProvider = new ScopeInfoProvider(customSpokenFormGenerator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ import {
SurroundingPairScopeHandler,
} from "./SurroundingPairScopeHandler";
import { InteriorScopeHandler } from "./SurroundingPairScopeHandler/InteriorScopeHandler";
import { ThatScopeHandler } from "./ThatScopeHandler";
import { TokenScopeHandler } from "./TokenScopeHandler";
import { WordScopeHandler } from "./WordScopeHandler/WordScopeHandler";
import type { StoredTargetMap } from "../../../core/StoredTargets";

/**
* Returns a scope handler for the given scope type and language id, or
Expand All @@ -46,7 +48,10 @@ import { WordScopeHandler } from "./WordScopeHandler/WordScopeHandler";
* undefined if the given scope type / language id combination is not supported.
*/
export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory {
constructor(private languageDefinitions: LanguageDefinitions) {
constructor(
private languageDefinitions: LanguageDefinitions,
private storedTargets: StoredTargetMap,
) {
this.maybeCreate = this.maybeCreate.bind(this);
this.create = this.create.bind(this);
}
Expand Down Expand Up @@ -118,6 +123,13 @@ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory {
scopeType,
languageId,
);
case "that":
return new ThatScopeHandler(
this,
scopeType,
languageId,
this.storedTargets,
);
case "interior":
return InteriorScopeHandler.maybeCreate(
this.languageDefinitions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { Direction, ScopeType } from "@cursorless/common";
import type { StoredTargetMap } from "../../../core/StoredTargets";
import { TokenTarget } from "../../targets";
import { NestedScopeHandler } from "./NestedScopeHandler";
import type { ScopeHandlerFactory } from "./ScopeHandlerFactory";
import type { TargetScope } from "./scope.types";

/**
* Scope handler that returns the range(s) from the "that" mark.
* The "that" mark stores the targets from the most recent Cursorless command.
*/
export class ThatScopeHandler extends NestedScopeHandler {
public readonly scopeType = { type: "that" } as const;
public readonly iterationScopeType: ScopeType = { type: "document" };

constructor(
scopeHandlerFactory: ScopeHandlerFactory,
scopeType: ScopeType,
languageId: string,
private storedTargets: StoredTargetMap,
) {
super(scopeHandlerFactory, scopeType, languageId);
}

protected *generateScopesInSearchScope(
_direction: Direction,
{ editor }: TargetScope,
): Iterable<TargetScope> {
// Get the targets stored in the "that" mark
const thatTargets = this.storedTargets.get("that");

if (thatTargets == null || thatTargets.length === 0) {
// No "that" mark available, yield nothing
return;
}

// Filter targets to only those in the current editor
const editorTargets = thatTargets.filter(
(target) => target.editor.id === editor.id,
);

// Yield a TargetScope for each target
for (const target of editorTargets) {
yield {
editor: target.editor,
domain: target.contentRange,
getTargets: (isReversed) => [
new TokenTarget({
editor: target.editor,
contentRange: target.contentRange,
isReversed,
}),
],
};
}
}
}
2 changes: 1 addition & 1 deletion packages/cursorless-engine/src/runCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function createCommandRunner(
const modifierStageFactory = new ModifierStageFactoryImpl(
languageDefinitions,
storedTargets,
new ScopeHandlerFactoryImpl(languageDefinitions),
new ScopeHandlerFactoryImpl(languageDefinitions, storedTargets),
);

const markStageFactory = new MarkStageFactoryImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ function isLanguageSpecific(scopeType: ScopeType): boolean {
case "boundedNonWhitespaceSequence":
case "url":
case "notebookCell":
case "that":
case "surroundingPair":
case "surroundingPairInterior":
case "customRegex":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { LanguageDefinitions } from "../languages/LanguageDefinitions";
import { ide } from "../singletons/ide.singleton";
import type { ScopeRangeProvider } from "./ScopeRangeProvider";
import { DecorationDebouncer } from "../util/DecorationDebouncer";
import type { StoredTargetMap } from "../core/StoredTargets";

/**
* Watches for changes to the scope ranges of visible editors and notifies
Expand All @@ -25,6 +26,7 @@ export class ScopeRangeWatcher {
constructor(
languageDefinitions: LanguageDefinitions,
private scopeRangeProvider: ScopeRangeProvider,
storedTargets: StoredTargetMap,
) {
this.onChange = this.onChange.bind(this);
this.onDidChangeScopeRanges = this.onDidChangeScopeRanges.bind(this);
Expand All @@ -48,6 +50,12 @@ export class ScopeRangeWatcher {
ide().onDidChangeTextDocument(debouncer.run),
ide().onDidChangeTextEditorVisibleRanges(debouncer.run),
languageDefinitions.onDidChangeDefinition(this.onChange),
// Listen for "that" mark changes to update the "that" scope visualization
storedTargets.onStoredTargets((key, _targets) => {
if (key === "that") {
debouncer.run();
}
}),
debouncer,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const defaultSpokenFormMapCore: DefaultSpokenFormMapDefinition = {
boundedNonWhitespaceSequence: "short paint",
url: "link",
notebookCell: "cell",
that: "that",

string: isPrivate("parse tree string"),
textFragment: isPrivate("text fragment"),
Expand Down
Loading