p-doom/crowd-code-dataset-0.2 huggingface dataset:
[content] src/extension.ts (typescript)
	const editor = vscode.window.activeTextEditor;
	if (!editor) { return; }
	disposePreviewDecorations();

	// Only preview the next text edit action (insert/delete/replace)
	const next = plan.find(a => a.kind === 'editInsert' || a.kind === 'editDelete' || a.kind === 'editReplace');
	if (!next) {
		previewVisible = false;
		vscode.commands.executeCommand('setContext', UI_CONTEXT_KEY, false);
		currentPlan = plan;
		return;
	}

	const oneLinePreview = (t: string) => {
		const idx = t.indexOf('
');
		const first = idx === -1 ? t : t.slice(0, idx) + ' …';
		return first.length > 80 ? first.slice(0, 77) + '…' : first;
	};

	if (next.kind === 'editInsert') {
		const pos = new vscode.Position(next.position[0], next.position[1]);
		decorationInsertType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: `${oneLinePreview(next.text)}`,
				color: new vscode.ThemeColor('charts.purple'),
				fontStyle: 'italic',
				fontWeight: '600',
			}
		});
		editor.setDecorations(decorationInsertType, [{ range: new vscode.Range(pos, pos) }]);
		currentInsertPreview = undefined;
	} else if (next.kind === 'editDelete') {
		const range = new vscode.Range(
			new vscode.Position(next.range.start[0], next.range.start[1]),
			new vscode.Position(next.range.end[0], next.range.end[1])
		);
		decorationDeleteType = vscode.window.createTextEditorDecorationType({
			backgroundColor: 'rgba(255, 60, 60, 0.18)',
			border: '1px solid rgba(255, 60, 60, 0.35)',
			textDecoration: 'line-through'
		});
		editor.setDecorations(decorationDeleteType, [{ range }]);
		currentInsertPreview = undefined;
	} else if (next.kind === 'editReplace') {
		const range = new vscode.Range(
			new vscode.Position(next.range.start[0], next.range.start[1]),
			new vscode.Position(next.range.end[0], next.range.end[1])
		);
		decorationReplaceType = vscode.window.createTextEditorDecorationType({
			backgroundColor: 'rgba(255,165,0,0.15)',
			border: '1px dashed rgba(255,165,0,0.45)',
		});
		editor.setDecorations(decorationReplaceType, [{ range }]);
		// Show full multi-line replacement as per-line overlay at the start of each line
		const docLineCount = editor.document.lineCount;
		const replacementLines = next.text.split(/
?
/);
		decorationReplacePreviewTextType = vscode.window.createTextEditorDecorationType({
			before: {
				color: new vscode.ThemeColor('charts.purple'),
				fontStyle: 'italic',
				fontWeight: '600'
			}
		});
		const previewDecorations: vscode.DecorationOptions[] = [];
		for (let i = 0; i < replacementLines.length; i++) {
			const targetLine = Math.min(next.range.start[0] + i, Math.max(0, docLineCount - 1));
			const pos = new vscode.Position(targetLine, 0);
			previewDecorations.push({
				range: new vscode.Range(pos, pos),
				renderOptions: {
					before: {
						contentText: replacementLines[i]
					}
				}
			});
		}
		editor.setDecorations(decorationReplacePreviewTextType, previewDecorations);
		currentInsertPreview = undefined;
	}
[content] src/extension.ts (typescript)
	const items: (vscode.QuickPickItem & { index: number })[] = plan.map((action, index) => {
		switch (action.kind) {
			case 'showTextDocument':
				return { index, label: '$(file) Focus active text document' };
			case 'setSelections':
				{
					const cursors = action.selections.map(s => `(${s.start[0]}, ${s.start[1]})`).join(', ');
					return { index, label: `$(cursor) Move cursor to ${cursors}` };
				}
			case 'editInsert':
				return { index, label: `$(pencil) Insert "${action.text.replace(/
/g, '\
')}" at (${action.position[0]}, ${action.position[1]})` };
			case 'terminalShow':
				return { index, label: '$(terminal) Focus terminal' };
			case 'terminalSendText':
				return { index, label: `$(terminal) Run "${action.text}" in terminal` };
		}
	});
    if (!previewQuickPick) {
        previewQuickPick = vscode.window.createQuickPick<(vscode.QuickPickItem & { index: number })>();
		previewQuickPick.title = 'crowd-pilot: preview';
		previewQuickPick.matchOnDetail = true;
		previewQuickPick.ignoreFocusOut = true;
		previewQuickPick.canSelectMany = false;
        previewQuickPick.onDidAccept(async () => {
            const qp = previewQuickPick!;
            const selected = qp.selectedItems?.[0];
            qp.hide();
            if (selected) {
                await executePlan([plan[selected.index]]);
                vscode.window.showInformationMessage('Action executed');
            }
        });
		previewQuickPick.onDidHide(() => {
			previewVisible = false;
			vscode.commands.executeCommand('setContext', UI_CONTEXT_KEY, false);
			try { previewQuickPick?.dispose(); } catch {}
			previewQuickPick = undefined;
		});
	}
	previewQuickPick.items = items;
	previewQuickPick.placeholder = 'Press Tab to run all, Enter for selected, or Esc to hide';
	previewQuickPick.show();
[content] src/extension.ts (typescript)
let decorationInsertType: vscode.TextEditorDecorationType | undefined;
let decorationDeleteType: vscode.TextEditorDecorationType | undefined;
let decorationReplaceType: vscode.TextEditorDecorationType | undefined;
let decorationReplaceOriginalType: vscode.TextEditorDecorationType | undefined;
let decorationReplaceNewType: vscode.TextEditorDecorationType | undefined;
let mockStep = 0;
let suppressAutoPreview = false;
let currentReplacePreview: undefined;
let currentInsertPreview: undefined;

function disposePreviewDecorations() {
	try { decorationInsertType?.dispose(); } catch {}
	try { decorationDeleteType?.dispose(); } catch {}
	try { decorationReplaceType?.dispose(); } catch {}
	try { decorationReplaceOriginalType?.dispose(); } catch {}
	try { decorationReplaceNewType?.dispose(); } catch {}
	decorationInsertType = undefined;
	decorationDeleteType = undefined;
	decorationReplaceType = undefined;
	decorationReplaceOriginalType = undefined;
	decorationReplaceNewType = undefined;
}
[content] src/extension.ts (typescript)
	// Auto-preview listeners
	const onSelChange = vscode.window.onDidChangeTextEditorSelection((e) => {
		if (e.textEditor === vscode.window.activeTextEditor) {
			suppressAutoPreview = false;
			autoShowNextAction();
		}
	});
	const onActiveChange = vscode.window.onDidChangeActiveTextEditor(() => {
		suppressAutoPreview = false;
		autoShowNextAction();
	});
	const onDocChange = vscode.workspace.onDidChangeTextDocument((e) => {
		if (vscode.window.activeTextEditor?.document === e.document) {
			suppressAutoPreview = false;
			autoShowNextAction();
		}
	});

	context.subscriptions.push(hideUi, sglangTest, modelRun, testRun, previewNoop, onSelChange, onActiveChange, onDocChange);
[content] src/extension.ts (typescript)
let decorationInsertType: vscode.TextEditorDecorationType | undefined;
let decorationDeleteType: vscode.TextEditorDecorationType | undefined;
let decorationReplaceType: vscode.TextEditorDecorationType | undefined;
let decorationReplaceBlockType: vscode.TextEditorDecorationType | undefined;
let mockStep = 0;
let suppressAutoPreview = false;

function disposePreviewDecorations() {
	try { decorationInsertType?.dispose(); } catch {}
	try { decorationDeleteType?.dispose(); } catch {}
	try { decorationReplaceType?.dispose(); } catch {}
	try { decorationReplaceBlockType?.dispose(); } catch {}
	decorationInsertType = undefined;
	decorationDeleteType = undefined;
	decorationReplaceType = undefined;
	decorationReplaceBlockType = undefined;
}
[content] src/extension.ts (typescript)
	if (suppress) {
		suppressAutoPreview = true;
	}
}

// -------------------- Hardcoded single-step actions --------------------
function getHardcodedNextAction(editor: vscode.TextEditor): PlannedAction | undefined {
	const cursor = editor.selection.active;
	const doc = editor.document;
	const lineCount = doc.lineCount;
	const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));

	// Step 0: Insert multiline content two lines below the cursor (start of target line)
	if (mockStep === 0) {
		const targetLine = clamp(cursor.line + 2, 0, Math.max(0, lineCount - 1));
		return {
			kind: 'editInsert',
			position: [targetLine, 0],
			text: '/* crowd-pilot: insert start */
line A
line B
/* crowd-pilot: insert end */
'
		};
	}
	// Step 1: Replace a two-line range three and four lines below the cursor
	if (mockStep === 1) {
		const startLine = clamp(cursor.line + 3, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 1, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		const replacement = [
			'/* crowd-pilot: replacement */',
			'REPLACED LINE 1',
			'REPLACED LINE 2'
		].join('
');
		return { kind: 'editReplace', range, text: replacement };
	}
	// Step 2: Delete a three-line range six to eight lines below the cursor
	if (mockStep === 2) {
		const startLine = clamp(cursor.line + 6, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 2, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		return { kind: 'editDelete', range };
	}
	return undefined;
}

function advanceMockStep(): void {
	mockStep = (mockStep + 1) % 3;
}

function autoShowNextAction(): void {
	if (suppressAutoPreview) { return; }
	const editor = vscode.window.activeTextEditor;
	if (!editor) { return; }
	const next = getHardcodedNextAction(editor);
	if (next) {
		showPreviewUI([next]);
	} else {
		hidePreviewUI();
	}
}

class ReplacePreviewCodeLensProvider implements vscode.CodeLensProvider {
	private emitter = new vscode.EventEmitter<void>();
	public onDidChangeCodeLenses = this.emitter.event;
	refresh(): void { this.emitter.fire(); }
	provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult<vscode.CodeLens[]> {
		if (!previewVisible || !currentReplacePreview) { return []; }
		if (document.uri.toString() !== currentReplacePreview.uri.toString()) { return []; }
		const startLine = currentReplacePreview.range.start.line;
		const range = new vscode.Range(startLine, 0, startLine, 0);
		const title = currentReplacePreview.text.length > 120
			? currentReplacePreview.text.slice(0, 117).replace(/\s+/g, ' ') + '…'
			: currentReplacePreview.text.replace(/\s+/g, ' ');
		const cmd: vscode.Command = {
			title,
			command: 'crowd-pilot.previewNoop',
			tooltip: 'Replacement preview'
		};
		return [new vscode.CodeLens(range, cmd)];
	}
[content] src/extension.ts (typescript)
	if (suppress) {
		suppressAutoPreview = true;
	}
}

// -------------------- Hardcoded single-step actions --------------------
function getHardcodedNextAction(editor: vscode.TextEditor): PlannedAction | undefined {
	const cursor = editor.selection.active;
	const doc = editor.document;
	const lineCount = doc.lineCount;
	const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));

	// Step 0: Insert multiline content two lines below the cursor (start of target line)
	if (mockStep === 0) {
		const targetLine = clamp(cursor.line + 2, 0, Math.max(0, lineCount - 1));
		return {
			kind: 'editInsert',
			position: [targetLine, 0],
			text: '/* crowd-pilot: insert start */
line A
line B
/* crowd-pilot: insert end */
'
		};
	}
	// Step 1: Replace a two-line range three and four lines below the cursor
	if (mockStep === 1) {
		const startLine = clamp(cursor.line + 3, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 1, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		const replacement = [
			'/* crowd-pilot: replacement */',
			'REPLACED LINE 1',
			'REPLACED LINE 2'
		].join('
');
		return { kind: 'editReplace', range, text: replacement };
	}
	// Step 2: Delete a three-line range six to eight lines below the cursor
	if (mockStep === 2) {
		const startLine = clamp(cursor.line + 6, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 2, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		return { kind: 'editDelete', range };
	}
	return undefined;
}

function advanceMockStep(): void {
	mockStep = (mockStep + 1) % 3;
}

function autoShowNextAction(): void {
	if (suppressAutoPreview) { return; }
	const editor = vscode.window.activeTextEditor;
	if (!editor) { return; }
	const next = getHardcodedNextAction(editor);
	if (next) {
		showPreviewUI([next]);
	} else {
		hidePreviewUI();
	}
[content] src/extension.ts (typescript)
		const blockDeco: vscode.DecorationOptions[] = [];
		// We insert the block before the start line of the range
		const startLine = range.start.line;
		
		// We can't easily "push" lines down with decorations. 
		// But we can show the replacement text *overlaying* or *before* the text.
		// If we want a "pop up" feel that is always visible, maybe we can use a large 'before' attachment on the first line?
		// VS Code allows `innerText` to span? No.
		// Let's try iterating and adding a decoration for each line of the replacement text, 
		// effectively stacking them above the start line? 
		// No, multiple 'before' on the same range usually overlap or fail.
		
		// ALTERNATIVE: Use a single decoration with `before` contentText set to the first line, 
		// and if multiline, we might be stuck. 
		// WAIT: We can use `renderOptions` with `after` on the PREVIOUS line? No.
		
		// Let's use the valid approach for multiline virtual text:
		// We can't really inject new lines that shift content.
		// But we can display the replacement text *inline* if it's small, or use a hover.
		// User specifically rejected hover and CodeLens.
		// What if we just display the text in the 'before' content property but replace newlines with `
` symbol?
		// That might be hard to read for blocks.
		
		// Let's try a best-effort block display:
		// We will attach a decoration to the start of the range.
		// Its 'before' content will be the full text, with newlines replaced by a visible newline symbol/spacer?
		// OR we accept that we can only show single-line previews easily.
		
		// Let's go with the "diff view" style:
		// Show the new text in Green (purple here) above the old text.
		// Since we can't inject lines, we'll just format it as a single block string if possible, or truncate.
		// User said: "replacement code lens displays the entire replacement text above the first line". 
		// This implies they saw the block and didn't like the CodeLens UI specifically? 
		// Or they DID like seeing the text but not the CodeLens?
		// "we need to switch from codelense ... to something else".
		
		// Let's use a decoration that puts the text before the range, but format it nicely.
		// Since we can't do real multiline, we'll join with " ⏎ " to show it's multiple lines.
[content] src/extension.ts (typescript)
		// Show replacement block before the range
		decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
			before: {
				contentText: next.text, // This won't work for multiline text directly in contentText
				color: new vscode.ThemeColor('charts.purple'),
				fontStyle: 'italic',
				fontWeight: '600'
			}
		});
		
		// We need to handle multiline replacement carefully. 
		// VScode decorations don't support multiline 'contentText' well for block rendering.
		// Instead, we split lines and use a block decoration or multiple line decorations.
		// A cleaner way for "block" preview is to use a separate decoration that injects content.
		// However, simple 'contentText' strips newlines.
		// Let's use a hack: for multiline, we just show "Replacement:
<content>" 
		// but since we want it visible without hover, we use a loop to render lines if needed,
		// or just use the first line with ellipsis if it's too long?
		// No, user wants to see the replacement.
		
		// Actually, standard approach for "virtual text" blocks is using `before` on the first line 
		// but passing the full text string only works if it doesn't contain newlines or if we use multiple decorations.
		// Let's try rendering each line of the replacement as a virtual line above the target.
[content] src/extension.ts (typescript)
		// Show replacement block on the line after the replaced range
		const lines = next.text.split(/
?
/);
		const oneLineBlock = next.text.replace(/
?
/g, ' ⏎ ');
		
		// Determine target for the "lines after" decoration
		const docLineCount = editor.document.lineCount;
		const endLine = range.end.line;
		
		if (endLine + 1 < docLineCount) {
			// Attach 'before' decoration to the start of the NEXT line
			const nextLineStart = new vscode.Position(endLine + 1, 0);
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				before: {
					contentText: `↳ [Replacement]: ${oneLineBlock}`,
					color: new vscode.ThemeColor('charts.purple'),
					fontStyle: 'italic',
					fontWeight: '600',
					backgroundColor: 'rgba(100, 0, 100, 0.15)',
					margin: '0 0 0 20px'
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(nextLineStart, nextLineStart) }]);
		} else {
			// EOF: Attach 'after' decoration to the end of the current line
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				after: {
					contentText: `  ↳ [Replacement]: ${oneLineBlock}`,
					color: new vscode.ThemeColor('charts.purple'),
					fontStyle: 'italic',
					fontWeight: '600',
					backgroundColor: 'rgba(100, 0, 100, 0.15)',
					margin: '0 0 0 20px'
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(range.end, range.end) }]);
		}
[content] src/extension.ts (typescript)
		const fullBlock = next.text;
		
		// CSS-escape the text for the 'content' property:
		// - Escape double quotes
		// - Replace newlines with \A (CSS newline)
		const cssContent = fullBlock
			.replace(/"/g, '\\"')
			.replace(/
?
/g, '\\A ');
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "\\A   ↳ [Replacement]:\\A ${cssContent}"; border: 1px solid ${new vscode.ThemeColor('charts.purple')}; padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "↳ [Replacement]:\\A ${cssContent}"; border: 1px solid ${new vscode.ThemeColor('charts.purple')}; padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "\\A   ↳ [Replacement]:\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "↳ [Replacement]:\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
	if (next.kind === 'terminalShow') {
		const cursor = editor.selection.active;
		decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: '',
				color: new vscode.ThemeColor('charts.purple'),
				backgroundColor: new vscode.ThemeColor('editor.background'),
				fontStyle: 'italic',
				fontWeight: '600',
				margin: '0 0 0 20px',
				textDecoration: `none; display: block; white-space: pre; content: "↳ Focus Terminal"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
			}
		});
		editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(cursor, cursor) }]);
	} else if (next.kind === 'editInsert') {
[content] src/extension.ts (typescript)
	// Only preview the next text edit action (insert/delete/replace/terminalShow)
	const next = plan.find(a => a.kind === 'editInsert' || a.kind === 'editDelete' || a.kind === 'editReplace' || a.kind === 'terminalShow');
[content] src/extension.ts (typescript)
	} else if (next.kind === 'terminalSendText') {
		const cursor = editor.selection.active;
		const cmd = next.text.replace(/"/g, '\\"').replace(/
?
/g, '\\A ');
		decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: '',
				color: new vscode.ThemeColor('charts.purple'),
				backgroundColor: new vscode.ThemeColor('editor.background'),
				fontStyle: 'italic',
				fontWeight: '600',
				margin: '0 0 0 20px',
				textDecoration: `none; display: block; white-space: pre; content: "↳ Execute in Terminal:\\A ${cmd}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
			}
		});
		editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(cursor, cursor) }]);
[content] src/extension.ts (typescript)
	// Only preview the next text edit action (insert/delete/replace/terminalShow/terminalSendText)
	const next = plan.find(a => a.kind === 'editInsert' || a.kind === 'editDelete' || a.kind === 'editReplace' || a.kind === 'terminalShow' || a.kind === 'terminalSendText');
[content] src/extension.ts (typescript)
		const fullBlock = next.text;
		const cssContent = fullBlock
			.replace(/"/g, '\\"')
			.replace(/
?
/g, '\\A ');

		const docLineCount = editor.document.lineCount;
		const endLine = pos.line;

		if (endLine + 1 < docLineCount) {
			const nextLineStart = new vscode.Position(endLine + 1, 0);
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				before: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(nextLineStart, nextLineStart) }]);
		} else {
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				after: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(pos, pos) }]);
		}
[content] src/extension.ts (typescript)
		decorationInsertType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: `${trimText(next.text)}`,
				color: new vscode.ThemeColor('charts.purple'),
				fontStyle: 'italic',
				fontWeight: '600',
			}
		});
		editor.setDecorations(decorationInsertType, [{ range: new vscode.Range(pos, pos) }]);
[content] src/extension.ts (typescript)
	} else if (next.kind === 'editInsert') {
		const pos = new vscode.Position(next.position[0], next.position[1]);
		const fullBlock = next.text;
		const cssContent = fullBlock
			.replace(/"/g, '\\"')
			.replace(/
?
/g, '\\A ');

		const docLineCount = editor.document.lineCount;
		const endLine = pos.line;

		if (endLine + 1 < docLineCount) {
			const nextLineStart = new vscode.Position(endLine + 1, 0);
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				before: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(nextLineStart, nextLineStart) }]);
		} else {
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				after: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(pos, pos) }]);
		}
[content] src/extension.ts (typescript)
				textDecoration: `none; display: block; white-space: pre; content: "↳ Execute in Terminal:\\A ${cmd}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
	// Only preview the next text edit action (insert/delete/replace/terminalSendText)
	const next = plan.find(a => a.kind === 'editInsert' || a.kind === 'editDelete' || a.kind === 'editReplace' || a.kind === 'terminalSendText');
[content] src/extension.ts (typescript)
	} else if (next.kind === 'terminalSendText') {
		const cursor = editor.selection.active;
		const cmd = next.text.replace(/"/g, '\\"').replace(/
?
/g, '\\A ');
		decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: '',
				color: new vscode.ThemeColor('charts.purple'),
				backgroundColor: new vscode.ThemeColor('editor.background'),
				fontStyle: 'italic',
				fontWeight: '600',
				margin: '0 0 0 20px',
				textDecoration: `none; display: block; white-space: pre; content: "↳ Execute in Terminal:\\A ${cmd}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
			}
		});
		editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(cursor, cursor) }]);
	} else if (next.kind === 'editInsert') {
		const pos = new vscode.Position(next.position[0], next.position[1]);
		decorationInsertType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: `${trimText(next.text)}`,
				color: new vscode.ThemeColor('charts.purple'),
				fontStyle: 'italic',
				fontWeight: '600',
			}
		});
		editor.setDecorations(decorationInsertType, [{ range: new vscode.Range(pos, pos) }]);
[content] src/extension.ts (typescript)
				textDecoration: `none; display: block; white-space: pre; content: "↳ Focus Terminal"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
	} else if (next.kind === 'editInsert') {
		const pos = new vscode.Position(next.position[0], next.position[1]);
		const fullBlock = next.text;
		const cssContent = fullBlock
			.replace(/"/g, '\\"')
			.replace(/
?
/g, '\\A ');

		const docLineCount = editor.document.lineCount;
		const endLine = pos.line;

		if (endLine + 1 < docLineCount) {
			const nextLineStart = new vscode.Position(endLine + 1, 0);
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				before: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					// Add border-top to visualize the insertion point
					textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); border-top: 2px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(nextLineStart, nextLineStart) }]);
		} else {
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				after: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0 0 0 20px',
					// Add border-top to visualize the insertion point
					textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); border-top: 2px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(pos, pos) }]);
		}
[content] src/extension.ts (typescript)
						textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none; z-index: 1000; position: relative;`
[content] src/extension.ts (typescript)
						textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none; z-index: 1000; position: relative;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "↳ Execute in Terminal:\\A ${cmd}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none; z-index: 1000; position: relative;`
[content] src/extension.ts (typescript)
						textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
						textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
					textDecoration: `none; display: block; white-space: pre; content: "↳ Execute in Terminal:\\A ${cmd}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
[content] src/extension.ts (typescript)
			// For insertion, we want the preview to appear EXACTLY at the insertion point.
			// If inserting at [N, 0], it should appear ABOVE line N.
			// We use a 'before' decoration on the line itself.
			decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
				before: {
					contentText: '',
					color: new vscode.ThemeColor('charts.purple'),
					backgroundColor: new vscode.ThemeColor('editor.background'),
					fontStyle: 'italic',
					fontWeight: '600',
					margin: '0',
					textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none; z-index: 1000; position: relative;`
				}
			});
			editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(pos, pos) }]);
[content] src/extension.ts (typescript)
			const docLineCount = editor.document.lineCount;
			const endLine = pos.line;
	
			if (endLine + 1 < docLineCount) {
				const nextLineStart = new vscode.Position(endLine + 1, 0);
				decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
					before: {
						contentText: '',
						color: new vscode.ThemeColor('charts.purple'),
						backgroundColor: new vscode.ThemeColor('editor.background'),
						fontStyle: 'italic',
						fontWeight: '600',
						margin: '0',
						// Add border-top to visualize the insertion point
						textDecoration: `none; display: block; white-space: pre; content: "${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
					}
				});
				editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(nextLineStart, nextLineStart) }]);
			} else {
				decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
					after: {
						contentText: '',
						color: new vscode.ThemeColor('charts.purple'),
						backgroundColor: new vscode.ThemeColor('editor.background'),
						fontStyle: 'italic',
						fontWeight: '600',
						margin: '0',
						// Add border-top to visualize the insertion point
						textDecoration: `none; display: block; white-space: pre; content: "\\A ${cssContent}"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none;`
					}
				});
				editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(pos, pos) }]);
			}
[content] src/extension.ts (typescript)
		
		// To fully delete the lines including the newline, we target the start of the next line.
		let endPosLine = endLine + 1;
		let endPosChar = 0;
		
		if (endPosLine >= lineCount) {
			// If deleting the last line(s), just go to the end of the document
			endPosLine = lineCount - 1;
			endPosChar = doc.lineAt(endPosLine).range.end.character;
		}
[content] src/extension.ts (typescript)
	if (next.kind === 'setSelections') {
		// For setSelections, we only preview the primary selection's start/active position
		const selection = next.selections[0];
		const targetPos = new vscode.Position(selection.start[0], selection.start[1]);
		
		decorationReplaceBlockType = vscode.window.createTextEditorDecorationType({
			after: {
				contentText: '',
				color: new vscode.ThemeColor('charts.purple'),
				backgroundColor: new vscode.ThemeColor('editor.background'),
				fontStyle: 'italic',
				fontWeight: '600',
				margin: '0',
				textDecoration: `none; display: block; white-space: pre; content: "↳ Move Cursor Here"; border: 1px solid var(--vscode-charts-purple); padding: 4px; border-radius: 4px; box-shadow: 0 4px 8px rgba(0,0,0,0.25); pointer-events: none; position: relative;`
			}
		});
		// If target is EOF/empty line, we might need 'after' or 'before'.
		// 'after' on the target position usually works if line exists.
		editor.setDecorations(decorationReplaceBlockType, [{ range: new vscode.Range(targetPos, targetPos) }]);
	} else if (next.kind === 'terminalSendText') {
[content] src/extension.ts (typescript)
	// Step 4: Move Cursor to End of File
	if (mockStep === 4) {
		const lastLine = doc.lineCount - 1;
		const lastChar = doc.lineAt(lastLine).range.end.character;
		return {
			kind: 'setSelections',
			selections: [{ start: [lastLine, lastChar], end: [lastLine, lastChar] }]
		};
	}