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
3 changes: 3 additions & 0 deletions packages/lib-common/src/ide/normalized/NormalizedIDE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export class NormalizedIDE extends PassthroughIDE {
}

private initializeConfiguration() {
if (this.runMode === "development") {
this.configuration.mockConfiguration("debug", true);
}
this.configuration.mockConfigurationScope(
{ languageId: "css" },
{ wordSeparators: ["_", "-"] },
Expand Down
2 changes: 1 addition & 1 deletion packages/lib-engine/src/core/HatTokenMapImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class HatTokenMapImpl implements HatTokenMap {
await this.commandServerApi.signals.prePhrase.getVersion();

if (newSignalVersion !== this.lastSignalVersion) {
this.debug.log("taking snapshot");
this.debug.log("Taking snapshot");
this.lastSignalVersion = newSignalVersion;

if (newSignalVersion != null) {
Expand Down
23 changes: 21 additions & 2 deletions packages/lib-tutorial/src/TutorialImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ export class TutorialImpl implements Tutorial, CommandRunnerDecorator {

async resume() {
await this.setupStep();
Comment thread
AndreasArvidsson marked this conversation as resolved.
await this.checkPreconditions();
}

async list() {
Expand Down Expand Up @@ -353,17 +352,30 @@ export class TutorialImpl implements Tutorial, CommandRunnerDecorator {

const currentStep = this.currentTutorial!.steps[state.stepNumber];

const preConditionsMet = await arePreconditionsMet(
const preconditionError = await arePreconditionsMet(
this.ide.activeTextEditor,
this.editor,
this.hatTokenMap,
currentStep,
);

// Verify that the state hasn't changed since we started checking preconditions
if (this.state_ !== state) {
this.debug(
`Tutorial ${state.id} step ${state.stepNumber + 1}: precondition check discarded because the tutorial state changed`,
);
return;
}

const preConditionsMet = preconditionError == null;

if (!preConditionsMet) {
this.debug(
`Tutorial ${state.id} step ${state.stepNumber + 1}: ${preconditionError}`,
);
}

// Update the state if the preconditions have changed
if (preConditionsMet !== state.preConditionsMet) {
this.setState({
...state,
Expand All @@ -372,4 +384,11 @@ export class TutorialImpl implements Tutorial, CommandRunnerDecorator {
await this.ensureHighlights();
}
}

private debug(message: string) {
const debug = this.ide.configuration.getOwnConfiguration("debug");
if (debug) {
console.log(message);
}
}
}
46 changes: 28 additions & 18 deletions packages/lib-tutorial/src/arePreconditionsMet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,56 @@ import type { TutorialStep } from "./types/tutorial.types";
* @param editor The editor to check.
* @param hatTokenMap The hat token map to use for checking if hats are correct.
* @param step The tutorial step whose prerequesites are to be checked.
* @returns `true` if the preconditions are met, `false` otherwise.
* @returns A description of the first failed precondition, or `undefined` if
* all preconditions are met.
*/
export async function arePreconditionsMet(
activeTextEditor: TextEditor | undefined,
editor: TextEditor | undefined,
hatTokenMap: HatTokenMap,
{ initialState: snapshot, languageId }: TutorialStep,
): Promise<boolean> {
): Promise<string | undefined> {
if (snapshot == null) {
return true;
return undefined;
}

if (activeTextEditor !== editor) {
return false;
return `Active editor differs from tutorial editor`;
}

if (editor == null || editor.document.languageId !== languageId) {
return false;
if (editor == null) {
return "Tutorial editor is unavailable";
}

if (editor.document.languageId !== languageId) {
return `Language differs (expected: ${languageId}, actual: ${editor.document.languageId})`;
}

if (editor.document.getText() !== snapshot.documentContents) {
return false;
return "Document contents differ";
}

if (
!isEqual(editor.selections, snapshot.selections.map(plainObjectToSelection))
) {
return false;
const expectedSelections = snapshot.selections.map(plainObjectToSelection);
if (!isEqual(editor.selections, expectedSelections)) {
const expected = expectedSelections
.map((selection) => selection.concise())
.join(", ");
const actual = editor.selections
.map((selection) => selection.concise())
.join(", ");
return `Selections differ (expected: ${expected}, actual: ${actual})`;
}

const readableHatMap = await hatTokenMap.getReadableMap(false);
for (const mark of serializedMarksToTokenHats(snapshot.marks, editor)) {
if (
!readableHatMap
.getToken(mark.hatStyle, mark.grapheme)
?.range.isRangeEqual(mark.hatRange)
) {
return false;
const actualRange = readableHatMap.getToken(
mark.hatStyle,
mark.grapheme,
)?.range;
if (!actualRange?.isRangeEqual(mark.hatRange)) {
return `Hat ${mark.hatStyle}.${mark.grapheme} differs (expected: ${mark.hatRange.concise()}, actual: ${actualRange?.concise() ?? "none"})`;
}
}

return true;
return undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ async function runBasicTutorialTest(spyIde: SpyIDE) {
// Test resuming tutorial
await commands.executeCommand("cursorless.tutorial.resume");
await checkStepSetup(fixtures[0]);
const resumedStateEvent = getTutorialWebviewEventLog().at(-2);
assert.ok(resumedStateEvent?.type === "messageSent");
assert.equal(resumedStateEvent.data.preConditionsMet, true);

// Test automatic advancing
await runCursorlessCommand({
Expand Down
Loading