Skip to content

Commit 74f8a78

Browse files
authored
Merge pull request microsoft#157923 from amunger/interactiveExecute
add parameter to Interactive Execute to specify resource
2 parents bef747b + 08639eb commit 74f8a78

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

extensions/vscode-api-tests/src/singlefolder-tests/interactiveWindow.test.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Kernel, saveAllFilesAndCloseAll } from './notebook.api.test';
1212
export type INativeInteractiveWindow = { notebookUri: vscode.Uri; inputUri: vscode.Uri; notebookEditor: vscode.NotebookEditor };
1313

1414
async function createInteractiveWindow(kernel: Kernel) {
15-
const { notebookEditor } = (await vscode.commands.executeCommand(
15+
const { notebookEditor, inputUri } = (await vscode.commands.executeCommand(
1616
'interactive.open',
1717
// Keep focus on the owning file if there is one
1818
{ viewColumn: vscode.ViewColumn.Beside, preserveFocus: false },
@@ -21,7 +21,7 @@ async function createInteractiveWindow(kernel: Kernel) {
2121
undefined
2222
)) as unknown as INativeInteractiveWindow;
2323

24-
return notebookEditor;
24+
return { notebookEditor, inputUri };
2525
}
2626

2727
async function addCell(code: string, notebook: vscode.NotebookDocument) {
@@ -61,21 +61,26 @@ async function addCellAndRun(code: string, notebook: vscode.NotebookDocument, i:
6161
await saveAllFilesAndCloseAll();
6262
});
6363

64-
test('Can open an interactive window', async () => {
64+
test('Can open an interactive window and execute from input box', async () => {
6565
assert.ok(vscode.workspace.workspaceFolders);
66-
const notebookEditor = await createInteractiveWindow(defaultKernel);
66+
const { notebookEditor, inputUri } = await createInteractiveWindow(defaultKernel);
6767
assert.ok(notebookEditor);
6868

69-
// Try adding a cell and running it.
70-
await addCell('print foo', notebookEditor.notebook);
69+
const inputBox = vscode.window.visibleTextEditors.find(
70+
(e) => e.document.uri.path === inputUri.path
71+
);
72+
await inputBox!.edit((editBuilder) => {
73+
editBuilder.insert(new vscode.Position(0, 0), 'print foo');
74+
});
75+
await vscode.commands.executeCommand('interactive.execute', notebookEditor.notebook.uri);
7176

7277
assert.strictEqual(notebookEditor.notebook.cellCount, 1);
7378
assert.strictEqual(notebookEditor.notebook.cellAt(0).kind, vscode.NotebookCellKind.Code);
7479
});
7580

7681
test('Interactive window scrolls after execute', async () => {
7782
assert.ok(vscode.workspace.workspaceFolders);
78-
const notebookEditor = await createInteractiveWindow(defaultKernel);
83+
const { notebookEditor } = await createInteractiveWindow(defaultKernel);
7984
assert.ok(notebookEditor);
8085

8186
// Run and add a bunch of cells
@@ -90,13 +95,13 @@ async function addCellAndRun(code: string, notebook: vscode.NotebookDocument, i:
9095

9196
test('Interactive window has the correct kernel', async () => {
9297
assert.ok(vscode.workspace.workspaceFolders);
93-
const notebookEditor = await createInteractiveWindow(defaultKernel);
98+
const { notebookEditor } = await createInteractiveWindow(defaultKernel);
9499
assert.ok(notebookEditor);
95100

96101
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
97102

98103
// Create a new interactive window with a different kernel
99-
const notebookEditor2 = await createInteractiveWindow(secondKernel);
104+
const { notebookEditor: notebookEditor2 } = await createInteractiveWindow(secondKernel);
100105
assert.ok(notebookEditor2);
101106

102107
// Verify the kernel is the secondary one

src/vs/workbench/contrib/interactive/browser/interactive.contribution.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Schemas } from 'vs/base/common/network';
1212
import { extname } from 'vs/base/common/resources';
1313
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
1414
import { assertType } from 'vs/base/common/types';
15-
import { URI } from 'vs/base/common/uri';
15+
import { URI, UriComponents } from 'vs/base/common/uri';
1616
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
1717
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
1818
import { EditOperation } from 'vs/editor/common/core/editOperation';
@@ -462,15 +462,40 @@ registerAction2(class extends Action2 {
462462
}
463463
],
464464
icon: icons.executeIcon,
465-
f1: false
465+
f1: false,
466+
description: {
467+
description: 'Execute the Contents of the Input Box',
468+
args: [
469+
{
470+
name: 'resource',
471+
description: 'Interactive resource Uri',
472+
isOptional: true
473+
}
474+
]
475+
}
466476
});
467477
}
468478

469-
async run(accessor: ServicesAccessor): Promise<void> {
479+
async run(accessor: ServicesAccessor, context?: UriComponents): Promise<void> {
470480
const editorService = accessor.get(IEditorService);
471481
const bulkEditService = accessor.get(IBulkEditService);
472482
const historyService = accessor.get(IInteractiveHistoryService);
473-
const editorControl = editorService.activeEditorPane?.getControl() as { notebookEditor: NotebookEditorWidget | undefined; codeEditor: CodeEditorWidget } | undefined;
483+
let editorControl: { notebookEditor: NotebookEditorWidget | undefined; codeEditor: CodeEditorWidget } | undefined;
484+
if (context) {
485+
if (context.scheme === Schemas.vscodeInteractive) {
486+
const resourceUri = URI.revive(context);
487+
const editors = editorService.findEditors(resourceUri).filter(id => id.editor instanceof InteractiveEditorInput && id.editor.resource?.toString() === resourceUri.toString());
488+
if (editors.length) {
489+
const editorInput = editors[0].editor as InteractiveEditorInput;
490+
const currentGroup = editors[0].groupId;
491+
const editor = await editorService.openEditor(editorInput, currentGroup);
492+
editorControl = editor?.getControl() as { notebookEditor: NotebookEditorWidget | undefined; codeEditor: CodeEditorWidget } | undefined;
493+
}
494+
}
495+
}
496+
else {
497+
editorControl = editorService.activeEditorPane?.getControl() as { notebookEditor: NotebookEditorWidget | undefined; codeEditor: CodeEditorWidget } | undefined;
498+
}
474499

475500
if (editorControl && editorControl.notebookEditor && editorControl.codeEditor) {
476501
const notebookDocument = editorControl.notebookEditor.textModel;

src/vs/workbench/contrib/interactive/browser/interactiveEditor.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export class InteractiveEditor extends EditorPane {
104104
#notebookOptions: NotebookOptions;
105105
#editorMemento: IEditorMemento<InteractiveEditorViewState>;
106106
#groupListener = this._register(new DisposableStore());
107+
#runbuttonToolbar: ToolBar | undefined;
107108

108109
#onDidFocusWidget = this._register(new Emitter<void>());
109110
override get onDidFocus(): Event<void> { return this.#onDidFocusWidget.event; }
@@ -186,7 +187,7 @@ export class InteractiveEditor extends EditorPane {
186187

187188
#setupRunButtonToolbar(runButtonContainer: HTMLElement) {
188189
const menu = this._register(this.#menuService.createMenu(MenuId.InteractiveInputExecute, this.#contextKeyService));
189-
const toolbar = this._register(new ToolBar(runButtonContainer, this.#contextMenuService, {
190+
this.#runbuttonToolbar = this._register(new ToolBar(runButtonContainer, this.#contextMenuService, {
190191
getKeyBinding: action => this.#keybindingService.lookupKeybinding(action.id),
191192
actionViewItemProvider: action => {
192193
return createActionViewItem(this.#instantiationService, action);
@@ -199,7 +200,7 @@ export class InteractiveEditor extends EditorPane {
199200
const result = { primary, secondary };
200201

201202
createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, result);
202-
toolbar.setActions([...primary, ...secondary]);
203+
this.#runbuttonToolbar.setActions([...primary, ...secondary]);
203204
}
204205

205206
#createLayoutStyles(): void {
@@ -392,6 +393,9 @@ export class InteractiveEditor extends EditorPane {
392393

393394
await super.setInput(input, options, context, token);
394395
const model = await input.resolve();
396+
if (this.#runbuttonToolbar) {
397+
this.#runbuttonToolbar.context = input.resource;
398+
}
395399

396400
if (model === null) {
397401
throw new Error('?');

0 commit comments

Comments
 (0)