Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new REPL notebook API #24029

Merged
merged 13 commits into from
Sep 20, 2024
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
"terminalDataWriteEvent",
"terminalExecuteCommandEvent",
"contribIssueReporter",
"notebookVariableProvider",
"codeActionAI"
"codeActionAI",
"notebookReplDocument",
"notebookVariableProvider"
],
"author": {
"name": "Microsoft Corporation"
Expand All @@ -47,7 +48,7 @@
"theme": "dark"
},
"engines": {
"vscode": "^1.94.0-20240913"
"vscode": "^1.94.0-20240918"
},
"enableTelemetry": false,
"keywords": [
Expand Down Expand Up @@ -1168,6 +1169,11 @@
{
"command": "python.execInREPLEnter",
"key": "enter",
"when": "!config.interactiveWindow.executeWithShiftEnter && activeEditor == 'workbench.editor.repl' && !inlineChatFocused"
},
{
"command": "python.execInInteractiveWindowEnter",
"key": "enter",
"when": "!config.interactiveWindow.executeWithShiftEnter && activeEditor == 'workbench.editor.interactive' && !inlineChatFocused"
},
{
Expand Down
1 change: 1 addition & 0 deletions src/client/common/application/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export interface ICommandNameArgumentTypeMapping extends ICommandNameWithoutArgu
[Commands.Start_Native_REPL]: [undefined | Uri];
[Commands.Exec_In_REPL]: [undefined | Uri];
[Commands.Exec_In_REPL_Enter]: [undefined | Uri];
[Commands.Exec_In_IW_Enter]: [undefined | Uri];
[Commands.Exec_In_Terminal]: [undefined, Uri];
[Commands.Exec_In_Terminal_Icon]: [undefined, Uri];
[Commands.Debug_In_Terminal]: [Uri];
Expand Down
1 change: 1 addition & 0 deletions src/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export namespace Commands {
export const Exec_In_REPL = 'python.execInREPL';
export const Exec_Selection_In_Django_Shell = 'python.execSelectionInDjangoShell';
export const Exec_In_REPL_Enter = 'python.execInREPLEnter';
export const Exec_In_IW_Enter = 'python.execInInteractiveWindowEnter';
export const Exec_Selection_In_Terminal = 'python.execSelectionInTerminal';
export const GetSelectedInterpreterPath = 'python.interpreterPath';
export const InstallJupyter = 'python.installJupyter';
Expand Down
2 changes: 1 addition & 1 deletion src/client/repl/nativeRepl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class NativeRepl implements Disposable {
this.replController.updateNotebookAffinity(this.notebookDocument, NotebookControllerAffinity.Default);
await selectNotebookKernel(notebookEditor, this.replController.id, PVSC_EXTENSION_ID);
if (code) {
await executeNotebookCell(this.notebookDocument, code);
await executeNotebookCell(notebookEditor, code);
}
}
}
Expand Down
46 changes: 21 additions & 25 deletions src/client/repl/replCommandHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
workspace,
} from 'vscode';
import { getExistingReplViewColumn } from './replUtils';
import { PVSC_EXTENSION_ID } from '../common/constants';

/**
* Function that opens/show REPL using IW UI.
Expand All @@ -23,29 +24,24 @@ export async function openInteractiveREPL(
notebookController: NotebookController,
notebookDocument: NotebookDocument | undefined,
): Promise<NotebookEditor> {
let notebookEditor: NotebookEditor | undefined;
let viewColumn = ViewColumn.Beside;

// Case where NotebookDocument (REPL document already exists in the tab)
if (notebookDocument) {
const existingReplViewColumn = getExistingReplViewColumn(notebookDocument);
const replViewColumn = existingReplViewColumn ?? ViewColumn.Beside;
notebookEditor = await window.showNotebookDocument(notebookDocument!, { viewColumn: replViewColumn });
viewColumn = existingReplViewColumn ?? viewColumn;
} else if (!notebookDocument) {
// Case where NotebookDocument doesnt exist, open new REPL tab
const interactiveWindowObject = (await commands.executeCommand(
'interactive.open',
{
preserveFocus: true,
viewColumn: ViewColumn.Beside,
},
undefined,
notebookController.id,
'Python REPL',
)) as { notebookEditor: NotebookEditor };
notebookEditor = interactiveWindowObject.notebookEditor;
notebookDocument = interactiveWindowObject.notebookEditor.notebook;
// Case where NotebookDocument doesnt exist, create a blank one.
notebookDocument = await workspace.openNotebookDocument('jupyter-notebook');
amunger marked this conversation as resolved.
Show resolved Hide resolved
}
return notebookEditor!;
const editor = window.showNotebookDocument(notebookDocument!, { viewColumn, asRepl: 'Python REPL' });
await commands.executeCommand('notebook.selectKernel', {
editor,
id: notebookController.id,
extension: PVSC_EXTENSION_ID,
});

return editor;
}

/**
Expand Down Expand Up @@ -73,13 +69,14 @@ export async function selectNotebookKernel(
* @param code
* @return Promise<void>
*/
export async function executeNotebookCell(notebookDocument: NotebookDocument, code: string): Promise<void> {
const { cellCount } = notebookDocument;
await addCellToNotebook(notebookDocument, code);
export async function executeNotebookCell(notebookEditor: NotebookEditor, code: string): Promise<void> {
const { notebook, replOptions } = notebookEditor;
const cellIndex = replOptions?.appendIndex ?? notebook.cellCount;
await addCellToNotebook(notebook, cellIndex, code);
// Execute the cell
commands.executeCommand('notebook.cell.execute', {
ranges: [{ start: cellCount, end: cellCount + 1 }],
document: notebookDocument.uri,
ranges: [{ start: cellIndex, end: cellIndex + 1 }],
document: notebook.uri,
});
}

Expand All @@ -89,11 +86,10 @@ export async function executeNotebookCell(notebookDocument: NotebookDocument, co
* @param code
*
*/
async function addCellToNotebook(notebookDocument: NotebookDocument, code: string): Promise<void> {
async function addCellToNotebook(notebookDocument: NotebookDocument, index: number, code: string): Promise<void> {
const notebookCellData = new NotebookCellData(NotebookCellKind.Code, code as string, 'python');
const { cellCount } = notebookDocument!;
// Add new cell to interactive window document
const notebookEdit = NotebookEdit.insertCells(cellCount, [notebookCellData]);
const notebookEdit = NotebookEdit.insertCells(index, [notebookCellData]);
const workspaceEdit = new WorkspaceEdit();
workspaceEdit.set(notebookDocument!.uri, [notebookEdit]);
await workspace.applyEdit(workspaceEdit);
Expand Down
56 changes: 35 additions & 21 deletions src/client/repl/replCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,29 +98,43 @@ export async function registerReplExecuteOnEnter(
): Promise<void> {
disposables.push(
commandManager.registerCommand(Commands.Exec_In_REPL_Enter, async (uri: Uri) => {
const interpreter = await interpreterService.getActiveInterpreter(uri);
if (!interpreter) {
commands.executeCommand(Commands.TriggerEnvironmentSelection, uri).then(noop, noop);
return;
}
await onInputEnter(uri, 'repl.execute', interpreterService, disposables);
}),
);
disposables.push(
commandManager.registerCommand(Commands.Exec_In_IW_Enter, async (uri: Uri) => {
await onInputEnter(uri, 'interactive.execute', interpreterService, disposables);
}),
);
}

const nativeRepl = await getNativeRepl(interpreter, disposables);
const completeCode = await nativeRepl?.checkUserInputCompleteCode(window.activeTextEditor);
const editor = window.activeTextEditor;
async function onInputEnter(
uri: Uri,
commandName: string,
interpreterService: IInterpreterService,
disposables: Disposable[],
): Promise<void> {
const interpreter = await interpreterService.getActiveInterpreter(uri);
if (!interpreter) {
commands.executeCommand(Commands.TriggerEnvironmentSelection, uri).then(noop, noop);
return;
}

if (editor) {
// Execute right away when complete code and Not multi-line
if (completeCode && !isMultiLineText(editor)) {
await commands.executeCommand('interactive.execute');
} else {
insertNewLineToREPLInput(editor);
const nativeRepl = await getNativeRepl(interpreter, disposables);
const completeCode = await nativeRepl?.checkUserInputCompleteCode(window.activeTextEditor);
const editor = window.activeTextEditor;

// Handle case when user enters on blank line, just trigger interactive.execute
if (editor && editor.document.lineAt(editor.selection.active.line).text === '') {
await commands.executeCommand('interactive.execute');
}
}
if (editor) {
// Execute right away when complete code and Not multi-line
if (completeCode && !isMultiLineText(editor)) {
await commands.executeCommand(commandName);
} else {
insertNewLineToREPLInput(editor);

// Handle case when user enters on blank line, just trigger interactive.execute
if (editor && editor.document.lineAt(editor.selection.active.line).text === '') {
await commands.executeCommand(commandName);
}
}),
);
}
}
}
2 changes: 1 addition & 1 deletion src/client/repl/replController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function createReplController(
const server = createPythonServer([interpreterPath], cwd);
disposables.push(server);

const controller = vscode.notebooks.createNotebookController('pythonREPL', 'interactive', 'Python REPL');
const controller = vscode.notebooks.createNotebookController('pythonREPL', 'jupyter-notebook', 'Python REPL');
Copy link

@anthonykim1 anthonykim1 Sep 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar question here - is interactive type not valid after the new REPL api?

controller.supportedLanguages = ['python'];
controller.supportsExecutionOrder = true;

Expand Down
33 changes: 33 additions & 0 deletions types/vscode.proposed.notebookReplDocument.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

declare module 'vscode' {

export interface NotebookDocumentShowOptions {
/**
* The notebook should be opened in a REPL editor,
* where the last cell of the notebook is an input box and the other cells are the read-only history.
* When the value is a string, it will be used as the label for the editor tab.
*/
readonly asRepl?: boolean | string | {
/**
* The label to be used for the editor tab.
*/
readonly label: string;
};
}

export interface NotebookEditor {
/**
* Information about the REPL editor if the notebook was opened as a repl.
*/
replOptions?: {
/**
* The index where new cells should be appended.
*/
appendIndex: number;
};
}
}
Loading