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
19 changes: 14 additions & 5 deletions packages/common/src/ide/fake/FakeIDE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import type { TextDocumentChangeEvent } from "../types/Events";
import type { FlashDescriptor } from "../types/FlashDescriptor";
import type { QuickPickOptions } from "../types/QuickPickOptions";
import type {
Emit,
Event,
TextEditorSelectionChangeEvent,
TextEditorVisibleRangesChangeEvent,
} from "../types/events.types";
import type {
Disposable,
IDE,
EmittableIDE,
OpenUntitledTextDocumentOptions,
RunMode,
WorkspaceFolder,
Expand All @@ -28,7 +29,7 @@ import FakeConfiguration from "./FakeConfiguration";
import FakeKeyValueStore from "./FakeKeyValueStore";
import FakeMessages from "./FakeMessages";

export class FakeIDE implements IDE {
export class FakeIDE implements EmittableIDE {
configuration = new FakeConfiguration();
keyValueStore = new FakeKeyValueStore();
clipboard = new FakeClipboard();
Expand All @@ -47,15 +48,15 @@ export class FakeIDE implements IDE {
}

async flashRanges(_flashDescriptors: FlashDescriptor[]): Promise<void> {
// empty
// Empty
}

async setHighlightRanges(
_highlightId: string | undefined,
_editor: TextEditor,
_ranges: GeneralizedRange[],
): Promise<void> {
// empty
// Empty
}

onDidOpenTextDocument: Event<TextDocument> = dummyEvent;
Expand All @@ -68,6 +69,10 @@ export class FakeIDE implements IDE {
dummyEvent;
onDidChangeTextDocument: Event<TextDocumentChangeEvent> = dummyEvent;

emitDidChangeTextDocument: Emit<TextDocumentChangeEvent> = dummyEmit;
emitDidChangeTextEditorSelection: Emit<TextEditorSelectionChangeEvent> =
dummyEmit;

mockAssetsRoot(_assetsRoot: string) {
this.assetsRoot_ = _assetsRoot;
}
Expand Down Expand Up @@ -151,7 +156,11 @@ export class FakeIDE implements IDE {
function dummyEvent() {
return {
dispose() {
// empty
// Empty
},
};
}

function dummyEmit() {
// Empty
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,79 @@
import type {
Edit,
EditableTextEditor,
EmittableIDE,
GeneralizedRange,
InMemoryTextDocument,
OpenLinkOptions,
Range,
RevealLineAt,
Selection,
SelectionOffsets,
SetSelectionsOpts,
TextDocument,
TextEditor,
TextEditorOptions,
} from "@cursorless/common";
import { selectionsEqual } from "@cursorless/common";
import type { Talon } from "../types/talon.types";
import { setSelections } from "./setSelections";
import type { TalonJsIDE } from "./TalonJsIDE";
import { talonJsPerformEdits } from "./talonJsPerformEdits";

export class TalonJsEditor implements EditableTextEditor {
options: TextEditorOptions = {
tabSize: 4,
insertSpaces: true,
};

isActive = true;

constructor(
private talon: Talon,
private ide: TalonJsIDE,
public id: string,
public document: InMemoryTextDocument,
public visibleRanges: Range[],
public selections: Selection[],
) {}
import { Selection, selectionsEqual } from "@cursorless/common";
import { URI } from "vscode-uri";
import { InMemoryTextDocument } from "./InMemoryTextDocument";

interface Params {
ide: EmittableIDE;
languageId?: string;
content?: string;
options?: TextEditorOptions;
visibleRanges?: Range[];
selections?: Selection[] | SelectionOffsets[];
}

export class InMemoryTextEditor implements EditableTextEditor {
private static nextId = 0;

private readonly ide: EmittableIDE;
readonly id: string;
readonly isActive = true;
readonly document: InMemoryTextDocument;
readonly options: TextEditorOptions;
readonly visibleRanges: Range[];
selections: Selection[];

constructor({
ide,
languageId = "plaintext",
content = "",
visibleRanges,
selections,
options,
}: Params) {
this.ide = ide;
this.id = String(InMemoryTextEditor.nextId++);
const uri = URI.parse(`InMemoryTextEditor://${this.id}`);
this.document = new InMemoryTextDocument(uri, languageId, content);

if (visibleRanges != null) {
if (visibleRanges.length === 0) {
throw new Error("Visible ranges must be non-empty");
}
this.visibleRanges = visibleRanges;
} else {
this.visibleRanges = [this.document.range];
}

if (selections != null) {
if (selections.length === 0) {
throw new Error("Selections must be non-empty");
}
this.selections = selections.map((s) => {
return s instanceof Selection ? s : createSelection(this.document, s);
});
} else {
this.selections = [new Selection(0, 0, 0, 0)];
}

this.options = options ?? {
insertSpaces: true,
tabSize: 4,
};
}

isEqual(other: TextEditor): boolean {
return this.id === other.id;
Expand All @@ -42,14 +83,24 @@ export class TalonJsEditor implements EditableTextEditor {
selections: Selection[],
_opts?: SetSelectionsOpts,
): Promise<void> {
if (selections.length === 0) {
throw new Error("Selections must be non-empty");
}
if (!selectionsEqual(this.selections, selections)) {
await setSelections(this.talon, this.document, selections);
this.selections = selections;
this.ide.emitDidChangeTextEditorSelection({
textEditor: this,
selections: selections,
});
}
}

edit(edits: Edit[]): Promise<boolean> {
talonJsPerformEdits(this.talon, this.ide, this.document, edits);
const changes = this.document.edit(edits);
this.ide.emitDidChangeTextDocument({
document: this.document,
contentChanges: changes,
});
return Promise.resolve(true);
}

Expand Down Expand Up @@ -179,3 +230,10 @@ export class TalonJsEditor implements EditableTextEditor {
throw Error("gitUnstageRange: not implemented");
}
}

function createSelection(document: TextDocument, selection: SelectionOffsets) {
return new Selection(
document.positionAt(selection.anchor),
document.positionAt(selection.active),
);
}
7 changes: 7 additions & 0 deletions packages/common/src/ide/types/events.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export interface Event<T> {
): Disposable;
}

/**
* Represents a function that emits an event of type T.
*/
export interface Emit<T> {
(event: T): void;
}

/**
* Represents an event describing the change in a {@link TextEditor.selections text editor's selections}.
*/
Expand Down
5 changes: 5 additions & 0 deletions packages/common/src/ide/types/ide.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ export interface IDE {
): Promise<void>;
}

export interface EmittableIDE extends IDE {
emitDidChangeTextDocument(event: TextDocumentChangeEvent): void;
emitDidChangeTextEditorSelection(event: TextEditorSelectionChangeEvent): void;
}

export interface WorkspaceFolder {
uri: URI;
name: string;
Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export * from "./errors";
export * from "./extensionDependencies";
export * from "./FakeCommandServerApi";
export * from "./ide/fake/FakeIDE";
export * from "./ide/inMemoryTextDocument/InMemoryTextDocument";
export * from "./ide/inMemoryTextEditor/InMemoryTextDocument";
export * from "./ide/inMemoryTextEditor/InMemoryTextEditor";
export * from "./ide/normalized/NormalizedIDE";
export * from "./ide/PassthroughIDE";
export * from "./ide/spy/SpyIDE";
Expand Down Expand Up @@ -77,7 +78,6 @@ export * from "./types/NotebookEditor";
export * from "./types/Position";
export * from "./types/Range";
export * from "./types/RangeExpansionBehavior";
export * from "./types/RangeOffsets";
export * from "./types/RevealLineAt";
export * from "./types/ScopeProvider";
export * from "./types/Selection";
Expand Down
8 changes: 8 additions & 0 deletions packages/common/src/types/Range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,11 @@ export class Range {
return `${this.start.concise()}-${this.end.concise()}`;
}
}

/**
* Represents the offsets of a range, where `start` and `end` are zero-based offsets from the start of the document.
*/
export interface RangeOffsets {
start: number;
end: number;
}
4 changes: 0 additions & 4 deletions packages/common/src/types/RangeOffsets.ts

This file was deleted.

8 changes: 8 additions & 0 deletions packages/common/src/types/Selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,11 @@ export class Selection extends Range {
return this.concise();
}
}

/**
* Represents the offsets of a selection, where `anchor` and `active` are zero-based offsets from the start of the document.
*/
export interface SelectionOffsets {
anchor: number;
active: number;
}
3 changes: 1 addition & 2 deletions packages/common/src/types/Token.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/**
* A token within a text editor
*/
import type { Range } from "./Range";
import type { RangeOffsets } from "./RangeOffsets";
import type { Range, RangeOffsets } from "./Range";
import type { TextEditor } from "./TextEditor";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,5 @@ export default async function moveFile(file: string) {
const childDir = path.join(parent, childDirName);
await mkdir(childDir, { recursive: true });
const outputPath = path.join(childDir, path.basename(file));
// console.log(`${file} => ${outputPath}`);
await rename(file, outputPath);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
TextEditorOptions,
} from "@cursorless/common";

export class TestEditor implements EditableTextEditor {
export class TestTextEditor implements EditableTextEditor {
options: TextEditorOptions = {
tabSize: 4,
insertSpaces: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import type {
MessageType,
ScopeProvider,
} from "@cursorless/common";
import { FakeIDE, InMemoryTextDocument, Selection } from "@cursorless/common";
import { FakeIDE, InMemoryTextEditor } from "@cursorless/common";
import { FileSystemRawTreeSitterQueryProvider } from "@cursorless/node-common";
import { URI } from "vscode-uri";
import { createCursorlessEngine } from "..";
import { TestEditor } from "./TestEditor";
import { TestFileSystem } from "./TestFileSystem";
import { TestTreeSitter } from "./TestTreeSitter";

Expand Down Expand Up @@ -39,29 +37,14 @@ export async function createTestEnvironment(): Promise<TestEnvironment> {
});

const openNewEditor = async (content: string, languageId: string) => {
const editor = createNewEditor(content, languageId);
const editor = new InMemoryTextEditor({ ide, languageId, content });
await languageDefinitions.loadLanguage(languageId);
return editor;
};

return { openNewEditor, scopeProvider };
}

let nextId = 0;

function createNewEditor(
content: string,
languageId: string,
): EditableTextEditor {
const id = String(nextId++);
const uri = URI.parse(`talon-js://${id}`);
const document = new InMemoryTextDocument(uri, languageId, content);
const visibleRanges = [document.range];
const selections = [new Selection(0, 0, 0, 0)];
const editor = new TestEditor(id, document, visibleRanges, selections);
return editor;
}

class TestMessages implements Messages {
showMessage(
type: MessageType,
Expand Down
Loading
Loading