change cell language with cell change events.

This commit is contained in:
rebornix 2021-02-16 19:41:30 -08:00
parent b3f8737839
commit 79b8259abb
2 changed files with 110 additions and 20 deletions

View file

@ -135,7 +135,7 @@ suite('Notebook API tests', function () {
id: 'mainKernel',
label: 'Notebook Test Kernel',
isPreferred: true,
supportedLanguages: ['typescript'],
supportedLanguages: ['typescript', 'javascript'],
executeAllCells: async (_document: vscode.NotebookDocument) => {
const edit = new vscode.WorkspaceEdit();
@ -174,7 +174,7 @@ suite('Notebook API tests', function () {
id: 'secondaryKernel',
label: 'Notebook Secondary Test Kernel',
isPreferred: false,
supportedLanguages: ['typescript'],
supportedLanguages: ['typescript', 'javascript'],
executeAllCells: async (_document: vscode.NotebookDocument) => {
const edit = new vscode.WorkspaceEdit();
edit.replaceNotebookCellOutput(_document.uri, 0, [new vscode.NotebookCellOutput([
@ -471,6 +471,30 @@ suite('Notebook API tests', function () {
await saveFileAndCloseAll(resource);
});
test('change cell language', async function () {
assertInitalState();
const resource = await createRandomFile('', undefined, '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
assert.strictEqual(vscode.window.activeNotebookEditor?.document.cells[0].language, 'typescript');
assert.strictEqual(vscode.window.activeNotebookEditor?.document.cells[0].cellKind, vscode.NotebookCellKind.Code);
await withEvent(vscode.notebook.onDidChangeCellLanguage, async event => {
await vscode.commands.executeCommand('notebook.cell.changeLanguage', { start: 0, end: 1 }, 'javascript');
await event;
assert.strictEqual(vscode.window.activeNotebookEditor?.document.cells[0].language, 'javascript');
});
// switch to markdown will change the cell kind
await withEvent(vscode.notebook.onDidChangeNotebookCells, async event => {
await vscode.commands.executeCommand('notebook.cell.changeLanguage', { start: 0, end: 1 }, 'markdown');
await event;
assert.strictEqual(vscode.window.activeNotebookEditor?.document.cells[0].language, 'markdown');
assert.strictEqual(vscode.window.activeNotebookEditor?.document.cells[0].cellKind, vscode.NotebookCellKind.Markdown);
});
await saveAllFilesAndCloseAll(resource);
});
test('edit API (replaceCells)', async function () {
assertInitalState();
const resource = await createRandomFile('', undefined, '.vsctestnb');

View file

@ -1607,19 +1607,81 @@ interface ILanguagePickInput extends IQuickPickItem {
description: string;
}
export class ChangeCellLanguageAction extends NotebookCellAction {
interface IChangeCellContext extends INotebookCellActionContext {
// TODO@rebornix : `cells`
// range: ICellRange;
language?: string;
}
export class ChangeCellLanguageAction extends NotebookCellAction<ICellRange> {
constructor() {
super({
id: CHANGE_CELL_LANGUAGE,
title: localize('changeLanguage', 'Change Cell Language'),
description: {
description: localize('changeLanguage', 'Change Cell Language'),
args: [
{
name: 'range',
description: 'The cell range',
schema: {
'type': 'object',
'required': ['start', 'end'],
'properties': {
'start': {
'type': 'number'
},
'end': {
'type': 'number'
}
}
}
},
{
name: 'language',
description: 'The target cell language',
schema: {
'type': 'string'
}
}
]
}
});
}
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
this.showLanguagePicker(accessor, context);
protected getCellContextFromArgs(accessor: ServicesAccessor, context?: ICellRange, ...additionalArgs: any[]): IChangeCellContext | undefined {
if (!context || typeof context.start !== 'number' || typeof context.end !== 'number' || context.start >= context.end) {
return;
}
const language = additionalArgs.length && typeof additionalArgs[0] === 'string' ? additionalArgs[0] : undefined;
const activeEditorContext = this.getEditorContextFromArgsOrActive(accessor);
if (!activeEditorContext || !activeEditorContext.notebookEditor.viewModel || context.start >= activeEditorContext.notebookEditor.viewModel.viewCells.length) {
return;
}
const cells = activeEditorContext.notebookEditor.viewModel.viewCells;
// TODO@rebornix, support multiple cells
return {
notebookEditor: activeEditorContext.notebookEditor,
cell: cells[context.start],
language
};
}
private async showLanguagePicker(accessor: ServicesAccessor, context: INotebookCellActionContext) {
async runWithContext(accessor: ServicesAccessor, context: IChangeCellContext): Promise<void> {
if (context.language) {
await this.setLanguage(context, context.language);
} else {
await this.showLanguagePicker(accessor, context);
}
}
private async showLanguagePicker(accessor: ServicesAccessor, context: IChangeCellContext) {
const topItems: ILanguagePickInput[] = [];
const mainItems: ILanguagePickInput[] = [];
@ -1671,21 +1733,25 @@ export class ChangeCellLanguageAction extends NotebookCellAction {
const selection = await quickInputService.pick(picks, { placeHolder: localize('pickLanguageToConfigure', "Select Language Mode") }) as ILanguagePickInput | undefined;
if (selection && selection.languageId) {
if (selection.languageId === 'markdown' && context.cell?.language !== 'markdown') {
const newCell = await changeCellToKind(CellKind.Markdown, { cell: context.cell, notebookEditor: context.notebookEditor }, 'markdown');
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
} else if (selection.languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markdown) {
await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, selection.languageId);
} else {
const index = context.notebookEditor.viewModel.notebookDocument.cells.indexOf(context.cell.model);
context.notebookEditor.viewModel.notebookDocument.applyEdits(
context.notebookEditor.viewModel.notebookDocument.versionId,
[{ editType: CellEditType.CellLanguage, index, language: selection.languageId }],
true, undefined, () => undefined, undefined
);
await this.setLanguage(context, selection.languageId);
}
}
private async setLanguage(context: IChangeCellContext, languageId: string) {
if (languageId === 'markdown' && context.cell?.language !== 'markdown') {
const newCell = await changeCellToKind(CellKind.Markdown, { cell: context.cell, notebookEditor: context.notebookEditor }, 'markdown');
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
} else if (languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markdown) {
await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, languageId);
} else {
const index = context.notebookEditor.viewModel.notebookDocument.cells.indexOf(context.cell.model);
context.notebookEditor.viewModel.notebookDocument.applyEdits(
context.notebookEditor.viewModel.notebookDocument.versionId,
[{ editType: CellEditType.CellLanguage, index, language: languageId }],
true, undefined, () => undefined, undefined
);
}
}