Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added command history #2115

Merged
merged 50 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b8199c5
Added command history
AndreasArvidsson Dec 10, 2023
af0f3b8
clean up
AndreasArvidsson Dec 10, 2023
957c576
More clean up
AndreasArvidsson Dec 10, 2023
10dce17
Refactor as a command runner decorator
AndreasArvidsson Dec 11, 2023
8126d6c
cleanup
AndreasArvidsson Dec 11, 2023
8d838cd
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Dec 11, 2023
0e63bd9
Added setting to package
AndreasArvidsson Dec 11, 2023
1a76fc1
Merge branch 'commandHistory' of github.com:cursorless-dev/cursorless…
AndreasArvidsson Dec 11, 2023
f2cee87
Sanitize action
AndreasArvidsson Dec 11, 2023
ef206b3
Add comments
AndreasArvidsson Dec 11, 2023
c7bcf64
update
AndreasArvidsson Dec 11, 2023
6edd8ad
cleanup
AndreasArvidsson Dec 11, 2023
caad3ef
Added types
AndreasArvidsson Dec 11, 2023
5b108dd
cleanup
AndreasArvidsson Dec 11, 2023
6d3cb21
refactor
AndreasArvidsson Dec 11, 2023
7df130e
Added docstring
AndreasArvidsson Dec 11, 2023
c99ab91
tweak
pokey Dec 11, 2023
14343e4
List all action names
AndreasArvidsson Dec 11, 2023
1f9b9c8
add comment
AndreasArvidsson Dec 11, 2023
3c7cab9
Update packages/cursorless-vscode/src/CommandHistory.ts
AndreasArvidsson Dec 11, 2023
02b1160
Added thrown error
AndreasArvidsson Dec 12, 2023
1c345d0
Added order
AndreasArvidsson Dec 12, 2023
9b76190
Experiment with immer (#2124)
pokey Dec 12, 2023
3e3a074
Added tests
AndreasArvidsson Dec 13, 2023
1532071
cleanup
AndreasArvidsson Dec 13, 2023
194c58e
more clean up
AndreasArvidsson Dec 13, 2023
92e4d7d
remove log
AndreasArvidsson Dec 13, 2023
566cd36
update tests
AndreasArvidsson Dec 16, 2023
6ddb894
Merge branch 'main' into commandHistory
AndreasArvidsson Dec 17, 2023
86ad41e
Added analyze history command
AndreasArvidsson Dec 17, 2023
dc5eb24
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Dec 17, 2023
e510ee9
meta updater
AndreasArvidsson Dec 17, 2023
24c862e
Merge branch 'commandHistory' of github.com:cursorless-dev/cursorless…
AndreasArvidsson Dec 17, 2023
2254ee3
Added number
AndreasArvidsson Dec 17, 2023
5e365f1
Added documentation
AndreasArvidsson Dec 17, 2023
43bf118
Tweak docs
pokey Dec 18, 2023
88937fd
Tweaks
pokey Dec 18, 2023
40ea48b
tweak verbiage
pokey Dec 18, 2023
e27e392
tweak tests
pokey Dec 18, 2023
2016c40
Remove analyze action
AndreasArvidsson Dec 18, 2023
827e69f
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Dec 18, 2023
54ebcd0
Refactor
AndreasArvidsson Dec 19, 2023
b19c476
Remove spoken form
AndreasArvidsson Dec 19, 2023
47b187a
Merge branch 'main' into commandHistory
AndreasArvidsson Dec 19, 2023
b7d3887
added case
AndreasArvidsson Dec 19, 2023
2ef444c
Update tests
AndreasArvidsson Dec 19, 2023
1762319
update docs
AndreasArvidsson Dec 19, 2023
4c6de81
Added command id
AndreasArvidsson Jan 2, 2024
91212cf
Remove command analyzer
pokey Jan 3, 2024
598c1cd
Add sanitization tests
pokey Jan 3, 2024
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
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export * from "./types/ScopeProvider";
export * from "./types/SpokenForm";
export * from "./util/textFormatters";
export * from "./types/snippet.types";
export * from "./types/CommandHistory";
export * from "./testUtil/fromPlainObject";
export * from "./testUtil/spyToPlainObject";
export { default as DefaultMap } from "./util/DefaultMap";
Expand Down
12 changes: 12 additions & 0 deletions packages/common/src/types/CommandHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { CommandComplete } from "./command/command.types";

export interface CommandHistory {
append(command: CommandComplete): Promise<void>;
dispose(): void;
}

export interface CommandHistoryItem {
date: string;
cursorlessVersion: string;
command: CommandComplete;
}
10 changes: 7 additions & 3 deletions packages/cursorless-engine/src/cursorlessEngine.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import {
Command,
CommandHistory,
CommandServerApi,
FileSystem,
Hats,
IDE,
ScopeProvider,
} from "@cursorless/common";
import { StoredTargetMap } from "./core/StoredTargets";
import { TreeSitter } from "./typings/TreeSitter";
import {
CommandRunnerDecorator,
CursorlessEngine,
} from "./api/CursorlessEngineApi";
import { Debug } from "./core/Debug";
import { HatTokenMapImpl } from "./core/HatTokenMapImpl";
import { Snippets } from "./core/Snippets";
import { StoredTargetMap } from "./core/StoredTargets";
import { ensureCommandShape } from "./core/commandVersionUpgrades/ensureCommandShape";
import { RangeUpdater } from "./core/updateSelections/RangeUpdater";
import { CustomSpokenFormGeneratorImpl } from "./generateSpokenForm/CustomSpokenFormGeneratorImpl";
import { LanguageDefinitions } from "./languages/LanguageDefinitions";
import { TalonSpokenFormsJsonReader } from "./nodeCommon/TalonSpokenFormsJsonReader";
import { ModifierStageFactoryImpl } from "./processTargets/ModifierStageFactoryImpl";
import { ScopeHandlerFactoryImpl } from "./processTargets/modifiers/scopeHandlers";
import { runCommand } from "./runCommand";
Expand All @@ -28,15 +29,16 @@ import { ScopeRangeProvider } from "./scopeProviders/ScopeRangeProvider";
import { ScopeRangeWatcher } from "./scopeProviders/ScopeRangeWatcher";
import { ScopeSupportChecker } from "./scopeProviders/ScopeSupportChecker";
import { ScopeSupportWatcher } from "./scopeProviders/ScopeSupportWatcher";
import { TalonSpokenFormsJsonReader } from "./nodeCommon/TalonSpokenFormsJsonReader";
import { injectIde } from "./singletons/ide.singleton";
import { TreeSitter } from "./typings/TreeSitter";

export function createCursorlessEngine(
treeSitter: TreeSitter,
ide: IDE,
hats: Hats,
commandServerApi: CommandServerApi | null,
fileSystem: FileSystem,
commandHistory: CommandHistory,
): CursorlessEngine {
injectIde(ide);

Expand Down Expand Up @@ -81,6 +83,7 @@ export function createCursorlessEngine(
languageDefinitions,
rangeUpdater,
commandRunnerDecorators,
commandHistory,
command,
);
},
Expand All @@ -95,6 +98,7 @@ export function createCursorlessEngine(
languageDefinitions,
rangeUpdater,
commandRunnerDecorators,
commandHistory,
ensureCommandShape(args),
);
},
Expand Down
12 changes: 10 additions & 2 deletions packages/cursorless-engine/src/runCommand.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Command, HatTokenMap, ReadOnlyHatMap } from "@cursorless/common";
import {
Command,
CommandHistory,
HatTokenMap,
ReadOnlyHatMap,
} from "@cursorless/common";
import { CommandRunner } from "./CommandRunner";
import { Actions } from "./actions/Actions";
import { CommandRunnerDecorator } from "./api/CursorlessEngineApi";
import { Debug } from "./core/Debug";
import { Snippets } from "./core/Snippets";
import { CommandRunnerImpl } from "./core/commandRunner/CommandRunnerImpl";
Expand All @@ -12,7 +18,6 @@ import { TargetPipelineRunner } from "./processTargets";
import { MarkStageFactoryImpl } from "./processTargets/MarkStageFactoryImpl";
import { ModifierStageFactoryImpl } from "./processTargets/ModifierStageFactoryImpl";
import { ScopeHandlerFactoryImpl } from "./processTargets/modifiers/scopeHandlers";
import { CommandRunnerDecorator } from "./api/CursorlessEngineApi";

/**
* Entry point for Cursorless commands. We proceed as follows:
Expand All @@ -35,6 +40,7 @@ export async function runCommand(
languageDefinitions: LanguageDefinitions,
rangeUpdater: RangeUpdater,
commandRunnerDecorators: CommandRunnerDecorator[],
commandHistory: CommandHistory,
command: Command,
AndreasArvidsson marked this conversation as resolved.
Show resolved Hide resolved
): Promise<unknown> {
if (debug.active) {
Expand All @@ -44,6 +50,8 @@ export async function runCommand(

const commandComplete = canonicalizeAndValidateCommand(command);

void commandHistory.append(commandComplete);

const readableHatMap = await hatTokenMap.getReadableMap(
commandComplete.usePrePhraseSnapshot,
);
Expand Down
16 changes: 14 additions & 2 deletions packages/cursorless-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "@cursorless/common";
import {
createCursorlessEngine,
TestCaseRecorder,
TreeSitter,
} from "@cursorless/cursorless-engine";
import {
Expand All @@ -22,13 +23,18 @@ import {
toVscodeRange,
} from "@cursorless/vscode-common";
import * as crypto from "crypto";
import { mkdir } from "fs/promises";
import * as os from "os";
import * as path from "path";
import * as vscode from "vscode";
import { constructTestHelpers } from "./constructTestHelpers";
import { FakeFontMeasurements } from "./ide/vscode/hats/FakeFontMeasurements";
import { FontMeasurementsImpl } from "./ide/vscode/hats/FontMeasurementsImpl";
import { VscodeHats } from "./ide/vscode/hats/VscodeHats";
import {
DisabledCommandHistory,
VscodeCommandHistory,
} from "./ide/vscode/VscodeCommandHistory";
import { VscodeFileSystem } from "./ide/vscode/VscodeFileSystem";
import { VscodeIDE } from "./ide/vscode/VscodeIDE";
import {
Expand All @@ -47,8 +53,6 @@ import {
} from "./ScopeVisualizerCommandApi";
import { StatusBarItem } from "./StatusBarItem";
import { vscodeApi } from "./vscodeApi";
import { mkdir } from "fs/promises";
import { TestCaseRecorder } from "@cursorless/cursorless-engine";

/**
* Extension entrypoint called by VSCode on Cursorless startup.
Expand Down Expand Up @@ -81,6 +85,13 @@ export async function activate(

const treeSitter: TreeSitter = createTreeSitter(parseTreeApi);

const commandHistory =
vscodeIDE.runMode === "test"
? DisabledCommandHistory
: new VscodeCommandHistory(vscodeIDE, fileSystem);

context.subscriptions.push(commandHistory);

const {
commandApi,
storedTargets,
Expand All @@ -97,6 +108,7 @@ export async function activate(
hats,
commandServerApi,
fileSystem,
commandHistory,
);

const testCaseRecorder = new TestCaseRecorder(hatTokenMap, storedTargets);
Expand Down
94 changes: 94 additions & 0 deletions packages/cursorless-vscode/src/ide/vscode/VscodeCommandHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {
CommandComplete,
CommandHistory,
CommandHistoryItem,
Disposable,
FileSystem,
} from "@cursorless/common";
import * as fs from "fs/promises";
import { mkdirSync } from "fs";
import * as path from "path";
import * as vscode from "vscode";
import { VscodeIDE } from "./VscodeIDE";

const dirName = "commandHistory";
const filePrefix = "cursorlessCommandHistory";
const settingSection = "cursorless";
const settingName = "commandHistory";
const settingFullName = `${settingSection}.${settingName}`;

export class VscodeCommandHistory implements CommandHistory {
private readonly dirPath: string;
private readonly cursorlessVersion: string;
private disposable: Disposable;
private active: boolean = false;

constructor(ide: VscodeIDE, fileSystem: FileSystem) {
this.evaluateSetting = this.evaluateSetting.bind(this);
this.cursorlessVersion = ide.cursorlessVersion;
this.dirPath = path.join(fileSystem.cursorlessDir, dirName);

mkdirSync(this.dirPath, { recursive: true });
AndreasArvidsson marked this conversation as resolved.
Show resolved Hide resolved

this.evaluateSetting();

this.disposable = vscode.workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration(settingFullName)) {
this.evaluateSetting();
}
});
}

async append(command: CommandComplete): Promise<void> {
if (!this.active) {
return;
}
AndreasArvidsson marked this conversation as resolved.
Show resolved Hide resolved

const date = new Date();
const fileName = `${filePrefix}_${getMonthDate(date)}.jsonl`;
const file = path.join(this.dirPath, fileName);

const historyItem: CommandHistoryItem = {
date: getDayDate(date),
cursorlessVersion: this.cursorlessVersion,
command: sanitizeCommand(command),
};
const data = JSON.stringify(historyItem) + "\n";

await fs.appendFile(file, data, "utf8");
}

private evaluateSetting() {
this.active =
vscode.workspace
.getConfiguration(settingSection)
.get<boolean>(settingName) ?? false;
}

dispose() {
this.disposable.dispose();
}
}

export const DisabledCommandHistory: CommandHistory = {
async append(command: CommandComplete) {},
dispose() {},
};

function sanitizeCommand(command: CommandComplete): CommandComplete {
// TODO: Sanitize action payload
const { spokenForm, ...rest } = command;
return rest;
}

function getMonthDate(date: Date): string {
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}`;
}

function getDayDate(date: Date): string {
return `${getMonthDate(date)}-${pad(date.getDate())}`;
}

function pad(num: number): string {
return num.toString().padStart(2, "0");
}
2 changes: 2 additions & 0 deletions packages/cursorless-vscode/src/ide/vscode/VscodeIDE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class VscodeIDE implements IDE {
readonly messages: VscodeMessages;
readonly clipboard: VscodeClipboard;
readonly capabilities: VscodeCapabilities;
readonly cursorlessVersion: string;
private flashHandler: VscodeFlashHandler;
private highlights: VscodeHighlights;
private editorMap;
Expand All @@ -53,6 +54,7 @@ export class VscodeIDE implements IDE {
this.flashHandler = new VscodeFlashHandler(this, this.highlights);
this.capabilities = new VscodeCapabilities();
this.editorMap = new WeakMap<vscode.TextEditor, VscodeTextEditorImpl>();
this.cursorlessVersion = extensionContext.extension.packageJSON.version;
}

async showQuickPick(
Expand Down
Loading