Skip to content

Support Untitled files and automatic *.Notebook.ps1 files #2919

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@
"onCommand:PowerShell.UnregisterExternalExtension",
"onCommand:PowerShell.GetPowerShellVersionDetails",
"onView:PowerShellCommands",
"onNotebookEditor:PowerShellNotebookMode"
"onNotebook:PowerShellNotebookModeDefault",
"onNotebookEditor:PowerShellNotebookModeDefault",
"onNotebook:PowerShellNotebookModeOption",
"onNotebookEditor:PowerShellNotebookModeOption"
Copy link
Member Author

Choose a reason for hiding this comment

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

in a few insider builds we can remove the onNotebookEditor ones as that will be deprecated.

],
"dependencies": {
"node-fetch": "^2.6.0",
Expand Down Expand Up @@ -113,10 +116,21 @@
},
"notebookProvider": [
{
"viewType": "PowerShellNotebookMode",
"viewType": "PowerShellNotebookModeDefault",
"displayName": "Powershell Notebook",
"selector": [
{
"filenamePattern": "*.Notebook.ps1"
}
],
"priority": "default"
},
{
"viewType": "PowerShellNotebookModeOption",
"displayName": "Powershell Notebook",
"selector": [
{
"excludeFileNamePattern": "*.Notebook.ps1",
"filenamePattern": "*.ps1"
}
],
Expand Down
58 changes: 52 additions & 6 deletions src/features/PowerShellNotebooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,40 @@ export class PowerShellNotebooksFeature extends LanguageClientConsumer {
}

public registerNotebookProviders() {
const options = {
transientOutputs: true,
transientMetadata: {
inputCollapsed: true,
outputCollapsed: true,
runState: true,
runStartTime: true,
executionOrder: true,
lastRunDuration: true,
statusMessage: true,
},
};

// Until vscode supports using the same view type with different priority,
// we register 2 of the same viewTypes.
// This one is used to open *.Notebook.ps1 files which automatically go straight to Notebook mode.
this.disposables.push(vscode.notebook.registerNotebookKernelProvider({
viewType: "PowerShellNotebookModeDefault"
}, this.notebookKernel));

this.disposables.push(vscode.notebook.registerNotebookContentProvider(
"PowerShellNotebookModeDefault",
this.notebookContentProvider,
options));

// This one is used to open *.ps1 files which will be opened in the default text editor first.
this.disposables.push(vscode.notebook.registerNotebookKernelProvider({
viewType: "PowerShellNotebookMode"
viewType: "PowerShellNotebookModeOption"
}, this.notebookKernel));

this.disposables.push(vscode.notebook.registerNotebookContentProvider(
"PowerShellNotebookMode",
this.notebookContentProvider));
"PowerShellNotebookModeOption",
this.notebookContentProvider,
options));
}

public dispose() {
Expand All @@ -55,8 +82,17 @@ export class PowerShellNotebooksFeature extends LanguageClientConsumer {

private static async EnableNotebookMode() {
const uri = vscode.window.activeTextEditor.document.uri;
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
await vscode.commands.executeCommand("vscode.openWith", uri, "PowerShellNotebookMode");

// If the file is an untitled file, then we can't close it.
if (!vscode.window.activeTextEditor.document.isUntitled) {
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
}

if (uri.fsPath?.endsWith(".Notebook.ps1")) {
await vscode.commands.executeCommand("vscode.openWith", uri, "PowerShellNotebookModeDefault");
} else {
await vscode.commands.executeCommand("vscode.openWith", uri, "PowerShellNotebookModeOption");
}
}

private static async DisableNotebookMode() {
Expand Down Expand Up @@ -95,8 +131,12 @@ class PowerShellNotebookContentProvider implements vscode.NotebookContentProvide
// load from backup if needed.
const actualUri = context.backupId ? vscode.Uri.parse(context.backupId) : uri;
this.logger.writeDiagnostic(`Opening Notebook: ${uri.toString()}`);
const isUntitled = uri.scheme !== "file";

const data = (await vscode.workspace.fs.readFile(actualUri)).toString();
// If we have an untitled file, get the contents from vscode instead of the file system.
const data: string = isUntitled
? (await vscode.workspace.openTextDocument(actualUri)).getText()
: (await vscode.workspace.fs.readFile(actualUri)).toString();

let lines: string[];
// store the line ending in the metadata of the document
Expand All @@ -117,6 +157,7 @@ class PowerShellNotebookContentProvider implements vscode.NotebookContentProvide
metadata: {
custom: {
lineEnding,
isUntitled,
}
}
};
Expand Down Expand Up @@ -374,6 +415,11 @@ class PowerShellNotebookKernel implements vscode.NotebookKernel, vscode.Notebook
await this.languageClient.sendRequest(EvaluateRequestType, {
expression: cell.document.getText(),
});

// Show the integrated console if it isn't already visible and
// scroll terminal to bottom so new output is visible
await vscode.commands.executeCommand("PowerShell.ShowSessionConsole", true);
await vscode.commands.executeCommand("workbench.action.terminal.scrollToBottom");
}

// Since executing a cell is a "fire and forget", there's no time for the user to cancel
Expand Down
30 changes: 28 additions & 2 deletions test/features/PowerShellNotebooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const notebookSimpleLineComments = vscode.Uri.file(
path.join(...notebookDir,"simpleLineComments.ps1"));
const notebookSimpleMixedComments = vscode.Uri.file(
path.join(...notebookDir,"simpleMixedComments.ps1"));
const notebookSimpleDotNotebook = vscode.Uri.file(
path.join(...notebookDir,"simple.Notebook.ps1"));

const notebookTestData = new Map<vscode.Uri, vscode.NotebookCellData[]>();

Expand Down Expand Up @@ -343,7 +345,7 @@ suite("PowerShellNotebooks tests", () => {
}

// Open an existing notebook ps1.
await vscode.commands.executeCommand("vscode.openWith", notebookSimpleMixedComments, "PowerShellNotebookMode");
await vscode.commands.executeCommand("vscode.openWith", notebookSimpleMixedComments, "PowerShellNotebookModeOption");

// Allow some time to pass to render the Notebook
await utils.sleep(5000);
Expand All @@ -369,7 +371,7 @@ suite("PowerShellNotebooks tests", () => {
}

// Open an existing notebook ps1.
await vscode.commands.executeCommand("vscode.openWith", notebookBlockCommentsWithTextOnSameLine, "PowerShellNotebookMode");
await vscode.commands.executeCommand("vscode.openWith", notebookBlockCommentsWithTextOnSameLine, "PowerShellNotebookModeOption");

// Allow some time to pass to render the Notebook
await utils.sleep(5000);
Expand All @@ -385,4 +387,28 @@ suite("PowerShellNotebooks tests", () => {
// Verify that saving does not mutate result.
assert.strictEqual(contentOfBackingFileBefore, contentOfBackingFileAfter);
}).timeout(20000);

test("Can open an untitled Notebook", async () => {
const doc = await vscode.workspace.openTextDocument({
language: "powershell",
content: `# asdf
gci`,
});

const notebookData = await notebookContentProvider.openNotebook(doc.uri, {});
assert.strictEqual(notebookData.cells.length, 2);
assert.strictEqual(notebookData.cells[0].cellKind, vscode.CellKind.Markdown);
assert.strictEqual(notebookData.cells[0].source, "asdf");
assert.strictEqual(notebookData.cells[1].cellKind, vscode.CellKind.Code);
assert.strictEqual(notebookData.cells[1].source, "gci");
}).timeout(20000);

test(".Notebook.ps1 files are opened automatically", async () => {
await vscode.commands.executeCommand("vscode.open", notebookSimpleDotNotebook);
assert.strictEqual(vscode.notebook.activeNotebookEditor.document.cells.length, 2);
assert.strictEqual(vscode.notebook.activeNotebookEditor.document.cells[0].cellKind, vscode.CellKind.Markdown);
assert.strictEqual(vscode.notebook.activeNotebookEditor.document.cells[0].document.getText(), "asdf");
assert.strictEqual(vscode.notebook.activeNotebookEditor.document.cells[1].cellKind, vscode.CellKind.Code);
assert.strictEqual(vscode.notebook.activeNotebookEditor.document.cells[1].document.getText(), "gci\n");
}).timeout(20000);
});
2 changes: 2 additions & 0 deletions test/features/testNotebookFiles/simple.Notebook.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# asdf
gci