Skip to content

Commit

Permalink
make sure to push an undo stop after each request (#213137)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken authored May 21, 2024
1 parent 601018a commit 89eb8a7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 57 deletions.
28 changes: 12 additions & 16 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ export class InlineChatController implements IEditorContribution {
return State.ACCEPT;
}

this._session.addInput(new SessionPrompt(input));
this._session.addInput(new SessionPrompt(request));

return State.SHOW_REQUEST;
}
Expand Down Expand Up @@ -669,7 +669,6 @@ export class InlineChatController implements IEditorContribution {
const progressiveEditsClock = StopWatch.create();
const progressiveEditsQueue = new Queue();

let lastLength = 0;


let message = Message.NONE;
Expand All @@ -684,6 +683,8 @@ export class InlineChatController implements IEditorContribution {
this._chatService.cancelCurrentRequestForSession(request.session.sessionId);
}));

let lastLength = 0;
let isFirstChange = true;

// apply edits
store.add(response.onDidChange(() => {
Expand All @@ -699,13 +700,6 @@ export class InlineChatController implements IEditorContribution {
return;
}

// if ("1") {
// return;
// }

// TODO@jrieken
const editsShouldBeInstant = false;

const edits = response.response.value.map(part => {
if (part.kind === 'textEditGroup' && isEqual(part.uri, this._session?.textModelN.uri)) {
return part.edits;
Expand All @@ -732,10 +726,12 @@ export class InlineChatController implements IEditorContribution {
// influence the time it takes to receive the changes and progressive typing will
// become infinitely fast
for (const edits of newEdits) {
await this._makeChanges(edits, editsShouldBeInstant
? undefined
: { duration: progressiveEditsAvgDuration.value, token: progressiveEditsCts.token }
);
await this._makeChanges(edits, {
duration: progressiveEditsAvgDuration.value,
token: progressiveEditsCts.token
}, isFirstChange);

isFirstChange = false;
}

// reshow the widget if the start position changed or shows at the wrong position
Expand Down Expand Up @@ -981,7 +977,7 @@ export class InlineChatController implements IEditorContribution {
}
}

private async _makeChanges(edits: TextEdit[], opts: ProgressingEditsOptions | undefined) {
private async _makeChanges(edits: TextEdit[], opts: ProgressingEditsOptions | undefined, undoStopBefore: boolean) {
assertType(this._session);
assertType(this._strategy);

Expand All @@ -1004,9 +1000,9 @@ export class InlineChatController implements IEditorContribution {
this._inlineChatSavingService.markChanged(this._session);
this._session.wholeRange.trackEdits(editOperations);
if (opts) {
await this._strategy.makeProgressiveChanges(editOperations, editsObserver, opts);
await this._strategy.makeProgressiveChanges(editOperations, editsObserver, opts, undoStopBefore);
} else {
await this._strategy.makeChanges(editOperations, editsObserver);
await this._strategy.makeChanges(editOperations, editsObserver, undoStopBefore);
}
this._ctxDidEdit.set(this._session.hasChangedText);

Expand Down
10 changes: 7 additions & 3 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ILogService } from 'vs/platform/log/common/log';
import { ChatModel, IChatResponseModel } from 'vs/workbench/contrib/chat/common/chatModel';
import { ChatModel, IChatRequestModel, IChatResponseModel } from 'vs/workbench/contrib/chat/common/chatModel';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';


Expand Down Expand Up @@ -279,9 +279,13 @@ export class Session {

export class SessionPrompt {

readonly value: string;

constructor(
readonly value: string,
) { }
readonly request: IChatRequestModel
) {
this.value = request.message.text;
}
}

export class SessionExchange {
Expand Down
78 changes: 40 additions & 38 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export abstract class EditModeStrategy {
protected readonly _onDidAccept = this._store.add(new Emitter<void>());
protected readonly _onDidDiscard = this._store.add(new Emitter<void>());

protected _editCount: number = 0;

readonly onDidAccept: Event<void> = this._onDidAccept.event;
readonly onDidDiscard: Event<void> = this._onDidDiscard.event;
Expand Down Expand Up @@ -133,38 +132,9 @@ export abstract class EditModeStrategy {
this._onDidDiscard.fire();
}

abstract makeProgressiveChanges(edits: ISingleEditOperation[], obs: IEditObserver, timings: ProgressingEditsOptions): Promise<void>;
abstract makeProgressiveChanges(edits: ISingleEditOperation[], obs: IEditObserver, timings: ProgressingEditsOptions, undoStopBefore: boolean): Promise<void>;

abstract makeChanges(edits: ISingleEditOperation[], obs: IEditObserver): Promise<void>;

protected async _makeChanges(edits: ISingleEditOperation[], obs: IEditObserver, opts: ProgressingEditsOptions | undefined, progress: Progress<IValidEditOperation[]> | undefined): Promise<void> {

// push undo stop before first edit
if (++this._editCount === 1) {
this._editor.pushUndoStop();
}

if (opts) {
// ASYNC
const durationInSec = opts.duration / 1000;
for (const edit of edits) {
const wordCount = countWords(edit.text ?? '');
const speed = wordCount / durationInSec;
// console.log({ durationInSec, wordCount, speed: wordCount / durationInSec });
const asyncEdit = asProgressiveEdit(new WindowIntervalTimer(this._zone.domNode), edit, speed, opts.token);
await performAsyncTextEdit(this._session.textModelN, asyncEdit, progress, obs);
}

} else {
// SYNC
obs.start();
this._session.textModelN.pushEditOperations(null, edits, (undoEdits) => {
progress?.report(undoEdits);
return null;
});
obs.stop();
}
}
abstract makeChanges(edits: ISingleEditOperation[], obs: IEditObserver, undoStopBefore: boolean): Promise<void>;

abstract undoChanges(altVersionId: number): Promise<void>;

Expand Down Expand Up @@ -216,10 +186,10 @@ export class PreviewStrategy extends EditModeStrategy {
await super._doApplyChanges(false);
}

override async makeChanges(edits: ISingleEditOperation[], obs: IEditObserver): Promise<void> {
override async makeChanges(): Promise<void> {
}

override async makeProgressiveChanges(edits: ISingleEditOperation[], obs: IEditObserver, opts: ProgressingEditsOptions): Promise<void> {
override async makeProgressiveChanges(): Promise<void> {
}

override async undoChanges(altVersionId: number): Promise<void> {
Expand Down Expand Up @@ -289,6 +259,7 @@ export class LiveStrategy extends EditModeStrategy {
private readonly _ctxCurrentChangeShowsDiff: IContextKey<boolean>;

private readonly _progressiveEditingDecorations: IEditorDecorationsCollection;
private _editCount: number = 0;

override acceptHunk: () => Promise<void> = () => super.acceptHunk();
override discardHunk: () => Promise<void> = () => super.discardHunk();
Expand Down Expand Up @@ -347,11 +318,11 @@ export class LiveStrategy extends EditModeStrategy {
await undoModelUntil(textModelN, altVersionId);
}

override async makeChanges(edits: ISingleEditOperation[], obs: IEditObserver): Promise<void> {
return this._makeChanges(edits, obs, undefined, undefined);
override async makeChanges(edits: ISingleEditOperation[], obs: IEditObserver, undoStopBefore: boolean): Promise<void> {
return this._makeChanges(edits, obs, undefined, undefined, undoStopBefore);
}

override async makeProgressiveChanges(edits: ISingleEditOperation[], obs: IEditObserver, opts: ProgressingEditsOptions): Promise<void> {
override async makeProgressiveChanges(edits: ISingleEditOperation[], obs: IEditObserver, opts: ProgressingEditsOptions, undoStopBefore: boolean): Promise<void> {

// add decorations once per line that got edited
const progress = new Progress<IValidEditOperation[]>(edits => {
Expand All @@ -371,7 +342,38 @@ export class LiveStrategy extends EditModeStrategy {

this._progressiveEditingDecorations.append(newDecorations);
});
return this._makeChanges(edits, obs, opts, progress);
return this._makeChanges(edits, obs, opts, progress, undoStopBefore);
}

private async _makeChanges(edits: ISingleEditOperation[], obs: IEditObserver, opts: ProgressingEditsOptions | undefined, progress: Progress<IValidEditOperation[]> | undefined, undoStopBefore: boolean): Promise<void> {

// push undo stop before first edit
if (undoStopBefore) {
this._editor.pushUndoStop();
}

this._editCount++;

if (opts) {
// ASYNC
const durationInSec = opts.duration / 1000;
for (const edit of edits) {
const wordCount = countWords(edit.text ?? '');
const speed = wordCount / durationInSec;
// console.log({ durationInSec, wordCount, speed: wordCount / durationInSec });
const asyncEdit = asProgressiveEdit(new WindowIntervalTimer(this._zone.domNode), edit, speed, opts.token);
await performAsyncTextEdit(this._session.textModelN, asyncEdit, progress, obs);
}

} else {
// SYNC
obs.start();
this._session.textModelN.pushEditOperations(null, edits, (undoEdits) => {
progress?.report(undoEdits);
return null;
});
obs.stop();
}
}

private readonly _hunkDisplayData = new Map<HunkInformation, HunkDisplayData>();
Expand Down

0 comments on commit 89eb8a7

Please sign in to comment.