From dfbd729fa4a6bce83ed6915ba5c359a7a4f6dda9 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Tue, 24 Dec 2024 23:45:58 -0500 Subject: [PATCH] nightly progress --- .../platform/void/common/llmMessageTypes.ts | 14 +- .../void/browser/inlineDiffsService.ts | 407 +++++++++++------- .../contrib/void/browser/quickEditActions.ts | 97 +---- 3 files changed, 272 insertions(+), 246 deletions(-) diff --git a/src/vs/platform/void/common/llmMessageTypes.ts b/src/vs/platform/void/common/llmMessageTypes.ts index 5bc92e24..c1e46671 100644 --- a/src/vs/platform/void/common/llmMessageTypes.ts +++ b/src/vs/platform/void/common/llmMessageTypes.ts @@ -17,14 +17,14 @@ export type LLMMessage = { content: string; } -export type LLMFeatureSelection = { - featureName: 'Ctrl+K', - range: IRange +export type ServiceSendLLMFeatureParams = { + featureName: 'Ctrl+K'; + range: IRange; } | { - featureName: 'Ctrl+L', + featureName: 'Ctrl+L'; } | { - featureName: 'Autocomplete', - range: IRange + featureName: 'Autocomplete'; + range: IRange; } // params to the true sendLLMMessage function @@ -54,7 +54,7 @@ export type ServiceSendLLMMessageParams = { logging: { loggingName: string, }; -} & LLMFeatureSelection +} & ServiceSendLLMFeatureParams // can't send functions across a proxy, use listeners instead export type BlockedMainLLMMessageParams = 'onText' | 'onFinalMessage' | 'onError' | 'abortRef' diff --git a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts index 87039031..d20d770f 100644 --- a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts +++ b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts @@ -5,7 +5,7 @@ import { Disposable } from '../../../../base/common/lifecycle.js'; import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'; -import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; +import { createDecorator, IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; import { ICodeEditor, IOverlayWidget, IViewZone } from '../../../../editor/browser/editorBrowser.js'; // import { IUndoRedoService } from '../../../../platform/undoRedo/common/undoRedo.js'; @@ -26,11 +26,14 @@ import { ILanguageService } from '../../../../editor/common/languages/language.j import * as dom from '../../../../base/browser/dom.js'; import { Widget } from '../../../../base/browser/ui/widget.js'; import { URI } from '../../../../base/common/uri.js'; -import { LLMFeatureSelection, ServiceSendLLMMessageParams } from '../../../../platform/void/common/llmMessageTypes.js'; +import { ServiceSendLLMFeatureParams } from '../../../../platform/void/common/llmMessageTypes.js'; import { IConsistentItemService } from './helperServices/consistentItemService.js'; import { inlineDiff_systemMessage } from './prompt/prompts.js'; import { ILLMMessageService } from '../../../../platform/void/common/llmMessageService.js'; +import { IPosition } from '../../../../editor/common/core/position.js'; +import { mountCtrlK } from '../browser/react/out/ctrl-k-tsx/index.js' +import { QuickEditPropsType } from './quickEditActions.js'; const configOfBG = (color: Color) => { return { dark: color, light: color, hcDark: color, hcLight: color, } @@ -52,62 +55,99 @@ const sweepIdxBG = new Color(new RGBA(100, 100, 100, .5)); registerColor('void.sweepIdxBG', configOfBG(sweepIdxBG), '', true); + +// similar to ServiceLLM +export type StartStreamingOpts = { + featureName: 'Ctrl+K'; + diffareaid: string; // id of the CtrlK area +} | { + featureName: 'Ctrl+L'; +} | { + featureName: 'Autocomplete'; + range: IRange; +} + + + + export type Diff = { diffid: number; diffareaid: number; // the diff area this diff belongs to, "computed" } & ComputedDiff + + // _ means anything we don't include if we clone it // DiffArea.originalStartLine is the line in originalCode (not the file) -type DiffArea = { + +type CommonZoneProps = { diffareaid: number; - originalCode: string; startLine: number; endLine: number; - shouldHighlight: boolean; // should visually highlight this DiffArea _URI: URI; // typically we get the URI from model - _diffOfId: Record; // diffid -> diff in this DiffArea -} & ({ + _removeStylesFns: Set; // these don't remove diffs or this diffArea, only their styles + +} + +type CtrlKZone = { + type: 'CtrlKZone'; + originalCode?: undefined; + userText: string; +} & CommonZoneProps + + +type DiffZone = { + type: 'DiffZone', + originalCode: string; + _diffOfId: Record; // diffid -> diff in this DiffArea _sweepState: { isStreaming: true; + streamRequestIdRef: { current: string | null }; line: number; } | { isStreaming: false; + streamRequestIdRef?: undefined; line: null; }; -}) + userText?: undefined; +} & CommonZoneProps + + + +// called DiffArea for historical purposes, we can rename to something like TextRegion if we want +type DiffArea = CtrlKZone | DiffZone const diffAreaSnapshotKeys = [ + 'type', 'diffareaid', 'originalCode', 'startLine', 'endLine', - 'shouldHighlight', + 'userText', ] as const satisfies (keyof DiffArea)[] -type DiffAreaSnapshot = Pick +type DiffAreaSnapshot = Pick type HistorySnapshot = { snapshottedDiffAreaOfId: Record; entireFileCode: string; -} & - ({ - type: 'Ctrl+K'; - ctrlKText: string; - } | { - type: 'Ctrl+L'; - }) +} & ({ + type: 'Ctrl+K'; + ctrlKText: string; +} | { + type: 'Ctrl+L'; +}) export interface IInlineDiffsService { readonly _serviceBrand: undefined; - startStreaming(params: LLMFeatureSelection, str: string): void; + startStreaming(params: , str: string): void; } export const IInlineDiffsService = createDecorator('inlineDiffAreasService'); @@ -117,12 +157,13 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { // URI <--> model - removeStylesFnsOfURI: Record> = {} // functions that remove the styles of this uri diffAreasOfURI: Record> = {} diffAreaOfId: Record = {}; diffOfId: Record = {}; // redundant with diffArea._diffs + + _diffareaidPool = 0 // each diffarea has an id _diffidPool = 0 // each diff has an id @@ -134,6 +175,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { @ILanguageService private readonly _langService: ILanguageService, @ILLMMessageService private readonly _llmMessageService: ILLMMessageService, @IConsistentItemService private readonly _zoneStyleService: IConsistentItemService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { super(); @@ -142,9 +184,6 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { if (!(model.uri.fsPath in this.diffAreasOfURI)) { this.diffAreasOfURI[model.uri.fsPath] = new Set(); } - if (!(model.uri.fsPath in this.removeStylesFnsOfURI)) { - this.removeStylesFnsOfURI[model.uri.fsPath] = new Set(); - } // when the user types, realign diff areas and re-render them this._register( @@ -178,19 +217,10 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { let initializeEditor = (editor: ICodeEditor) => { const uri = editor.getModel()?.uri ?? null if (uri) this._refreshDiffsInURI(uri) - - - // this isn't relevant anymore because consistentItemService takes care of it - // called when the user switches tabs (typically there's only 1 editor on the screen, it switches between models, make sure you understand this) - // this._register(editor.onDidChangeModel((e) => { - // if (e.newModelUrl) this._refreshDiffsInURI(e.newModelUrl) - // if (e.oldModelUrl) this._clearAllDiffsAndStyles(e.oldModelUrl) - // })) } // add listeners for all existing editors + listen for editor being added for (let editor of this._editorService.listCodeEditors()) { initializeEditor(editor) } this._register(this._editorService.onCodeEditorAdd(editor => { initializeEditor(editor) })) - // this._register(this._editorService.onCodeEditorRemove(editor => { console.log('REMOVE EDITOR'); initializeEditor(editor) })) } @@ -221,18 +251,61 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { for (const diffareaid of this.diffAreasOfURI[uri.fsPath]) { const diffArea = this.diffAreaOfId[diffareaid] - // add sweep styles to the diffArea - if (diffArea._sweepState.isStreaming) { - // sweepLine ... sweepLine - const fn1 = this._addLineDecoration(model, diffArea._sweepState.line, diffArea._sweepState.line, 'void-sweepIdxBG') - // sweepLine+1 ... endLine - const fn2 = this._addLineDecoration(model, diffArea._sweepState.line + 1, diffArea.endLine, 'void-sweepBG') - this.removeStylesFnsOfURI[uri.fsPath].add(() => { fn1?.(); fn2?.(); }) + if (diffArea.type === 'DiffZone') { + // add sweep styles to the diffZone + if (diffArea._sweepState.isStreaming) { + // sweepLine ... sweepLine + const fn1 = this._addLineDecoration(model, diffArea._sweepState.line, diffArea._sweepState.line, 'void-sweepIdxBG') + // sweepLine+1 ... endLine + const fn2 = this._addLineDecoration(model, diffArea._sweepState.line + 1, diffArea.endLine, 'void-sweepBG') + diffArea._removeStylesFns.add(() => { fn1?.(); fn2?.(); }) + } } - // highlight the diffArea - if (diffArea.shouldHighlight) { + // highlight the ctrlK zone + if (diffArea.type === 'CtrlKZone') { + + const consistentZoneId = this._zoneStyleService.addConsistentItemToURI({ + uri, + fn: (editor) => { + const domNode = document.createElement('div'); + domNode.style.zIndex = '1' + + // domNode.className = 'void-redBG' + const viewZone: IViewZone = { + // afterLineNumber: computedDiff.startLine - 1, + afterLineNumber: 1, + heightInPx: 100, + // heightInLines: 1, + // minWidthInPx: 200, + domNode: domNode, + suppressMouseDown: false, + }; + + + let zoneId: string | null = null + editor.changeViewZones(accessor => { zoneId = accessor.addZone(viewZone) }) + const fn1 = () => editor.changeViewZones(accessor => { if (zoneId) accessor.removeZone(zoneId) }) + + // on resize + domNode.onresize = () => { + viewZone.heightInPx = domNode.clientHeight + editor.changeViewZones(accessor => { if (zoneId) accessor.layoutZone(zoneId) }) + } + + this._instantiationService.invokeFunction(accessor => { + const props: QuickEditPropsType = { + quickEditId: diffArea.diffareaid, + } + mountCtrlK(domNode, accessor, props) + }) + + return () => { fn1(); } + }, + }) + diffArea._removeStylesFns.add(() => this._zoneStyleService.removeConsistentItemFromURI(consistentZoneId)); + const fn = this._addLineDecoration(model, diffArea.startLine, diffArea.endLine, 'void-highlightBG') - this.removeStylesFnsOfURI[uri.fsPath].add(() => fn?.()); + diffArea._removeStylesFns.add(() => fn?.()); } } } @@ -377,20 +450,38 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { const { snapshottedDiffAreaOfId, entireFileCode: entireModelCode } = structuredClone(snapshot) // don't want to destroy the snapshot // delete all current decorations (diffs, sweep styles) so we don't have any unwanted leftover decorations - this._clearAllDiffsAndAllStyles(uri) + this._clearAllEffects(uri) + + // __TODO__ stop streaming if currently streaming + + // restore diffAreaOfId and diffAreasOfModelId this.diffAreaOfId = {} this.diffAreasOfURI[uri.fsPath].clear() for (const diffareaid in snapshottedDiffAreaOfId) { - this.diffAreaOfId[diffareaid] = { - ...snapshottedDiffAreaOfId[diffareaid], - _diffOfId: {}, - _URI: uri, - _sweepState: { - isStreaming: false, - line: null, - }, + + const snapshottedDiffArea = snapshottedDiffAreaOfId[diffareaid] + + if (snapshottedDiffArea.type === 'DiffZone') { + this.diffAreaOfId[diffareaid] = { + ...snapshottedDiffArea as DiffAreaSnapshot, + type: 'DiffZone', + _diffOfId: {}, + _URI: uri, + _sweepState: { + isStreaming: false, + line: null, + } as const, + _removeStylesFns: new Set(), + } + } + else if (snapshottedDiffArea.type === 'CtrlKZone') { + this.diffAreaOfId[diffareaid] = { + ...snapshottedDiffArea as DiffAreaSnapshot, + _URI: uri, + _removeStylesFns: new Set(), + } } this.diffAreasOfURI[uri.fsPath].add(diffareaid) } @@ -425,34 +516,43 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { // delete diffOfId and diffArea._diffOfId private _deleteDiff(diff: Diff) { const diffArea = this.diffAreaOfId[diff.diffareaid] + if (diffArea.type !== 'DiffZone') return delete diffArea._diffOfId[diff.diffid] delete this.diffOfId[diff.diffid] } - private _deleteDiffs(diffArea: DiffArea) { - for (const diffid in diffArea._diffOfId) { - const diff = diffArea._diffOfId[diffid] + private _deleteDiffs(diffZone: DiffZone) { + for (const diffid in diffZone._diffOfId) { + const diff = diffZone._diffOfId[diffid] this._deleteDiff(diff) } } - // clears styles of DiffAreas too - private _clearAllDiffsAndAllStyles(uri: URI) { + private _deleteEffects(diffArea: DiffArea) { + // clear diffZone effects (diffs) + if (diffArea.type === 'DiffZone') + this._deleteDiffs(diffArea) + else if (diffArea.type === 'CtrlKZone') { + + } + + diffArea._removeStylesFns.forEach(removeStyles => removeStyles()) + } + + // clears all Diffs (and their styles) and all styles of DiffAreas + private _clearAllEffects(uri: URI) { for (let diffareaid of this.diffAreasOfURI[uri.fsPath]) { const diffArea = this.diffAreaOfId[diffareaid] - this._deleteDiffs(diffArea) + this._deleteEffects(diffArea) + diffArea._removeStylesFns.clear() } - for (const removeStyleFn of this.removeStylesFnsOfURI[uri.fsPath]) { - removeStyleFn() - } - this.removeStylesFnsOfURI[uri.fsPath].clear() } // delete all diffs, update diffAreaOfId, update diffAreasOfModelId private _deleteDiffArea(diffArea: DiffArea) { - this._deleteDiffs(diffArea) + // we had clear all diffs, but not really needed delete this.diffAreaOfId[diffArea.diffareaid] this.diffAreasOfURI[diffArea._URI.fsPath].delete(diffArea.diffareaid.toString()) } @@ -530,9 +630,10 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { if (content === null) return // 1. clear Diffs and styles - this._clearAllDiffsAndAllStyles(uri) + this._clearAllEffects(uri) // 2. recompute all diffs on each editor with this URI + const fullFileText = this._readURI(uri) ?? '' @@ -540,25 +641,28 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { for (let diffareaid of this.diffAreasOfURI[uri.fsPath]) { const diffArea = this.diffAreaOfId[diffareaid] - console.log('DA start and end:', diffArea.startLine, diffArea.endLine) - const newDiffAreaCode = fullFileText.split('\n').slice((diffArea.startLine - 1), (diffArea.endLine - 1) + 1).join('\n') - const computedDiffs = findDiffs(diffArea.originalCode, newDiffAreaCode) + if (diffArea.type === 'DiffZone') { - for (let computedDiff of computedDiffs) { - const diffid = this._diffidPool++ + console.log('DA start and end:', diffArea.startLine, diffArea.endLine) + const newDiffAreaCode = fullFileText.split('\n').slice((diffArea.startLine - 1), (diffArea.endLine - 1) + 1).join('\n') + const computedDiffs = findDiffs(diffArea.originalCode, newDiffAreaCode) - // create a Diff of it - const newDiff: Diff = { - ...computedDiff, - diffid: diffid, - diffareaid: diffArea.diffareaid, + for (let computedDiff of computedDiffs) { + const diffid = this._diffidPool++ + + // create a Diff of it + const newDiff: Diff = { + ...computedDiff, + diffid: diffid, + diffareaid: diffArea.diffareaid, + } + + const fn = this._addDiffStylesToURI(uri, newDiff) + diffArea._removeStylesFns.add(fn) + + this.diffOfId[diffid] = newDiff + diffArea._diffOfId[diffid] = newDiff } - - const fn = this._addDiffStylesToURI(uri, newDiff) - this.removeStylesFnsOfURI[uri.fsPath].add(fn) - - this.diffOfId[diffid] = newDiff - diffArea._diffOfId[diffid] = newDiff } // update styles on this DiffArea @@ -570,16 +674,17 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { // @throttle(100) - private _writeDiffAreaLLMText(diffArea: DiffArea, newCodeSoFar: string) { + private _writeDiffZoneLLMText(diffArea: DiffArea, llmText: string, latestCurrentFileEnd: IPosition, newPosition: IPosition) { + if (diffArea.type !== 'DiffZone') return // ----------- 1. Write the new code to the document ----------- // figure out where to highlight based on where the AI is in the stream right now, use the last diff to figure that out const uri = diffArea._URI - const computedDiffs = findDiffs(diffArea.originalCode, newCodeSoFar) + const computedDiffs = findDiffs(diffArea.originalCode, llmText) // if not streaming, just write the new code if (!diffArea._sweepState.isStreaming) { - this._writeText(uri, newCodeSoFar, + this._writeText(uri, llmText, { startLineNumber: diffArea.startLine, startColumn: 1, endLineNumber: diffArea.endLine, endColumn: Number.MAX_SAFE_INTEGER, } // 1-indexed ) } @@ -617,7 +722,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { diffArea._sweepState.line = newFileEndLine // lines are 1-indexed - const newFileTop = newCodeSoFar.split('\n').slice(0, (newFileEndLine - 1)).join('\n') + const newFileTop = llmText.split('\n').slice(0, (newFileEndLine - 1)).join('\n') const oldFileBottom = diffArea.originalCode.split('\n').slice((oldFileStartLine - 1), Infinity).join('\n') const newCode = `${newFileTop}\n${oldFileBottom}` @@ -635,7 +740,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { - private async _initializeStream(opts: LLMFeatureSelection, diffRepr: string, uri: URI,) { + private _initializeStream(featureParams: ServiceSendLLMFeatureParams, diffRepr: string, uri: URI,): DiffZone | undefined { // diff area begin and end line const numLines = this._getNumLines(uri) @@ -660,6 +765,10 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { if (currentFileStr === null) return const originalCode = currentFileStr.split('\n').slice((beginLine - 1), (endLine - 1) + 1).join('\n') + + let streamRequestIdRef: { current: string | null } = { current: null } + + // add to history const { onFinishEdit } = this._addToHistory(uri) @@ -667,20 +776,22 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService { const diffareaid = this._diffareaidPool++ // in ctrl+L the start and end lines are the full document - const diffArea: DiffArea = { + const diffArea: DiffZone = { + type: 'DiffZone', diffareaid: diffareaid, // originalStartLine: beginLine, // originalEndLine: endLine, originalCode: originalCode, startLine: beginLine, endLine: endLine, // starts out the same as the current file - shouldHighlight: false, _URI: uri, _sweepState: { isStreaming: true, + streamRequestIdRef, line: 1, }, _diffOfId: {}, // added later + _removeStylesFns: new Set(), } // console.log('adding uri.fspath', uri.fsPath, diffArea.diffareaid.toString()) @@ -704,45 +815,42 @@ Please finish writing the new file by applying the diff to the original file. Re ` - await new Promise((resolve, reject) => { + const latestCurrentFileEnd: IPosition = { lineNumber: 1, column: 1 } + const latestOriginalFileStart: IPosition = { lineNumber: 1, column: 1 } - let streamRequestId: string | null = null + streamRequestIdRef.current = this._llmMessageService.sendLLMMessage({ + logging: { loggingName: 'streamChunk' }, + messages: [ + { role: 'system', content: inlineDiff_systemMessage, }, + // TODO include more context too + { role: 'user', content: promptContent, } + ], + onText: ({ newText, fullText }) => { + this._writeDiffZoneLLMText(diffArea, fullText, latestCurrentFileEnd, latestOriginalFileStart) + this._refreshDiffsInURI(uri) + }, + onFinalMessage: ({ fullText }) => { + this._writeText(uri, fullText, + { startLineNumber: diffArea.startLine, startColumn: 1, endLineNumber: diffArea.endLine, endColumn: Number.MAX_SAFE_INTEGER }, // 1-indexed + ) + diffArea._sweepState = { isStreaming: false, line: null } + this._refreshDiffsInURI(uri) + onFinishEdit() + }, + onError: (e) => { + console.error('Error rewriting file with diff', e); + // TODO indicate there was an error + if (streamRequestIdRef.current) + this._llmMessageService.abort(streamRequestIdRef.current) - const object: ServiceSendLLMMessageParams = { - logging: { loggingName: 'streamChunk' }, - messages: [ - { role: 'system', content: inlineDiff_systemMessage, }, - // TODO include more context too - { role: 'user', content: promptContent, } - ], - onText: ({ newText, fullText }) => { - this._writeDiffAreaLLMText(diffArea, fullText) - this._refreshDiffsInURI(uri) - }, - onFinalMessage: ({ fullText }) => { - this._writeText(uri, fullText, - { startLineNumber: diffArea.startLine, startColumn: 1, endLineNumber: diffArea.endLine, endColumn: Number.MAX_SAFE_INTEGER }, // 1-indexed - ) - diffArea._sweepState = { isStreaming: false, line: null } - this._refreshDiffsInURI(uri) - resolve(); - }, - onError: (e: any) => { - console.error('Error rewriting file with diff', e); - // TODO indicate there was an error - if (streamRequestId) - this._llmMessageService.abort(streamRequestId) - - diffArea._sweepState = { isStreaming: false, line: null } - resolve(); - }, - ...opts - } - - streamRequestId = this._llmMessageService.sendLLMMessage(object) + diffArea._sweepState = { isStreaming: false, line: null } + onFinishEdit() + }, + ...featureParams }) - onFinishEdit() + + return diffArea } @@ -751,49 +859,50 @@ Please finish writing the new file by applying the diff to the original file. Re - async startStreaming(opts: LLMFeatureSelection, userMessage: string) { - + async startStreaming(opts: StartStreamingOpts, userMessage: string) { const editor = this._editorService.getActiveCodeEditor() if (!editor) return - const uri = editor.getModel()?.uri if (!uri) return - // TODO reject all diffs in the diff area - // TODO deselect user's cursor - - this._initializeStream(opts, userMessage, uri) + const addedDiffZone = this._initializeStream(opts, userMessage, uri) + return addedDiffZone?.diffareaid } - interruptStreaming() { - // TODO add abort + private _stopIfStreaming(diffZone: DiffZone) { + } - addDiffArea({ uri, startLine, endLine, originalCode }: { uri: URI, startLine: number, endLine: number, originalCode: string }) { - const diffareaid = this._diffareaidPool++ + interruptStreaming(diffareaid: string) { + const diffArea = this.diffAreaOfId[diffareaid] - const diffArea: DiffArea = { - diffareaid: diffareaid, - originalCode, - startLine, - endLine, - shouldHighlight: true, - _URI: uri, - _sweepState: { - isStreaming: false, - line: null, - }, - _diffOfId: {}, - } + if (!diffArea) return + if (diffArea.type !== 'DiffZone') return + if (!diffArea._sweepState.isStreaming) return - this.diffAreasOfURI[uri.fsPath].add(diffArea.diffareaid.toString()) - this.diffAreaOfId[diffArea.diffareaid] = diffArea + const streamRequestId = diffArea._sweepState.streamRequestIdRef.current + if (streamRequestId) + this._llmMessageService.abort(streamRequestId) + + // __TODO__ update diffArea streamState here + don't elsewhere + // call undo - __TODO__ make this get called in undo and redo too + + this._undoRedoService.undo(diffArea._URI) + + } + + + + + + addCtrlK({ uri, range }: { uri: URI, range: IRange, }) { + + // TODO check if intersects with a current ctrl K, if so focus it - this._refreshDiffsInURI(uri) } @@ -810,6 +919,8 @@ Please finish writing the new file by applying the diff to the original file. Re const diffArea = this.diffAreaOfId[diffareaid] if (!diffArea) return + if (diffArea.type !== 'DiffZone') return + const uri = diffArea._URI // add to history @@ -877,6 +988,8 @@ Please finish writing the new file by applying the diff to the original file. Re const diffArea = this.diffAreaOfId[diffareaid] if (!diffArea) return + if (diffArea.type !== 'DiffZone') return + const uri = diffArea._URI // add to history diff --git a/src/vs/workbench/contrib/void/browser/quickEditActions.ts b/src/vs/workbench/contrib/void/browser/quickEditActions.ts index 9d5314a8..e3ea47c3 100644 --- a/src/vs/workbench/contrib/void/browser/quickEditActions.ts +++ b/src/vs/workbench/contrib/void/browser/quickEditActions.ts @@ -1,20 +1,11 @@ import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js'; -import { ICodeEditor, IViewZone } from '../../../../editor/browser/editorBrowser.js'; import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; -import { createDecorator, IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js'; +import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js'; import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js'; import { IMetricsService } from '../../../../platform/void/common/metricsService.js'; -import { Emitter, Event } from '../../../../base/common/event.js'; -// import { IInlineDiffService } from '../../../../editor/browser/services/inlineDiffService/inlineDiffService.js'; -import { Disposable } from '../../../../base/common/lifecycle.js'; -import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js'; -import { mountCtrlK } from './react/out/ctrl-k-tsx/index.js'; -import { URI } from '../../../../base/common/uri.js'; -type InitialZone = { uri: URI, startLine: number, selectedText: string, } - export type QuickEditPropsType = { quickEditId: number, } @@ -28,83 +19,6 @@ export type QuickEdit = { } -export interface IQuickEditService { - readonly _serviceBrand: undefined; - readonly onDidChangeState: Event; - addZone(zone: InitialZone): void; -} - -export const IQuickEditService = createDecorator('voidQuickEditService'); -class VoidQuickEditService extends Disposable implements IQuickEditService { - _serviceBrand: undefined; - - quickEditId: number = 0 - - private readonly _onDidChangeState = new Emitter(); - readonly onDidChangeState: Event = this._onDidChangeState.event; - - // state - // state: {} - - constructor( - // @IInlineDiffService private readonly _inlineDiffService: IInlineDiffService, - @ICodeEditorService private readonly _editorService: ICodeEditorService, - @IInstantiationService private readonly _instantiationService: IInstantiationService, - ) { - super(); - } - - addZone(zone: InitialZone) { - - const addZoneToEditor = (editor: ICodeEditor) => { - - const model = editor.getModel() - if (!model) return - - editor.changeViewZones(accessor => { - - const domNode = document.createElement('div'); - domNode.style.zIndex = '1' - - // domNode.className = 'void-redBG' - const viewZone: IViewZone = { - // afterLineNumber: computedDiff.startLine - 1, - afterLineNumber: 1, - heightInPx: 100, - // heightInLines: 1, - // minWidthInPx: 200, - domNode: domNode, - // marginDomNode: document.createElement('div'), // displayed to left - suppressMouseDown: false, - }; - - // const zoneId = - accessor.addZone(viewZone) - - this._instantiationService.invokeFunction(accessor => { - const props: QuickEditPropsType = { - quickEditId: this.quickEditId++, - } - mountCtrlK(domNode, accessor, props) - }) - - // disposeInThisEditorFns.push(() => { editor.changeViewZones(accessor => { if (zoneId) accessor.removeZone(zoneId) }) }) - }) - } - - - const editors = this._editorService.listCodeEditors().filter(editor => editor.getModel()?.uri.fsPath === zone.uri.fsPath) - for (const editor of editors) { - addZoneToEditor(editor) - } - } - -} - -registerSingleton(IQuickEditService, VoidQuickEditService, InstantiationType.Eager); - - - export const VOID_CTRL_K_ACTION_ID = 'void.ctrlKAction' registerAction2(class extends Action2 { constructor() { @@ -112,7 +26,6 @@ registerAction2(class extends Action2 { } async run(accessor: ServicesAccessor): Promise { - const quickEditService = accessor.get(IQuickEditService) const editorService = accessor.get(ICodeEditorService) const metricsService = accessor.get(IMetricsService) @@ -125,11 +38,11 @@ registerAction2(class extends Action2 { const selection = editor.getSelection() if (!selection) return; - const uri = model.uri - const startLine = selection.startLineNumber - const selectedText = model.getValueInRange(selection) + // const uri = model.uri + // const startLine = selection.startLineNumber + // const selectedText = model.getValueInRange(selection) - quickEditService.addZone({ uri, startLine, selectedText, }) + // quickEditService.addZone({ uri, startLine, selectedText, }) } });