mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Nb/open book without reload (#6635)
* initial commit * fix: added initialize method to fix the previous/next links rendering * added checks * open first markdown/ipynb in the book ans expand the view * added launch book from command pallete, removed the pick folder and save option added launching the first notebook/markdown * moved the open book command pallet action from mssql to notebooks * open as untitled to true * opening markdown files issue fix * removed opening as untitled files * open ipynb files as untitled and changes for previous&next links to work * add books as seperate viewlet * localize double quote issues and renamed treeCollapsibleState * renames and added logic to conditionally show Preview command * moved registerCommands from widget to extension contribution * isEditorUntitled check * async comment updates * formatting issues. * promisfying the async calls * moved existsAsync to top
This commit is contained in:
@@ -100,6 +100,8 @@ class AzdataExtensionBookContributionProvider extends Disposable implements Book
|
|||||||
this._onContributionsChanged.fire(this);
|
this._onContributionsChanged.fire(this);
|
||||||
}
|
}
|
||||||
}, undefined, this._disposables);
|
}, undefined, this._disposables);
|
||||||
|
|
||||||
|
this.registerCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly _onContributionsChanged = this._register(new vscode.EventEmitter<this>());
|
private readonly _onContributionsChanged = this._register(new vscode.EventEmitter<this>());
|
||||||
@@ -117,8 +119,18 @@ class AzdataExtensionBookContributionProvider extends Disposable implements Book
|
|||||||
.map(BookContributions.fromExtension)
|
.map(BookContributions.fromExtension)
|
||||||
.reduce(BookContributions.merge, []);
|
.reduce(BookContributions.merge, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private registerCommands(): void {
|
||||||
|
this.contributions.map(book => {
|
||||||
|
let bookName: string = path.basename(book.path);
|
||||||
|
vscode.commands.executeCommand('setContext', bookName, true);
|
||||||
|
vscode.commands.registerCommand('books.' + bookName, async (context) => {
|
||||||
|
vscode.commands.executeCommand('bookTreeView.openBook', book.path, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBookExtensionContributions(context: vscode.ExtensionContext): BookContributionProvider {
|
export function getBookExtensionContributions(context: vscode.ExtensionContext): BookContributionProvider {
|
||||||
return new AzdataExtensionBookContributionProvider(context.extensionPath);
|
return new AzdataExtensionBookContributionProvider(context.extensionPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,10 @@
|
|||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as nls from 'vscode-nls';
|
|
||||||
import * as fs from 'fs-extra';
|
|
||||||
import * as path from 'path';
|
|
||||||
import {
|
import {
|
||||||
BookContributionProvider, BookContribution
|
BookContributionProvider
|
||||||
} from './bookExtensions';
|
} from './bookExtensions';
|
||||||
import * as Utils from '../utils';
|
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
|
||||||
|
|
||||||
export function registerBooksWidget(bookContributionProvider: BookContributionProvider): void {
|
export function registerBooksWidget(bookContributionProvider: BookContributionProvider): void {
|
||||||
azdata.ui.registerModelViewProvider('books-widget', async (view) => {
|
azdata.ui.registerModelViewProvider('books-widget', async (view) => {
|
||||||
@@ -40,7 +35,8 @@ export function registerBooksWidget(bookContributionProvider: BookContributionPr
|
|||||||
title: contribution.name
|
title: contribution.name
|
||||||
}).component();
|
}).component();
|
||||||
tsgbooklink.onDidClick(() => {
|
tsgbooklink.onDidClick(() => {
|
||||||
promptForFolder(contribution);
|
let uri: vscode.Uri = vscode.Uri.file(contribution.path);
|
||||||
|
openBookViewlet(uri);
|
||||||
});
|
});
|
||||||
bookRow.addItem(tsgbooklink, {
|
bookRow.addItem(tsgbooklink, {
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
@@ -73,56 +69,6 @@ export function registerBooksWidget(bookContributionProvider: BookContributionPr
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptForFolder(bookContribution: BookContribution): Promise<void> {
|
function openBookViewlet(folderUri: vscode.Uri): void {
|
||||||
try {
|
vscode.commands.executeCommand('bookTreeView.openBook', folderUri.fsPath, true);
|
||||||
const allFilesFilter = localize('allFiles', "All Files");
|
|
||||||
let filter = {};
|
|
||||||
filter[allFilesFilter] = '*';
|
|
||||||
let uris = await vscode.window.showOpenDialog({
|
|
||||||
filters: filter,
|
|
||||||
canSelectFiles: false,
|
|
||||||
canSelectMany: false,
|
|
||||||
canSelectFolders: true,
|
|
||||||
openLabel: localize('labelPickFolder', "Pick Folder")
|
|
||||||
});
|
|
||||||
if (uris && uris.length > 0) {
|
|
||||||
let pickedFolder = uris[0];
|
|
||||||
let destinationUri: vscode.Uri = vscode.Uri.file(path.join(pickedFolder.fsPath, bookContribution.name));
|
|
||||||
await saveBooksToFolder(destinationUri, bookContribution);
|
|
||||||
await promptToReloadWindow(destinationUri);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} catch (error) {
|
|
||||||
vscode.window.showErrorMessage(localize('FailedDuringSaveAndPrompt', 'Failed : {0}', Utils.getErrorMessage(error)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveBooksToFolder(folderUri: vscode.Uri, bookContribution: BookContribution): Promise<void> {
|
|
||||||
// Get book contributions
|
|
||||||
if (bookContribution && folderUri) {
|
|
||||||
//remove folder if exists
|
|
||||||
await fs.removeSync(folderUri.fsPath);
|
|
||||||
//make directory for each contribution book.
|
|
||||||
await fs.mkdirSync(folderUri.fsPath);
|
|
||||||
await fs.copy(bookContribution.path, folderUri.fsPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function promptToReloadWindow(folderUri: vscode.Uri): void {
|
|
||||||
const actionReload = localize('prompt.reloadInstance', "Reload");
|
|
||||||
const actionOpenNew = localize('prompt.openNewInstance', "Open new instance");
|
|
||||||
vscode.window.showInformationMessage(localize('prompt.reloadDescription', "Reload and view the Jupyter Books in the Files view."), actionReload, actionOpenNew)
|
|
||||||
.then(selectedAction => {
|
|
||||||
if (selectedAction === actionReload) {
|
|
||||||
vscode.commands.executeCommand('workbench.action.setWorkspaceAndOpen', {
|
|
||||||
forceNewWindow: false,
|
|
||||||
folderPath: folderUri
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (selectedAction === actionOpenNew) {
|
|
||||||
vscode.commands.executeCommand('workbench.action.setWorkspaceAndOpen', {
|
|
||||||
forceNewWindow: true,
|
|
||||||
folderPath: folderUri
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,385 +1,402 @@
|
|||||||
{
|
{
|
||||||
"name": "notebook",
|
"name": "notebook",
|
||||||
"displayName": "%displayName%",
|
"displayName": "%displayName%",
|
||||||
"description": "%description%",
|
"description": "%description%",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "*",
|
"vscode": "*",
|
||||||
"azdata": "*"
|
"azdata": "*"
|
||||||
},
|
},
|
||||||
"main": "./out/extension",
|
"main": "./out/extension",
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"*"
|
"*"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "%notebook.configuration.title%",
|
"title": "%notebook.configuration.title%",
|
||||||
"properties": {
|
"properties": {
|
||||||
"notebook.maxBookSearchDepth": {
|
"notebook.maxBookSearchDepth": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 5,
|
"default": 5,
|
||||||
"description": "%notebook.maxBookSearchDepth.description%"
|
"description": "%notebook.maxBookSearchDepth.description%"
|
||||||
},
|
},
|
||||||
"notebook.pythonPath": {
|
"notebook.pythonPath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "",
|
"default": "",
|
||||||
"description": "%notebook.pythonPath.description%"
|
"description": "%notebook.pythonPath.description%"
|
||||||
},
|
},
|
||||||
"notebook.useExistingPython": {
|
"notebook.useExistingPython": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "%notebook.useExistingPython.description%"
|
"description": "%notebook.useExistingPython.description%"
|
||||||
},
|
},
|
||||||
"notebook.overrideEditorTheming": {
|
"notebook.overrideEditorTheming": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true,
|
"default": true,
|
||||||
"description": "%notebook.overrideEditorTheming.description%"
|
"description": "%notebook.overrideEditorTheming.description%"
|
||||||
},
|
},
|
||||||
"notebook.maxTableRows": {
|
"notebook.maxTableRows": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 5000,
|
"default": 5000,
|
||||||
"description": "%notebook.maxTableRows.description%"
|
"description": "%notebook.maxTableRows.description%"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "notebook.command.analyzeNotebook",
|
"command": "notebook.command.analyzeNotebook",
|
||||||
"title": "%notebook.analyzeJupyterNotebook%"
|
"title": "%notebook.analyzeJupyterNotebook%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "_notebook.command.new",
|
"command": "_notebook.command.new",
|
||||||
"title": "%notebook.command.new%",
|
"title": "%notebook.command.new%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/new_notebook_inverse.svg",
|
"dark": "resources/dark/new_notebook_inverse.svg",
|
||||||
"light": "resources/light/new_notebook.svg"
|
"light": "resources/light/new_notebook.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.open",
|
"command": "notebook.command.open",
|
||||||
"title": "%notebook.command.open%",
|
"title": "%notebook.command.open%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/open_notebook_inverse.svg",
|
"dark": "resources/dark/open_notebook_inverse.svg",
|
||||||
"light": "resources/light/open_notebook.svg"
|
"light": "resources/light/open_notebook.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.runactivecell",
|
"command": "notebook.command.runactivecell",
|
||||||
"title": "%notebook.command.runactivecell%",
|
"title": "%notebook.command.runactivecell%",
|
||||||
"icon": "resources/dark/touchbar_run_cell.png"
|
"icon": "resources/dark/touchbar_run_cell.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.clearactivecellresult",
|
"command": "notebook.command.clearactivecellresult",
|
||||||
"title": "%notebook.command.clearactivecellresult%"
|
"title": "%notebook.command.clearactivecellresult%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.runallcells",
|
"command": "notebook.command.runallcells",
|
||||||
"title": "%notebook.command.runallcells%"
|
"title": "%notebook.command.runallcells%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.addcode",
|
"command": "notebook.command.addcode",
|
||||||
"title": "%notebook.command.addcode%"
|
"title": "%notebook.command.addcode%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.addtext",
|
"command": "notebook.command.addtext",
|
||||||
"title": "%notebook.command.addtext%"
|
"title": "%notebook.command.addtext%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "notebook.command.addcell",
|
"command": "notebook.command.addcell",
|
||||||
"title": "%notebook.command.addcell%",
|
"title": "%notebook.command.addcell%",
|
||||||
"icon": "resources/dark/touchbar_add_cell.png"
|
"icon": "resources/dark/touchbar_add_cell.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.cmd.analyzeNotebook",
|
"command": "jupyter.cmd.analyzeNotebook",
|
||||||
"title": "%title.analyzeJupyterNotebook%"
|
"title": "%title.analyzeJupyterNotebook%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.task.newNotebook",
|
"command": "jupyter.task.newNotebook",
|
||||||
"title": "%title.newJupyterNotebook%",
|
"title": "%title.newJupyterNotebook%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/new_notebook_inverse.svg",
|
"dark": "resources/dark/new_notebook_inverse.svg",
|
||||||
"light": "resources/light/new_notebook.svg"
|
"light": "resources/light/new_notebook.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.task.openNotebook",
|
"command": "jupyter.task.openNotebook",
|
||||||
"title": "%title.openJupyterNotebook%",
|
"title": "%title.openJupyterNotebook%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/open_notebook_inverse.svg",
|
"dark": "resources/dark/open_notebook_inverse.svg",
|
||||||
"light": "resources/light/open_notebook.svg"
|
"light": "resources/light/open_notebook.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.cmd.newNotebook",
|
"command": "jupyter.cmd.newNotebook",
|
||||||
"title": "%title.newJupyterNotebook%",
|
"title": "%title.newJupyterNotebook%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/new_notebook_inverse.svg",
|
"dark": "resources/dark/new_notebook_inverse.svg",
|
||||||
"light": "resources/light/new_notebook.svg"
|
"light": "resources/light/new_notebook.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.cmd.managePackages",
|
"command": "jupyter.cmd.managePackages",
|
||||||
"title": "%title.managePackages%",
|
"title": "%title.managePackages%",
|
||||||
"icon": {
|
"icon": {
|
||||||
"dark": "resources/dark/manage_inverse.svg",
|
"dark": "resources/dark/manage_inverse.svg",
|
||||||
"light": "resources/light/manage.svg"
|
"light": "resources/light/manage.svg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.cmd.configurePython",
|
"command": "jupyter.cmd.configurePython",
|
||||||
"title": "%title.configurePython%"
|
"title": "%title.configurePython%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "jupyter.reinstallDependencies",
|
"command": "jupyter.reinstallDependencies",
|
||||||
"title": "%title.reinstallNotebookDependencies%"
|
"title": "%title.reinstallNotebookDependencies%"
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"languages": [
|
"command": "books.sqlserver2019",
|
||||||
{
|
"title": "%title.SQL19PreviewBook%",
|
||||||
"id": "notebook",
|
"category": "%books-preview-category%"
|
||||||
"extensions": [
|
}
|
||||||
".ipynb"
|
],
|
||||||
],
|
"languages": [
|
||||||
"aliases": [
|
{
|
||||||
"Notebook"
|
"id": "notebook",
|
||||||
]
|
"extensions": [
|
||||||
}
|
".ipynb"
|
||||||
],
|
],
|
||||||
"menus": {
|
"aliases": [
|
||||||
"commandPalette": [
|
"Notebook"
|
||||||
{
|
]
|
||||||
"command": "notebook.command.analyzeNotebook",
|
}
|
||||||
"when": "false"
|
],
|
||||||
},
|
"menus": {
|
||||||
{
|
"commandPalette": [
|
||||||
"command": "_notebook.command.new",
|
{
|
||||||
"when": "false"
|
"command": "notebook.command.analyzeNotebook",
|
||||||
},
|
"when": "false"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.open"
|
{
|
||||||
},
|
"command": "_notebook.command.new",
|
||||||
{
|
"when": "false"
|
||||||
"command": "notebook.command.runactivecell",
|
},
|
||||||
"when": "notebookEditorVisible"
|
{
|
||||||
},
|
"command": "notebook.command.open"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.clearactivecellresult",
|
{
|
||||||
"when": "notebookEditorVisible"
|
"command": "notebook.command.runactivecell",
|
||||||
},
|
"when": "notebookEditorVisible"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.runallcells",
|
{
|
||||||
"when": "notebookEditorVisible"
|
"command": "notebook.command.clearactivecellresult",
|
||||||
},
|
"when": "notebookEditorVisible"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.addcode",
|
{
|
||||||
"when": "notebookEditorVisible"
|
"command": "notebook.command.runallcells",
|
||||||
},
|
"when": "notebookEditorVisible"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.addtext",
|
{
|
||||||
"when": "notebookEditorVisible"
|
"command": "notebook.command.addcode",
|
||||||
},
|
"when": "notebookEditorVisible"
|
||||||
{
|
},
|
||||||
"command": "notebook.command.addcell",
|
{
|
||||||
"when": "false"
|
"command": "notebook.command.addtext",
|
||||||
},
|
"when": "notebookEditorVisible"
|
||||||
{
|
},
|
||||||
"command": "jupyter.task.newNotebook",
|
{
|
||||||
"when": "false"
|
"command": "notebook.command.addcell",
|
||||||
},
|
"when": "false"
|
||||||
{
|
},
|
||||||
"command": "jupyter.cmd.newNotebook",
|
{
|
||||||
"when": "false"
|
"command": "jupyter.task.newNotebook",
|
||||||
},
|
"when": "false"
|
||||||
{
|
},
|
||||||
"command": "jupyter.cmd.analyzeNotebook",
|
{
|
||||||
"when": "false"
|
"command": "jupyter.cmd.newNotebook",
|
||||||
},
|
"when": "false"
|
||||||
{
|
},
|
||||||
"command": "jupyter.task.openNotebook",
|
{
|
||||||
"when": "false"
|
"command": "jupyter.cmd.analyzeNotebook",
|
||||||
},
|
"when": "false"
|
||||||
{
|
},
|
||||||
"command": "jupyter.cmd.managePackages",
|
{
|
||||||
"when": "false"
|
"command": "jupyter.task.openNotebook",
|
||||||
}
|
"when": "false"
|
||||||
],
|
},
|
||||||
"touchBar": [
|
{
|
||||||
{
|
"command": "jupyter.cmd.managePackages",
|
||||||
"command": "notebook.command.runactivecell",
|
"when": "false"
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor",
|
},
|
||||||
"group": "1_notebook@1"
|
{
|
||||||
},
|
"command": "books.sqlserver2019",
|
||||||
{
|
"when": "sqlserver2019 && notebookQuality != stable"
|
||||||
"command": "notebook.command.addcell",
|
}
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor",
|
],
|
||||||
"group": "1_notebook@2"
|
"touchBar": [
|
||||||
}
|
{
|
||||||
],
|
"command": "notebook.command.runactivecell",
|
||||||
"objectExplorer/item/context": [
|
"when": "activeEditor == workbench.editor.notebookEditor",
|
||||||
{
|
"group": "1_notebook@1"
|
||||||
"command": "notebook.command.analyzeNotebook",
|
},
|
||||||
"when": "nodeType=~/^mssqlCluster/ && nodeLabel=~/[^\\s]+(\\.(csv|tsv|txt))$/ && nodeType == mssqlCluster:file",
|
{
|
||||||
"group": "1notebook@1"
|
"command": "notebook.command.addcell",
|
||||||
},
|
"when": "activeEditor == workbench.editor.notebookEditor",
|
||||||
{
|
"group": "1_notebook@2"
|
||||||
"command": "jupyter.cmd.newNotebook",
|
}
|
||||||
"when": "connectionProvider == HADOOP_KNOX && nodeType && nodeType == Server",
|
],
|
||||||
"group": "1root@1"
|
"objectExplorer/item/context": [
|
||||||
},
|
{
|
||||||
{
|
"command": "notebook.command.analyzeNotebook",
|
||||||
"command": "jupyter.cmd.analyzeNotebook",
|
"when": "nodeType=~/^mssqlCluster/ && nodeLabel=~/[^\\s]+(\\.(csv|tsv|txt))$/ && nodeType == mssqlCluster:file",
|
||||||
"when": "nodeType=~/^hdfs/ && nodeLabel=~/[^\\s]+(\\.(csv|tsv|txt))$/ && nodeType == hdfs:file",
|
"group": "1notebook@1"
|
||||||
"group": "1notebook@1"
|
},
|
||||||
}
|
{
|
||||||
],
|
"command": "jupyter.cmd.newNotebook",
|
||||||
"notebook/toolbar": [
|
"when": "connectionProvider == HADOOP_KNOX && nodeType && nodeType == Server",
|
||||||
{
|
"group": "1root@1"
|
||||||
"command": "jupyter.cmd.managePackages",
|
},
|
||||||
"when": "providerId == jupyter && notebook:pythonInstalled"
|
{
|
||||||
}
|
"command": "jupyter.cmd.analyzeNotebook",
|
||||||
]
|
"when": "nodeType=~/^hdfs/ && nodeLabel=~/[^\\s]+(\\.(csv|tsv|txt))$/ && nodeType == hdfs:file",
|
||||||
},
|
"group": "1notebook@1"
|
||||||
"keybindings": [
|
}
|
||||||
{
|
],
|
||||||
"command": "notebook.command.runactivecell",
|
"notebook/toolbar": [
|
||||||
"key": "F5",
|
{
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor"
|
"command": "jupyter.cmd.managePackages",
|
||||||
},
|
"when": "providerId == jupyter && notebook:pythonInstalled"
|
||||||
{
|
}
|
||||||
"command": "notebook.command.clearactivecellresult",
|
]
|
||||||
"key": "Ctrl+Shift+R",
|
},
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor"
|
"keybindings": [
|
||||||
},
|
{
|
||||||
{
|
"command": "notebook.command.runactivecell",
|
||||||
"command": "notebook.command.runallcells",
|
"key": "F5",
|
||||||
"key": "Ctrl+Shift+F5",
|
"when": "activeEditor == workbench.editor.notebookEditor"
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor"
|
},
|
||||||
},
|
{
|
||||||
{
|
"command": "notebook.command.clearactivecellresult",
|
||||||
"command": "notebook.command.addcode",
|
"key": "Ctrl+Shift+R",
|
||||||
"key": "Ctrl+Shift+C",
|
"when": "activeEditor == workbench.editor.notebookEditor"
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor"
|
},
|
||||||
},
|
{
|
||||||
{
|
"command": "notebook.command.runallcells",
|
||||||
"command": "notebook.command.addtext",
|
"key": "Ctrl+Shift+F5",
|
||||||
"key": "Ctrl+Shift+T",
|
"when": "activeEditor == workbench.editor.notebookEditor"
|
||||||
"when": "activeEditor == workbench.editor.notebookEditor"
|
},
|
||||||
}
|
{
|
||||||
],
|
"command": "notebook.command.addcode",
|
||||||
"notebook.languagemagics": [
|
"key": "Ctrl+Shift+C",
|
||||||
{
|
"when": "activeEditor == workbench.editor.notebookEditor"
|
||||||
"magic": "lang_python",
|
},
|
||||||
"language": "python",
|
{
|
||||||
"executionTarget": null,
|
"command": "notebook.command.addtext",
|
||||||
"kernels": [
|
"key": "Ctrl+Shift+T",
|
||||||
"sql"
|
"when": "activeEditor == workbench.editor.notebookEditor"
|
||||||
]
|
}
|
||||||
},
|
],
|
||||||
{
|
"notebook.languagemagics": [
|
||||||
"magic": "lang_r",
|
{
|
||||||
"language": "r",
|
"magic": "lang_python",
|
||||||
"executionTarget": null,
|
"language": "python",
|
||||||
"kernels": [
|
"executionTarget": null,
|
||||||
"sql"
|
"kernels": [
|
||||||
]
|
"sql"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"magic": "lang_java",
|
{
|
||||||
"language": "java",
|
"magic": "lang_r",
|
||||||
"executionTarget": null,
|
"language": "r",
|
||||||
"kernels": [
|
"executionTarget": null,
|
||||||
"sql"
|
"kernels": [
|
||||||
]
|
"sql"
|
||||||
}
|
]
|
||||||
],
|
},
|
||||||
"notebook.providers": {
|
{
|
||||||
"provider": "jupyter",
|
"magic": "lang_java",
|
||||||
"fileExtensions": [
|
"language": "java",
|
||||||
"IPYNB"
|
"executionTarget": null,
|
||||||
],
|
"kernels": [
|
||||||
"standardKernels": [
|
"sql"
|
||||||
{
|
]
|
||||||
"name": "pyspark3kernel",
|
}
|
||||||
"displayName": "PySpark3",
|
],
|
||||||
"connectionProviderIds": [
|
"notebook.providers": {
|
||||||
"HADOOP_KNOX",
|
"provider": "jupyter",
|
||||||
"MSSQL"
|
"fileExtensions": [
|
||||||
]
|
"IPYNB"
|
||||||
},
|
],
|
||||||
{
|
"standardKernels": [
|
||||||
"name": "pysparkkernel",
|
{
|
||||||
"displayName": "PySpark",
|
"name": "pyspark3kernel",
|
||||||
"connectionProviderIds": [
|
"displayName": "PySpark3",
|
||||||
"HADOOP_KNOX",
|
"connectionProviderIds": [
|
||||||
"MSSQL"
|
"HADOOP_KNOX",
|
||||||
]
|
"MSSQL"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"name": "sparkkernel",
|
{
|
||||||
"displayName": "Spark | Scala",
|
"name": "pysparkkernel",
|
||||||
"connectionProviderIds": [
|
"displayName": "PySpark",
|
||||||
"HADOOP_KNOX",
|
"connectionProviderIds": [
|
||||||
"MSSQL"
|
"HADOOP_KNOX",
|
||||||
]
|
"MSSQL"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"name": "sparkrkernel",
|
{
|
||||||
"displayName": "Spark | R",
|
"name": "sparkkernel",
|
||||||
"connectionProviderIds": [
|
"displayName": "Spark | Scala",
|
||||||
"HADOOP_KNOX",
|
"connectionProviderIds": [
|
||||||
"MSSQL"
|
"HADOOP_KNOX",
|
||||||
]
|
"MSSQL"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"name": "python3",
|
{
|
||||||
"displayName": "Python 3",
|
"name": "sparkrkernel",
|
||||||
"connectionProviderIds": []
|
"displayName": "Spark | R",
|
||||||
}
|
"connectionProviderIds": [
|
||||||
]
|
"HADOOP_KNOX",
|
||||||
},
|
"MSSQL"
|
||||||
"views": {
|
]
|
||||||
"explorer": [
|
},
|
||||||
{
|
{
|
||||||
"id": "bookTreeView",
|
"name": "python3",
|
||||||
"name": "Books",
|
"displayName": "Python 3",
|
||||||
"when": "bookOpened && notebookQuality != stable"
|
"connectionProviderIds": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
},
|
"viewsContainers": {
|
||||||
"dependencies": {
|
"activitybar": [
|
||||||
"@jupyterlab/services": "^3.2.1",
|
{
|
||||||
"@types/js-yaml": "^3.12.1",
|
"id": "books-explorer",
|
||||||
"@types/rimraf": "^2.0.2",
|
"title": "Jupyter Books",
|
||||||
"decompress": "^4.2.0",
|
"icon": "resources/dark/open_notebook_inverse.svg"
|
||||||
"error-ex": "^1.3.1",
|
}
|
||||||
"fast-glob": "^3.0.4",
|
]
|
||||||
"figures": "^2.0.0",
|
},
|
||||||
"fs-extra": "^5.0.0",
|
"views": {
|
||||||
"glob": "^7.1.1",
|
"books-explorer": [
|
||||||
"node-fetch": "^2.3.0",
|
{
|
||||||
"request": "^2.88.0",
|
"id": "bookTreeView",
|
||||||
"temp-write": "^3.4.0",
|
"name": "Books"
|
||||||
"vscode-languageclient": "^5.3.0-next.1",
|
}
|
||||||
"vscode-nls": "^4.0.0"
|
]
|
||||||
},
|
}
|
||||||
"devDependencies": {
|
},
|
||||||
"@types/decompress": "^4.2.3",
|
"dependencies": {
|
||||||
"@types/fs-extra": "^5.0.0",
|
"@jupyterlab/services": "^3.2.1",
|
||||||
"@types/glob": "^7.1.1",
|
"@types/js-yaml": "^3.12.1",
|
||||||
"@types/mocha": "^5.2.5",
|
"@types/rimraf": "^2.0.2",
|
||||||
"@types/node": "^11.9.3",
|
"decompress": "^4.2.0",
|
||||||
"@types/request": "^2.48.1",
|
"error-ex": "^1.3.1",
|
||||||
"@types/temp-write": "^3.3.0",
|
"fast-glob": "^3.0.4",
|
||||||
"@types/uuid": "^3.4.5",
|
"figures": "^2.0.0",
|
||||||
"assert": "^1.4.1",
|
"fs-extra": "^5.0.0",
|
||||||
"mocha": "^5.2.0",
|
"glob": "^7.1.1",
|
||||||
"mocha-junit-reporter": "^1.17.0",
|
"node-fetch": "^2.3.0",
|
||||||
"mocha-multi-reporters": "^1.1.7",
|
"request": "^2.88.0",
|
||||||
"typemoq": "^2.1.0",
|
"temp-write": "^3.4.0",
|
||||||
"vscode": "1.1.5"
|
"vscode-languageclient": "^5.3.0-next.1",
|
||||||
},
|
"vscode-nls": "^4.0.0"
|
||||||
"enableProposedApi": true
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/decompress": "^4.2.3",
|
||||||
|
"@types/fs-extra": "^5.0.0",
|
||||||
|
"@types/glob": "^7.1.1",
|
||||||
|
"@types/mocha": "^5.2.5",
|
||||||
|
"@types/node": "^11.9.3",
|
||||||
|
"@types/request": "^2.48.1",
|
||||||
|
"@types/temp-write": "^3.3.0",
|
||||||
|
"@types/uuid": "^3.4.5",
|
||||||
|
"assert": "^1.4.1",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"mocha-junit-reporter": "^1.17.0",
|
||||||
|
"mocha-multi-reporters": "^1.1.7",
|
||||||
|
"typemoq": "^2.1.0",
|
||||||
|
"vscode": "1.1.5"
|
||||||
|
},
|
||||||
|
"enableProposedApi": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,5 +26,7 @@
|
|||||||
"config.jupyter.kernelConfigValuesDescription": "Configuration options for Jupyter kernels. This is automatically managed and not recommended to be manually edited.",
|
"config.jupyter.kernelConfigValuesDescription": "Configuration options for Jupyter kernels. This is automatically managed and not recommended to be manually edited.",
|
||||||
"title.reinstallNotebookDependencies": "Reinstall Notebook dependencies",
|
"title.reinstallNotebookDependencies": "Reinstall Notebook dependencies",
|
||||||
"title.configurePython": "Configure Python for Notebooks",
|
"title.configurePython": "Configure Python for Notebooks",
|
||||||
"title.managePackages": "Manage Packages"
|
"title.managePackages": "Manage Packages",
|
||||||
|
"title.SQL19PreviewBook": "SQL Server 2019 Guide",
|
||||||
|
"books-preview-category": "Jupyter Books"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export interface BookTreeItemFormat {
|
|||||||
tableOfContents: any[];
|
tableOfContents: any[];
|
||||||
page: any;
|
page: any;
|
||||||
type: BookTreeItemType;
|
type: BookTreeItemType;
|
||||||
|
treeItemCollapsibleState: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BookTreeItem extends vscode.TreeItem {
|
export class BookTreeItem extends vscode.TreeItem {
|
||||||
@@ -32,10 +33,10 @@ export class BookTreeItem extends vscode.TreeItem {
|
|||||||
public command: vscode.Command;
|
public command: vscode.Command;
|
||||||
|
|
||||||
constructor(public book: BookTreeItemFormat, icons: any) {
|
constructor(public book: BookTreeItemFormat, icons: any) {
|
||||||
super(book.title, vscode.TreeItemCollapsibleState.Collapsed);
|
super(book.title, book.treeItemCollapsibleState);
|
||||||
|
|
||||||
if (book.type === BookTreeItemType.Book) {
|
if (book.type === BookTreeItemType.Book) {
|
||||||
this.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
|
this.collapsibleState = book.treeItemCollapsibleState;
|
||||||
this._sections = book.page;
|
this._sections = book.page;
|
||||||
} else {
|
} else {
|
||||||
this.setPageVariables();
|
this.setPageVariables();
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ import * as yaml from 'js-yaml';
|
|||||||
import * as glob from 'fast-glob';
|
import * as glob from 'fast-glob';
|
||||||
import { BookTreeItem, BookTreeItemType } from './bookTreeItem';
|
import { BookTreeItem, BookTreeItemType } from './bookTreeItem';
|
||||||
import { maxBookSearchDepth, notebookConfigKey } from '../common/constants';
|
import { maxBookSearchDepth, notebookConfigKey } from '../common/constants';
|
||||||
|
import { isEditorTitleFree } from '../common/utils';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
const existsAsync = promisify(fs.exists);
|
||||||
|
|
||||||
export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeItem>, azdata.nb.NavigationProvider {
|
export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeItem>, azdata.nb.NavigationProvider {
|
||||||
readonly providerId: string = 'BookNavigator';
|
readonly providerId: string = 'BookNavigator';
|
||||||
@@ -25,17 +29,29 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
private _throttleTimer: any;
|
private _throttleTimer: any;
|
||||||
private _resource: string;
|
private _resource: string;
|
||||||
private _onReadAllTOCFiles: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
private _onReadAllTOCFiles: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
||||||
|
private _openAsUntitled: boolean;
|
||||||
|
|
||||||
constructor(workspaceFolders: vscode.WorkspaceFolder[], extensionContext: vscode.ExtensionContext) {
|
constructor(workspaceFolders: vscode.WorkspaceFolder[], extensionContext: vscode.ExtensionContext) {
|
||||||
this.getTableOfContentFiles(workspaceFolders).then(() => undefined, (err) => { console.log(err); });
|
this.initialze(workspaceFolders, null, extensionContext);
|
||||||
this._extensionContext = extensionContext;
|
}
|
||||||
|
|
||||||
|
private initialze(workspaceFolders: vscode.WorkspaceFolder[], bookPath: string, context: vscode.ExtensionContext): void {
|
||||||
|
let workspacePaths: string[] = [];
|
||||||
|
if (bookPath) {
|
||||||
|
workspacePaths.push(bookPath);
|
||||||
|
}
|
||||||
|
else if (workspaceFolders) {
|
||||||
|
workspacePaths = workspaceFolders.map(a => a.uri.fsPath);
|
||||||
|
}
|
||||||
|
this.getTableOfContentFiles(workspacePaths).then(() => undefined, (err) => { console.log(err); });
|
||||||
|
this._extensionContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get onReadAllTOCFiles(): vscode.Event<void> {
|
public get onReadAllTOCFiles(): vscode.Event<void> {
|
||||||
return this._onReadAllTOCFiles.event;
|
return this._onReadAllTOCFiles.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTableOfContentFiles(workspaceFolders: vscode.WorkspaceFolder[]): Promise<void> {
|
async getTableOfContentFiles(workspacePaths: string[]): Promise<void> {
|
||||||
let notebookConfig = vscode.workspace.getConfiguration(notebookConfigKey);
|
let notebookConfig = vscode.workspace.getConfiguration(notebookConfigKey);
|
||||||
let maxDepth = notebookConfig[maxBookSearchDepth];
|
let maxDepth = notebookConfig[maxBookSearchDepth];
|
||||||
// Use default value if user enters an invalid value
|
// Use default value if user enters an invalid value
|
||||||
@@ -44,7 +60,6 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
} else if (maxDepth === 0) { // No limit of search depth if user enters 0
|
} else if (maxDepth === 0) { // No limit of search depth if user enters 0
|
||||||
maxDepth = undefined;
|
maxDepth = undefined;
|
||||||
}
|
}
|
||||||
let workspacePaths: string[] = workspaceFolders.map(a => a.uri.fsPath);
|
|
||||||
for (let workspacePath of workspacePaths) {
|
for (let workspacePath of workspacePaths) {
|
||||||
let p = path.join(workspacePath, '**', '_data', 'toc.yml').replace(/\\/g, '/');
|
let p = path.join(workspacePath, '**', '_data', 'toc.yml').replace(/\\/g, '/');
|
||||||
let tableOfContentPaths = await glob(p, { deep: maxDepth });
|
let tableOfContentPaths = await glob(p, { deep: maxDepth });
|
||||||
@@ -55,12 +70,50 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
this._onReadAllTOCFiles.fire();
|
this._onReadAllTOCFiles.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async openBook(bookPath: string, context: vscode.ExtensionContext, openAsUntitled: boolean): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Check if the book is already open in viewlet.
|
||||||
|
if (this._tableOfContentPaths.indexOf(path.join(bookPath, '_data', 'toc.yml').replace(/\\/g, '/')) > -1 && this._allNotebooks.size > 0) {
|
||||||
|
vscode.commands.executeCommand('workbench.books.action.focusBooksExplorer');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await this.getTableOfContentFiles([bookPath]);
|
||||||
|
let bookViewer = vscode.window.createTreeView('bookTreeView', { showCollapseAll: true, treeDataProvider: this });
|
||||||
|
await vscode.commands.executeCommand('workbench.books.action.focusBooksExplorer');
|
||||||
|
this._openAsUntitled = openAsUntitled;
|
||||||
|
let books = this.getBooks();
|
||||||
|
if (books && books.length > 0) {
|
||||||
|
bookViewer.reveal(books[0], { expand: vscode.TreeItemCollapsibleState.Expanded, focus: true, select: true });
|
||||||
|
const readmeMarkdown: string = path.join(bookPath, 'content', books[0].tableOfContents[0].url.concat('.md'));
|
||||||
|
const readmeNotebook: string = path.join(bookPath, 'content', books[0].tableOfContents[0].url.concat('.ipynb'));
|
||||||
|
const markdownExists = await existsAsync(readmeMarkdown);
|
||||||
|
const notebookExists = await existsAsync(readmeNotebook);
|
||||||
|
if (markdownExists) {
|
||||||
|
vscode.commands.executeCommand('markdown.showPreview', vscode.Uri.file(readmeMarkdown));
|
||||||
|
}
|
||||||
|
else if (notebookExists) {
|
||||||
|
vscode.workspace.openTextDocument(readmeNotebook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
vscode.window.showErrorMessage(localize('openBookError', "Open book {0} failed: {1}",
|
||||||
|
bookPath,
|
||||||
|
e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async openNotebook(resource: string): Promise<void> {
|
async openNotebook(resource: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
let doc = await vscode.workspace.openTextDocument(resource);
|
if (this._openAsUntitled) {
|
||||||
vscode.window.showTextDocument(doc);
|
this.openNotebookAsUntitled(resource);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let doc = await vscode.workspace.openTextDocument(resource);
|
||||||
|
vscode.window.showTextDocument(doc);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(localize('openNotebookError', 'Open file {0} failed: {1}',
|
vscode.window.showErrorMessage(localize('openNotebookError', "Open file {0} failed: {1}",
|
||||||
resource,
|
resource,
|
||||||
e instanceof Error ? e.message : e));
|
e instanceof Error ? e.message : e));
|
||||||
}
|
}
|
||||||
@@ -78,6 +131,24 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openNotebookAsUntitled(resource: string): void {
|
||||||
|
try {
|
||||||
|
let untitledFileName: vscode.Uri = this.getUntitledNotebookUri(resource);
|
||||||
|
vscode.workspace.openTextDocument(resource).then((document) => {
|
||||||
|
let initialContent = document.getText();
|
||||||
|
azdata.nb.showNotebookDocument(untitledFileName, {
|
||||||
|
connectionProfile: null,
|
||||||
|
initialContent: initialContent,
|
||||||
|
initialDirtyState: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
vscode.window.showErrorMessage(localize('openUntitledNotebookError', "Open file {0} as untitled failed: {1}",
|
||||||
|
resource,
|
||||||
|
e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private runThrottledAction(resource: string, action: () => void) {
|
private runThrottledAction(resource: string, action: () => void) {
|
||||||
const isResourceChange = resource !== this._resource;
|
const isResourceChange = resource !== this._resource;
|
||||||
if (isResourceChange) {
|
if (isResourceChange) {
|
||||||
@@ -101,7 +172,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
try {
|
try {
|
||||||
vscode.env.openExternal(vscode.Uri.parse(resource));
|
vscode.env.openExternal(vscode.Uri.parse(resource));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(localize('openExternalLinkError', 'Open link {0} failed: {1}',
|
vscode.window.showErrorMessage(localize('openExternalLinkError', "Open link {0} failed: {1}",
|
||||||
resource,
|
resource,
|
||||||
e instanceof Error ? e.message : e));
|
e instanceof Error ? e.message : e));
|
||||||
}
|
}
|
||||||
@@ -139,7 +210,8 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
root: root,
|
root: root,
|
||||||
tableOfContents: this.flattenArray(tableOfContents),
|
tableOfContents: this.flattenArray(tableOfContents),
|
||||||
page: tableOfContents,
|
page: tableOfContents,
|
||||||
type: BookTreeItemType.Book
|
type: BookTreeItemType.Book,
|
||||||
|
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Expanded,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light: this._extensionContext.asAbsolutePath('resources/light/book.svg'),
|
light: this._extensionContext.asAbsolutePath('resources/light/book.svg'),
|
||||||
@@ -148,7 +220,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
);
|
);
|
||||||
books.push(book);
|
books.push(book);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(localize('openConfigFileError', 'Open file {0} failed: {1}',
|
vscode.window.showErrorMessage(localize('openConfigFileError', "Open file {0} failed: {1}",
|
||||||
path.join(root, '_config.yml'),
|
path.join(root, '_config.yml'),
|
||||||
e instanceof Error ? e.message : e));
|
e instanceof Error ? e.message : e));
|
||||||
}
|
}
|
||||||
@@ -166,7 +238,8 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
root: root,
|
root: root,
|
||||||
tableOfContents: tableOfContents,
|
tableOfContents: tableOfContents,
|
||||||
page: sections[i],
|
page: sections[i],
|
||||||
type: BookTreeItemType.ExternalLink
|
type: BookTreeItemType.ExternalLink,
|
||||||
|
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light: this._extensionContext.asAbsolutePath('resources/light/link.svg'),
|
light: this._extensionContext.asAbsolutePath('resources/light/link.svg'),
|
||||||
@@ -186,7 +259,8 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
root: root,
|
root: root,
|
||||||
tableOfContents: tableOfContents,
|
tableOfContents: tableOfContents,
|
||||||
page: sections[i],
|
page: sections[i],
|
||||||
type: BookTreeItemType.Notebook
|
type: BookTreeItemType.Notebook,
|
||||||
|
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light: this._extensionContext.asAbsolutePath('resources/light/notebook.svg'),
|
light: this._extensionContext.asAbsolutePath('resources/light/notebook.svg'),
|
||||||
@@ -195,13 +269,17 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
);
|
);
|
||||||
notebooks.push(notebook);
|
notebooks.push(notebook);
|
||||||
this._allNotebooks.set(pathToNotebook, notebook);
|
this._allNotebooks.set(pathToNotebook, notebook);
|
||||||
|
if (this._openAsUntitled) {
|
||||||
|
this._allNotebooks.set(path.basename(pathToNotebook, '.ipynb'), notebook);
|
||||||
|
}
|
||||||
} else if (fs.existsSync(pathToMarkdown)) {
|
} else if (fs.existsSync(pathToMarkdown)) {
|
||||||
let markdown = new BookTreeItem({
|
let markdown = new BookTreeItem({
|
||||||
title: sections[i].title,
|
title: sections[i].title,
|
||||||
root: root,
|
root: root,
|
||||||
tableOfContents: tableOfContents,
|
tableOfContents: tableOfContents,
|
||||||
page: sections[i],
|
page: sections[i],
|
||||||
type: BookTreeItemType.Markdown
|
type: BookTreeItemType.Markdown,
|
||||||
|
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light: this._extensionContext.asAbsolutePath('resources/light/markdown.svg'),
|
light: this._extensionContext.asAbsolutePath('resources/light/markdown.svg'),
|
||||||
@@ -210,7 +288,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
);
|
);
|
||||||
notebooks.push(markdown);
|
notebooks.push(markdown);
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage(localize('missingFileError', 'Missing file : {0}', sections[i].title));
|
vscode.window.showErrorMessage(localize('missingFileError', "Missing file : {0}", sections[i].title));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -226,8 +304,8 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
if (notebook) {
|
if (notebook) {
|
||||||
result = {
|
result = {
|
||||||
hasNavigation: true,
|
hasNavigation: true,
|
||||||
previous: notebook.previousUri ? vscode.Uri.file(notebook.previousUri) : undefined,
|
previous: notebook.previousUri ? this._openAsUntitled ? vscode.Uri.parse(notebook.previousUri).with({ scheme: 'untitled' }) : vscode.Uri.file(notebook.previousUri) : undefined,
|
||||||
next: notebook.nextUri ? vscode.Uri.file(notebook.nextUri) : undefined
|
next: notebook.nextUri ? this._openAsUntitled ? vscode.Uri.parse(notebook.nextUri).with({ scheme: 'untitled' }) : vscode.Uri.file(notebook.nextUri) : undefined
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
result = {
|
result = {
|
||||||
@@ -239,4 +317,28 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
|
|||||||
return Promise.resolve(result);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUntitledNotebookUri(resource: string): vscode.Uri {
|
||||||
|
let title = this.findNextUntitledFileName(resource);
|
||||||
|
let untitledFileName: vscode.Uri = vscode.Uri.parse(`untitled:${title}`);
|
||||||
|
if (!this._allNotebooks.get(untitledFileName.fsPath)) {
|
||||||
|
let notebook = this._allNotebooks.get(resource);
|
||||||
|
this._allNotebooks.set(untitledFileName.fsPath, notebook);
|
||||||
|
}
|
||||||
|
return untitledFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
findNextUntitledFileName(filePath: string): string {
|
||||||
|
const fileExtension = path.extname(filePath);
|
||||||
|
const baseName = path.basename(filePath, fileExtension);
|
||||||
|
let idx = 0;
|
||||||
|
let title = `${baseName}`;
|
||||||
|
do {
|
||||||
|
const suffix = idx === 0 ? '' : `-${idx}`;
|
||||||
|
title = `${baseName}${suffix}`;
|
||||||
|
idx++;
|
||||||
|
} while (!isEditorTitleFree(title));
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
|
|||||||
const bookTreeViewProvider = new BookTreeViewProvider(vscode.workspace.workspaceFolders || [], extensionContext);
|
const bookTreeViewProvider = new BookTreeViewProvider(vscode.workspace.workspaceFolders || [], extensionContext);
|
||||||
extensionContext.subscriptions.push(vscode.window.registerTreeDataProvider('bookTreeView', bookTreeViewProvider));
|
extensionContext.subscriptions.push(vscode.window.registerTreeDataProvider('bookTreeView', bookTreeViewProvider));
|
||||||
extensionContext.subscriptions.push(azdata.nb.registerNavigationProvider(bookTreeViewProvider));
|
extensionContext.subscriptions.push(azdata.nb.registerNavigationProvider(bookTreeViewProvider));
|
||||||
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openBook', (resource, openAsReadonly) => bookTreeViewProvider.openBook(resource, extensionContext, openAsReadonly)));
|
||||||
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openNotebookAsUntitled', (resource) => bookTreeViewProvider.openNotebookAsUntitled(resource)));
|
||||||
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openNotebook', (resource) => bookTreeViewProvider.openNotebook(resource)));
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openNotebook', (resource) => bookTreeViewProvider.openNotebook(resource)));
|
||||||
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openMarkdown', (resource) => bookTreeViewProvider.openMarkdown(resource)));
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openMarkdown', (resource) => bookTreeViewProvider.openMarkdown(resource)));
|
||||||
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openExternalLink', (resource) => bookTreeViewProvider.openExternalLink(resource)));
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openExternalLink', (resource) => bookTreeViewProvider.openExternalLink(resource)));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
|||||||
import { Schemas } from 'vs/base/common/network';
|
import { Schemas } from 'vs/base/common/network';
|
||||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SqlMainContext, MainThreadNotebookDocumentsAndEditorsShape, SqlExtHostContext, ExtHostNotebookDocumentsAndEditorsShape,
|
SqlMainContext, MainThreadNotebookDocumentsAndEditorsShape, SqlExtHostContext, ExtHostNotebookDocumentsAndEditorsShape,
|
||||||
@@ -698,13 +699,25 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
|
|||||||
onNext: async (uri) => {
|
onNext: async (uri) => {
|
||||||
let result = await this._proxy.$getNavigation(handle, uri);
|
let result = await this._proxy.$getNavigation(handle, uri);
|
||||||
if (result) {
|
if (result) {
|
||||||
this.doOpenEditor(result.next, {});
|
if (uri.scheme === Schemas.untitled) {
|
||||||
|
let untitledNbName: URI = URI.parse(`untitled:${path.basename(result.next.path, '.ipynb')}`);
|
||||||
|
this.doOpenEditor(untitledNbName, { initialContent: fs.readFileSync(result.next.path).toString(), initialDirtyState: false });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.doOpenEditor(result.next, {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPrevious: async (uri) => {
|
onPrevious: async (uri) => {
|
||||||
let result = await this._proxy.$getNavigation(handle, uri);
|
let result = await this._proxy.$getNavigation(handle, uri);
|
||||||
if (result) {
|
if (result) {
|
||||||
this.doOpenEditor(result.previous, {});
|
if (uri.scheme === Schemas.untitled) {
|
||||||
|
let untitledNbName: URI = URI.parse(`untitled:${path.basename(result.previous.path, '.ipynb')}`);
|
||||||
|
this.doOpenEditor(untitledNbName, { initialContent: fs.readFileSync(result.previous.path).toString(), initialDirtyState: false });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.doOpenEditor(result.previous, {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
|||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
|
||||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||||
|
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer } from 'vs/workbench/common/views';
|
||||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext';
|
import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext';
|
||||||
import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/common/mssqlNodeContext';
|
import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/common/mssqlNodeContext';
|
||||||
@@ -157,6 +158,22 @@ configurationRegistry.registerConfiguration({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explorer viewlet id.
|
||||||
|
*/
|
||||||
|
export const VIEWLET_ID = 'bookTreeView';
|
||||||
|
/**
|
||||||
|
* Explorer viewlet container.
|
||||||
|
*/
|
||||||
|
export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(VIEWLET_ID);
|
||||||
|
registerAction({
|
||||||
|
id: 'workbench.books.action.focusBooksExplorer',
|
||||||
|
handler: async (accessor) => {
|
||||||
|
const viewletService = accessor.get(IViewletService);
|
||||||
|
viewletService.openViewlet('workbench.view.extension.books-explorer', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* *************** Output components *************** */
|
/* *************** Output components *************** */
|
||||||
// Note: most existing types use the same component to render. In order to
|
// Note: most existing types use the same component to render. In order to
|
||||||
// preserve correct rank order, we register it once for each different rank of
|
// preserve correct rank order, we register it once for each different rank of
|
||||||
|
|||||||
Reference in New Issue
Block a user