All files / commands renumber-notebook-cells.ts

0% Statements 0/48
0% Branches 0/25
0% Functions 0/2
0% Lines 0/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102                                                                                                                                                                                                           
import * as vscode from 'vscode';
import { container } from 'tsyringe';
import { ServiceToken } from '@src/services/tokens';
import { DocumentContextService } from '@src/services/document/document-context-service';
import { ReferenceUpdateService } from '@src/services/core/reference-update-service';
import { WorkspaceUri } from '@src/providers/workspace-uri';
import { resolveNotebookFromContext } from '../utilities/vscode/notebook';
 
export const renumberNotebookCells = {
	id: 'mentor.command.renumberNotebookCells',
	handler: async (context?: any) => {
		const notebook = resolveNotebookFromContext(context);
 
		if (!notebook) {
			vscode.window.showWarningMessage('No notebook is currently open.');
			return;
		}
 
		// Collect only the cells that carry an auto-generated slug, in visual order.
		const autoCells = notebook.getCells().filter(c => c.metadata?.slugIsAuto === true);
 
		if (autoCells.length === 0) {
			vscode.window.showInformationMessage('There are no automatically numbered cells.');
			return;
		}
 
		const contextService = container.resolve<DocumentContextService>(ServiceToken.DocumentContextService);
 
		// Build the rename map: old IRI → new IRI.
		const changes = new Map<string, string>();
		const edits: vscode.NotebookEdit[] = [];
		const updatedContexts: Set<string> = new Set(); // Track which cell contexts were updated
		let counter = 0;
 
		for (const cell of notebook.getCells()) {
			if (cell.metadata?.slugIsAuto !== true) {
				continue;
			}
 
			counter++;
 
			const newSlug = `cell-${counter}`;
			const oldSlug: string = cell.metadata?.slug ?? '';
 
			if (oldSlug === newSlug) {
				continue;
			}
 
			// Build workspace IRI change.
			const oldIri = WorkspaceUri.toWorkspaceUri(cell.document.uri, oldSlug)?.toString();
			const newIri = WorkspaceUri.toWorkspaceUri(cell.document.uri, newSlug)?.toString();
 
			if (oldIri && newIri && oldIri !== newIri) {
				changes.set(oldIri, newIri);
			}
 
			// Prepare notebook metadata edit.
			const newMetadata = { ...cell.metadata, slug: newSlug, slugIsAuto: true };
			edits.push(vscode.NotebookEdit.updateCellMetadata(cell.index, newMetadata));
 
			// Update the document context slug immediately.
			const cellContext = contextService.contexts[cell.document.uri.toString()];
 
			if (cellContext) {
				cellContext.slug = newSlug;
				updatedContexts.add(cell.document.uri.toString());
			}
		}
 
		if (edits.length === 0) {
			vscode.window.showInformationMessage('All cells are already numbered correctly.');
			return;
		}
 
		// Apply all metadata edits as one atomic WorkspaceEdit.
		const workspaceEdit = new vscode.WorkspaceEdit();
		workspaceEdit.set(notebook.uri, edits);
 
		await vscode.workspace.applyEdit(workspaceEdit);
 
		// Update all workspace: URI references across the workspace.
		if (changes.size > 0) {
			const referenceService = container.resolve<ReferenceUpdateService>(ServiceToken.ReferenceUpdateService);
 
			await referenceService.batchUpdate(changes, notebook.uri);
		}
 
		// Fire context change events for updated cells so code lenses and other providers re-evaluate.
		for (const cellUri of updatedContexts) {
			const context = contextService.contexts[cellUri];
			
			if (context) {
				(contextService as any)._onDidChangeDocumentContext?.fire(context);
			}
		}
 
		const message = `Renumbered ${edits.length} cell${edits.length === 1 ? '' : 's'}`;
 
		vscode.window.setStatusBarMessage(message, 3000);
	}
};