Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.yarnrc2
-rw-r--r--build/azure-pipelines/darwin/product-build-darwin.yml2
-rw-r--r--build/azure-pipelines/linux/product-build-linux.yml2
-rw-r--r--build/azure-pipelines/win32/product-build-win32.yml2
-rw-r--r--build/lib/eslint/vscode-dts-region-comments.js8
-rw-r--r--build/lib/eslint/vscode-dts-region-comments.ts10
-rw-r--r--build/monaco/package.json2
-rwxr-xr-xextensions/git/src/askpass.sh2
-rw-r--r--extensions/git/src/askpass.ts1
-rw-r--r--extensions/git/src/model.ts2
-rw-r--r--extensions/markdown-language-features/notebook/index.ts5
-rw-r--r--extensions/markdown-language-features/src/features/preview.ts9
-rw-r--r--extensions/microsoft-authentication/src/AADHelper.ts11
-rw-r--r--extensions/vscode-test-resolver/src/extension.ts4
-rw-r--r--package.json16
-rw-r--r--remote/package.json14
-rw-r--r--remote/web/package.json8
-rw-r--r--remote/web/yarn.lock38
-rw-r--r--remote/yarn.lock66
-rwxr-xr-xresources/darwin/bin/code.sh2
-rwxr-xr-xresources/linux/bin/code.sh2
-rw-r--r--resources/server/test/test-remote-integration.bat3
-rwxr-xr-xresources/server/test/test-remote-integration.sh3
-rw-r--r--resources/win32/bin/code.cmd4
-rw-r--r--resources/win32/bin/code.sh4
-rw-r--r--scripts/code-cli.bat2
-rwxr-xr-xscripts/code-cli.sh2
-rwxr-xr-xscripts/code.sh2
-rw-r--r--scripts/node-electron.bat4
-rwxr-xr-xscripts/node-electron.sh6
-rw-r--r--scripts/test-integration.bat1
-rwxr-xr-xscripts/test-integration.sh1
-rw-r--r--src/vs/base/browser/ui/sash/sash.ts18
-rw-r--r--src/vs/base/browser/ui/scrollbar/media/scrollbars.css58
-rw-r--r--src/vs/base/browser/ui/table/tableWidget.ts29
-rw-r--r--src/vs/base/common/objects.ts6
-rw-r--r--src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts51
-rw-r--r--src/vs/editor/common/config/editorOptions.ts2
-rw-r--r--src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts3
-rw-r--r--src/vs/editor/contrib/zoneWidget/zoneWidget.ts1
-rw-r--r--src/vs/editor/standalone/browser/standaloneLanguages.ts4
-rw-r--r--src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts13
-rw-r--r--src/vs/platform/environment/common/argv.ts3
-rw-r--r--src/vs/platform/environment/node/argv.ts1
-rw-r--r--src/vs/platform/environment/node/shellEnv.ts5
-rw-r--r--src/vs/platform/list/browser/listService.ts2
-rw-r--r--src/vs/platform/product/common/product.ts2
-rw-r--r--src/vs/platform/userDataSync/common/userDataSyncAccount.ts6
-rw-r--r--src/vs/server/remoteCli.ts1
-rw-r--r--src/vs/server/remoteTerminalChannel.ts13
-rw-r--r--src/vs/workbench/api/browser/mainThreadCodeInsets.ts6
-rw-r--r--src/vs/workbench/api/browser/mainThreadSCM.ts9
-rw-r--r--src/vs/workbench/api/browser/mainThreadWebviewPanels.ts31
-rw-r--r--src/vs/workbench/api/browser/mainThreadWebviews.ts9
-rw-r--r--src/vs/workbench/api/common/extHost.api.impl.ts2
-rw-r--r--src/vs/workbench/api/common/extHost.protocol.ts38
-rw-r--r--src/vs/workbench/api/common/extHostCustomEditors.ts2
-rw-r--r--src/vs/workbench/api/common/extHostOutput.ts56
-rw-r--r--src/vs/workbench/api/common/extHostQuickOpen.ts21
-rw-r--r--src/vs/workbench/api/common/extHostSCM.ts10
-rw-r--r--src/vs/workbench/api/common/extHostWebview.ts6
-rw-r--r--src/vs/workbench/api/common/extHostWebviewPanels.ts2
-rw-r--r--src/vs/workbench/browser/parts/editor/editorPanes.ts48
-rw-r--r--src/vs/workbench/browser/style.ts47
-rw-r--r--src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts17
-rw-r--r--src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts6
-rw-r--r--src/vs/workbench/contrib/logs/common/logs.contribution.ts24
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts64
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts10
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts8
-rw-r--r--src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts31
-rw-r--r--src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts88
-rw-r--r--src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css7
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts64
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl.ts14
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts10
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts39
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts66
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts33
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection.ts4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts8
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookCommon.ts43
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookOptions.ts129
-rw-r--r--src/vs/workbench/contrib/notebook/test/notebookDiff.test.ts2
-rw-r--r--src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts2
-rw-r--r--src/vs/workbench/contrib/preferences/browser/settingsTree.ts32
-rw-r--r--src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts5
-rw-r--r--src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts2
-rw-r--r--src/vs/workbench/contrib/scm/browser/scmViewService.ts12
-rw-r--r--src/vs/workbench/contrib/terminal/browser/media/terminal.css67
-rw-r--r--src/vs/workbench/contrib/terminal/browser/media/widgets.css9
-rw-r--r--src/vs/workbench/contrib/terminal/browser/media/xterm.css2
-rw-r--r--src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts2
-rw-r--r--src/vs/workbench/contrib/terminal/browser/terminal.ts10
-rw-r--r--src/vs/workbench/contrib/terminal/browser/terminalInstance.ts177
-rw-r--r--src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts240
-rw-r--r--src/vs/workbench/contrib/terminal/browser/terminalProfileService.ts30
-rw-r--r--src/vs/workbench/contrib/terminal/browser/terminalService.ts295
-rw-r--r--src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts85
-rw-r--r--src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts4
-rw-r--r--src/vs/workbench/contrib/terminal/common/terminal.ts7
-rw-r--r--src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.test.ts113
-rw-r--r--src/vs/workbench/contrib/webview/browser/webview.ts57
-rw-r--r--src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css2
-rw-r--r--src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts4
-rw-r--r--src/vs/workbench/electron-sandbox/parts/dialogs/dialogHandler.ts4
-rw-r--r--src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts2
-rw-r--r--src/vs/workbench/services/preferences/common/preferences.ts2
-rw-r--r--src/vs/workbench/services/preferences/common/preferencesValidation.ts93
-rw-r--r--src/vs/workbench/services/preferences/test/common/preferencesValidation.test.ts60
-rw-r--r--src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts2
-rw-r--r--src/vscode-dts/vscode.d.ts64
-rw-r--r--src/vscode-dts/vscode.proposed.d.ts146
-rw-r--r--test/automation/src/code.ts4
-rw-r--r--test/smoke/README.md1
-rw-r--r--test/smoke/src/areas/terminal/terminal-profiles.test.ts20
-rw-r--r--test/smoke/src/areas/terminal/terminal-reconnection.test.ts20
-rw-r--r--test/smoke/src/main.ts46
-rw-r--r--yarn.lock66
124 files changed, 1744 insertions, 1379 deletions
diff --git a/.yarnrc b/.yarnrc
index 0e39a85f525..481bf7bfa46 100644
--- a/.yarnrc
+++ b/.yarnrc
@@ -1,4 +1,4 @@
disturl "https://electronjs.org/headers"
-target "13.5.1"
+target "13.5.2"
runtime "electron"
build_from_source "true"
diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml
index f21bd633a76..ce62104f949 100644
--- a/build/azure-pipelines/darwin/product-build-darwin.yml
+++ b/build/azure-pipelines/darwin/product-build-darwin.yml
@@ -233,7 +233,7 @@ steps:
APP_ROOT=$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)
APP_NAME="`ls $APP_ROOT | head -n 1`"
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-darwin" \
- yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --remote --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
+ yarn smoketest-no-compile --build "$APP_ROOT/$APP_NAME" --remote --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
timeoutInMinutes: 5
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml
index 5c742c2503c..a1bcb6a8a90 100644
--- a/build/azure-pipelines/linux/product-build-linux.yml
+++ b/build/azure-pipelines/linux/product-build-linux.yml
@@ -220,7 +220,7 @@ steps:
set -e
APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
- yarn smoketest-no-compile --build "$APP_PATH" --remote --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests
+ yarn smoketest-no-compile --build "$APP_PATH" --remote --electronArgs="--disable-dev-shm-usage --use-gl=swiftshader" --screenshots $(Build.SourcesDirectory)/.build/logs/smoke-tests-remote
timeoutInMinutes: 5
displayName: Run smoke tests (Remote)
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml
index d365c165f8b..ccd863c615b 100644
--- a/build/azure-pipelines/win32/product-build-win32.yml
+++ b/build/azure-pipelines/win32/product-build-win32.yml
@@ -216,7 +216,7 @@ steps:
$ErrorActionPreference = "Stop"
$AppRoot = "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
$env:VSCODE_REMOTE_SERVER_PATH = "$(agent.builddirectory)\vscode-reh-win32-$(VSCODE_ARCH)"
- exec { yarn smoketest-no-compile --build "$AppRoot" --remote }
+ exec { yarn smoketest-no-compile --build "$AppRoot" --remote --screenshots $(Build.SourcesDirectory)\.build\logs\smoke-tests-remote }
displayName: Run smoke tests (Remote)
timeoutInMinutes: 5
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'), ne(variables['VSCODE_ARCH'], 'arm64'))
diff --git a/build/lib/eslint/vscode-dts-region-comments.js b/build/lib/eslint/vscode-dts-region-comments.js
index 7d37a20fb6a..2dc9487314e 100644
--- a/build/lib/eslint/vscode-dts-region-comments.js
+++ b/build/lib/eslint/vscode-dts-region-comments.js
@@ -7,7 +7,7 @@ module.exports = new class ApiEventNaming {
constructor() {
this.meta = {
messages: {
- comment: 'region comments should start with the GH issue link, e.g #region https://github.com/microsoft/vscode/issues/<number>',
+ comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/<number>',
}
};
}
@@ -15,14 +15,14 @@ module.exports = new class ApiEventNaming {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node) => {
- for (let comment of sourceCode.getAllComments()) {
+ for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Line') {
continue;
}
- if (!comment.value.match(/^\s*#region /)) {
+ if (!/^\s*#region /.test(comment.value)) {
continue;
}
- if (!comment.value.match(/https:\/\/github.com\/microsoft\/vscode\/issues\/\d+/i)) {
+ if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) {
context.report({
node: comment,
messageId: 'comment',
diff --git a/build/lib/eslint/vscode-dts-region-comments.ts b/build/lib/eslint/vscode-dts-region-comments.ts
index 175fb9040ab..63139a50e3b 100644
--- a/build/lib/eslint/vscode-dts-region-comments.ts
+++ b/build/lib/eslint/vscode-dts-region-comments.ts
@@ -9,7 +9,7 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
- comment: 'region comments should start with the GH issue link, e.g #region https://github.com/microsoft/vscode/issues/<number>',
+ comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/<number>',
}
};
@@ -17,18 +17,16 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
const sourceCode = context.getSourceCode();
-
return {
['Program']: (_node: any) => {
-
- for (let comment of sourceCode.getAllComments()) {
+ for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Line') {
continue;
}
- if (!comment.value.match(/^\s*#region /)) {
+ if (!/^\s*#region /.test(comment.value)) {
continue;
}
- if (!comment.value.match(/https:\/\/github.com\/microsoft\/vscode\/issues\/\d+/i)) {
+ if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) {
context.report({
node: <any>comment,
messageId: 'comment',
diff --git a/build/monaco/package.json b/build/monaco/package.json
index b987a610d72..2e30e04628e 100644
--- a/build/monaco/package.json
+++ b/build/monaco/package.json
@@ -1,7 +1,7 @@
{
"name": "monaco-editor-core",
"private": true,
- "version": "0.29.2",
+ "version": "0.30.0",
"description": "A browser based code editor",
"author": "Microsoft Corporation",
"license": "MIT",
diff --git a/extensions/git/src/askpass.sh b/extensions/git/src/askpass.sh
index d19b62affa3..c85c64ad2fd 100755
--- a/extensions/git/src/askpass.sh
+++ b/extensions/git/src/askpass.sh
@@ -1,5 +1,5 @@
#!/bin/sh
VSCODE_GIT_ASKPASS_PIPE=`mktemp`
-ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_MAIN" $*
+ELECTRON_RUN_AS_NODE="1" VSCODE_GIT_ASKPASS_PIPE="$VSCODE_GIT_ASKPASS_PIPE" "$VSCODE_GIT_ASKPASS_NODE" "$VSCODE_GIT_ASKPASS_EXTRA_ARGS" "$VSCODE_GIT_ASKPASS_MAIN" $*
cat $VSCODE_GIT_ASKPASS_PIPE
rm $VSCODE_GIT_ASKPASS_PIPE
diff --git a/extensions/git/src/askpass.ts b/extensions/git/src/askpass.ts
index 7fc29a371ad..e6c21efa9cb 100644
--- a/extensions/git/src/askpass.ts
+++ b/extensions/git/src/askpass.ts
@@ -83,6 +83,7 @@ export class Askpass implements IIPCHandler {
...this.ipc.getEnv(),
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
VSCODE_GIT_ASKPASS_NODE: process.execPath,
+ VSCODE_GIT_ASKPASS_EXTRA_ARGS: (process.versions['electron'] && process.versions['microsoft-build']) ? '--ms-enable-electron-run-as-node' : '',
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
};
}
diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts
index 9a2f9197378..a57e5f73fac 100644
--- a/extensions/git/src/model.ts
+++ b/extensions/git/src/model.ts
@@ -300,7 +300,7 @@ export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRe
const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel);
this.open(repository);
- await repository.status();
+ repository.status(); // do not await this, we want SCM to know about the repo asap
} catch (ex) {
// noop
this.outputChannel.appendLine(`Opening repository for path='${repoPath}' failed; ex=${ex}`);
diff --git a/extensions/markdown-language-features/notebook/index.ts b/extensions/markdown-language-features/notebook/index.ts
index 2586457e2c2..fe25756c0ea 100644
--- a/extensions/markdown-language-features/notebook/index.ts
+++ b/extensions/markdown-language-features/notebook/index.ts
@@ -29,10 +29,6 @@ export const activate: ActivationFunction<void> = (ctx) => {
const style = document.createElement('style');
style.textContent = `
- #preview {
- font-size: 1.1em;
- }
-
.emptyMarkdownCell::before {
content: "${document.documentElement.style.getPropertyValue('--notebook-cell-markup-empty-content')}";
font-style: italic;
@@ -165,7 +161,6 @@ export const activate: ActivationFunction<void> = (ctx) => {
pre code {
font-family: var(--vscode-editor-font-family);
- font-size: var(--vscode-editor-font-size);
line-height: 1.357em;
white-space: pre-wrap;
diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts
index ff5f00cb949..499f168afff 100644
--- a/extensions/markdown-language-features/src/features/preview.ts
+++ b/extensions/markdown-language-features/src/features/preview.ts
@@ -120,6 +120,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
private imageInfo: { readonly id: string, readonly width: number, readonly height: number; }[] = [];
private readonly _fileWatchersBySrc = new Map</* src: */ string, vscode.FileSystemWatcher>();
+
private readonly _onScrollEmitter = this._register(new vscode.EventEmitter<LastScrollLocation>());
public readonly onScroll = this._onScrollEmitter.event;
@@ -262,13 +263,13 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
* The first call immediately refreshes the preview,
* calls happening shortly thereafter are debounced.
*/
- public refresh() {
+ public refresh(forceUpdate: boolean = false) {
// Schedule update if none is pending
if (!this.throttleTimer) {
if (this.firstUpdate) {
this.updatePreview(true);
} else {
- this.throttleTimer = setTimeout(() => this.updatePreview(true), this.delay);
+ this.throttleTimer = setTimeout(() => this.updatePreview(forceUpdate), this.delay);
}
}
@@ -333,7 +334,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
return;
}
- const shouldReloadPage = !this.currentVersion || this.currentVersion.resource.toString() !== pendingVersion.resource.toString();
+ const shouldReloadPage = forceUpdate || !this.currentVersion || this.currentVersion.resource.toString() !== pendingVersion.resource.toString();
this.currentVersion = pendingVersion;
const content = await (shouldReloadPage
@@ -429,7 +430,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
if (uri && uri.scheme === 'file' && !this._fileWatchersBySrc.has(src)) {
const watcher = vscode.workspace.createFileSystemWatcher(uri.fsPath);
watcher.onDidChange(() => {
- this.refresh();
+ this.refresh(true);
});
this._fileWatchersBySrc.set(src, watcher);
}
diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts
index 4e6be890442..4709ef62db0 100644
--- a/extensions/microsoft-authentication/src/AADHelper.ts
+++ b/extensions/microsoft-authentication/src/AADHelper.ts
@@ -240,6 +240,7 @@ export class AzureActiveDirectoryService {
}
if (added.length || removed.length) {
+ Logger.info(`Sending change event with ${added.length} added and ${removed.length} removed`);
onDidChangeSessions.fire({ added: added, removed: removed, changed: [] });
}
}
@@ -380,7 +381,7 @@ export class AzureActiveDirectoryService {
throw codeRes.err;
}
token = await this.exchangeCodeForToken(codeRes.code, codeVerifier, scope);
- this.setToken(token, scope);
+ await this.setToken(token, scope);
Logger.info(`Login successful for scopes: ${scope}`);
res.writeHead(302, { Location: '/' });
const session = await this.convertToSession(token);
@@ -491,7 +492,7 @@ export class AzureActiveDirectoryService {
}
const token = await this.exchangeCodeForToken(code, verifier, scope);
- this.setToken(token, scope);
+ await this.setToken(token, scope);
const session = await this.convertToSession(token);
resolve(session);
@@ -509,6 +510,7 @@ export class AzureActiveDirectoryService {
}
private async setToken(token: IToken, scope: string): Promise<void> {
+ Logger.info(`Setting token for scopes: ${scope}`);
const existingTokenIndex = this._tokens.findIndex(t => t.sessionId === token.sessionId);
if (existingTokenIndex > -1) {
this._tokens.splice(existingTokenIndex, 1, token);
@@ -522,6 +524,7 @@ export class AzureActiveDirectoryService {
this._refreshTimeouts.set(token.sessionId, setTimeout(async () => {
try {
const refreshedToken = await this.refreshToken(token.refreshToken, scope, token.sessionId);
+ Logger.info('Triggering change session event...');
onDidChangeSessions.fire({ added: [], removed: [], changed: [this.convertToSessionSync(refreshedToken)] });
} catch (e) {
if (e.message === REFRESH_NETWORK_FAILURE) {
@@ -537,7 +540,7 @@ export class AzureActiveDirectoryService {
}, 1000 * (token.expiresIn - 30)));
}
- this.storeTokenData();
+ await this.storeTokenData();
}
private getTokenFromResponse(json: ITokenResponse, scope: string, existingId?: string): IToken {
@@ -649,7 +652,7 @@ export class AzureActiveDirectoryService {
if (result.ok) {
const json = await result.json();
const token = this.getTokenFromResponse(json, scope, sessionId);
- this.setToken(token, scope);
+ await this.setToken(token, scope);
Logger.info(`Token refresh success for scopes: ${token.scope}`);
return token;
} else {
diff --git a/extensions/vscode-test-resolver/src/extension.ts b/extensions/vscode-test-resolver/src/extension.ts
index 63efe6d8bf9..9e54bd40dbe 100644
--- a/extensions/vscode-test-resolver/src/extension.ts
+++ b/extensions/vscode-test-resolver/src/extension.ts
@@ -83,6 +83,10 @@ export function activate(context: vscode.ExtensionContext) {
const commandArgs = ['--port=0', '--disable-telemetry'];
const env = getNewEnv();
const remoteDataDir = process.env['TESTRESOLVER_DATA_FOLDER'] || path.join(os.homedir(), serverDataFolderName || `${dataFolderName}-testresolver`);
+ const logsDir = process.env['TESTRESOLVER_LOGS_FOLDER'];
+ if (logsDir) {
+ commandArgs.push('--logsPath', logsDir);
+ }
env['VSCODE_AGENT_FOLDER'] = remoteDataDir;
outputChannel.appendLine(`Using data folder at ${remoteDataDir}`);
diff --git a/package.json b/package.json
index e6a02348d76..368265d0742 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.63.0",
- "distro": "f4a21145f5ec390f681f48c7140bf4f60d2987ac",
+ "distro": "cc8976e5470edb06e4b3abd29841ffe7bf5042d2",
"author": {
"name": "Microsoft Corporation"
},
@@ -59,7 +59,7 @@
},
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
- "@parcel/watcher": "2.0.0",
+ "@parcel/watcher": "2.0.1",
"@vscode/sqlite3": "4.0.12",
"@vscode/vscode-languagedetection": "1.0.21",
"applicationinsights": "1.0.8",
@@ -84,12 +84,12 @@
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
"vscode-textmate": "5.4.1",
- "xterm": "4.15.0-beta.10",
- "xterm-addon-search": "0.9.0-beta.5",
- "xterm-addon-serialize": "0.7.0-beta.2",
- "xterm-addon-unicode11": "0.3.0",
- "xterm-addon-webgl": "0.12.0-beta.15",
- "xterm-headless": "4.15.0-beta.10",
+ "xterm": "4.16.0-beta.2",
+ "xterm-addon-search": "0.9.0-beta.6",
+ "xterm-addon-serialize": "0.7.0-beta.3",
+ "xterm-addon-unicode11": "0.4.0-beta.1",
+ "xterm-addon-webgl": "0.12.0-beta.16",
+ "xterm-headless": "4.16.0-beta.2",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
diff --git a/remote/package.json b/remote/package.json
index 1851794ddd6..501827c3f79 100644
--- a/remote/package.json
+++ b/remote/package.json
@@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@microsoft/applicationinsights-web": "^2.6.4",
- "@parcel/watcher": "2.0.0",
+ "@parcel/watcher": "2.0.1",
"@vscode/vscode-languagedetection": "1.0.21",
"applicationinsights": "1.0.8",
"cookie": "^0.4.0",
@@ -24,12 +24,12 @@
"vscode-regexpp": "^3.1.0",
"vscode-ripgrep": "^1.12.1",
"vscode-textmate": "5.4.1",
- "xterm": "4.15.0-beta.10",
- "xterm-addon-search": "0.9.0-beta.5",
- "xterm-addon-serialize": "0.7.0-beta.2",
- "xterm-addon-unicode11": "0.3.0",
- "xterm-addon-webgl": "0.12.0-beta.15",
- "xterm-headless": "4.15.0-beta.10",
+ "xterm": "4.16.0-beta.2",
+ "xterm-addon-search": "0.9.0-beta.6",
+ "xterm-addon-serialize": "0.7.0-beta.3",
+ "xterm-addon-unicode11": "0.4.0-beta.1",
+ "xterm-addon-webgl": "0.12.0-beta.16",
+ "xterm-headless": "4.16.0-beta.2",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
diff --git a/remote/web/package.json b/remote/web/package.json
index 307a919a301..f69e0798f01 100644
--- a/remote/web/package.json
+++ b/remote/web/package.json
@@ -10,9 +10,9 @@
"tas-client-umd": "0.1.4",
"vscode-oniguruma": "1.5.1",
"vscode-textmate": "5.4.1",
- "xterm": "4.15.0-beta.10",
- "xterm-addon-search": "0.9.0-beta.5",
- "xterm-addon-unicode11": "0.3.0",
- "xterm-addon-webgl": "0.12.0-beta.15"
+ "xterm": "4.16.0-beta.2",
+ "xterm-addon-search": "0.9.0-beta.6",
+ "xterm-addon-unicode11": "0.4.0-beta.1",
+ "xterm-addon-webgl": "0.12.0-beta.16"
}
}
diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock
index 384abe27126..4bf3abe60b5 100644
--- a/remote/web/yarn.lock
+++ b/remote/web/yarn.lock
@@ -113,22 +113,22 @@ vscode-textmate@5.4.1:
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.4.1.tgz#09d566724fc76b60b3ad9791eebf1f0b50f29e5a"
integrity sha512-4CvPHmfuZQaXrcCpathdh6jo7myuR+MU8BvscgQADuponpbqfmu2rwTOtCXhGwwEgStvJF8V4s9FwMKRVLNmKQ==
-xterm-addon-search@0.9.0-beta.5:
- version "0.9.0-beta.5"
- resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.5.tgz#e0e60a203d1c9d6c8af933648a46865dba299302"
- integrity sha512-ylfqim0ISBvuuX83LQwgu/06p5GC545QsAo9SssXw03TPpIrcd0zwaVMEnhOftSIzM9EKRRsyx3GbBjgUdiF5w==
-
-xterm-addon-unicode11@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.3.0.tgz#e4435c3c91a5294a7eb8b79c380acbb28a659463"
- integrity sha512-x5fHDZT2j9tlTlHnzPHt++9uKZ2kJ/lYQOj3L6xJA22xoJsS8UQRw/5YIFg2FUHqEAbV77Z1fZij/9NycMSH/A==
-
-xterm-addon-webgl@0.12.0-beta.15:
- version "0.12.0-beta.15"
- resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.15.tgz#9ae82127f2a39b3cb7f5ae45a6af223810c933d4"
- integrity sha512-LWZ3iLspQOCc26OoT8qa+SuyuIcn2cAMRbBkinOuQCk4aW5kjovIrGovj9yVAcXNvOBnPm3sUqmnwGlN579kDA==
-
-xterm@4.15.0-beta.10:
- version "4.15.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.15.0-beta.10.tgz#8cda3d7885e8345f2fc6cf9275a43f3833d29acf"
- integrity sha512-valoh5ZcY/y7Pe+ffgcSAEFeuZfjzVeUUXcthdxTTsrGEiU1s4QR2EOg4U5jn5wye/Nc6mSfLW3s79R6Ac186w==
+xterm-addon-search@0.9.0-beta.6:
+ version "0.9.0-beta.6"
+ resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.6.tgz#8b016baac5580dc0ba93bb52610bc4f5776d3b17"
+ integrity sha512-UAEzas4O+NrF7BSGf0C9N5ngAkmbtr/hSTFvLAM/Rw7EfLUatf8aLMqAWZTggRGMwDjuqR0GXJI4+e5QrJhQfw==
+
+xterm-addon-unicode11@0.4.0-beta.1:
+ version "0.4.0-beta.1"
+ resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.4.0-beta.1.tgz#aeefd26e87bad15d8dfd8a1e0b804fe408c9b882"
+ integrity sha512-pG8mpxnqpYDry0e20vuEFKhd4kKIcLLNwdNftNvfo+R/EjYRnTYnF+H8L+7eQHq6hqDH61xCEP4H4qR2CyT4pg==
+
+xterm-addon-webgl@0.12.0-beta.16:
+ version "0.12.0-beta.16"
+ resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.16.tgz#63a0f1f5be9e66286e035448e2011e3065769ad5"
+ integrity sha512-g6v3RegOhSsD9Zt8ArWBMNT30QyPUlIWEIvP/xLHAluUZ1S5sDjFyZDB0nJAyn9MwQozJpwb0ylYO1nznN/TzA==
+
+xterm@4.16.0-beta.2:
+ version "4.16.0-beta.2"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.2.tgz#251beef21a232143f272da74c7005bc4d832ca79"
+ integrity sha512-PD0agueJ7qvbn1/QhZriAQXf+ykaoPKgQN9qiIGf88VMxHs8T47MYHW/+qPsrXagTmbrENtncughTIzOzv8Q5Q==
diff --git a/remote/yarn.lock b/remote/yarn.lock
index 091d7fe7dad..6eb9ea16e1b 100644
--- a/remote/yarn.lock
+++ b/remote/yarn.lock
@@ -83,10 +83,10 @@
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.4.tgz#40e1c0ad20743fcee1604a7df2c57faf0aa1af87"
integrity sha512-Ot53G927ykMF8cQ3/zq4foZtdk+Tt1YpX7aUTHxBU7UHNdkEiBvBfZSq+rnlUmKCJ19VatwPG4mNzvcGpBj4og==
-"@parcel/watcher@2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.0.tgz#ebe992a4838b35c3da9a568eb95a71cb26ddf551"
- integrity sha512-ByalKmRRXNNAhwZ0X1r0XeIhh1jG8zgdlvjgHk9ZV3YxiersEGNQkwew+RfqJbIL4gOJfvC2ey6lg5kaeRainw==
+"@parcel/watcher@2.0.1":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.1.tgz#ec4bb6c43d9588a1ffd3d2abe6df5b501463c62d"
+ integrity sha512-XegFF4L8sFn1RzU5KKOZxXUuzgOSwd6+X2ez3Cy6MVhYMbiLZ1moceMTqDhuT3N8DNbdumK3zP1wojsIsnX40w==
dependencies:
node-addon-api "^3.2.1"
node-gyp-build "^4.3.0"
@@ -541,35 +541,35 @@ xregexp@2.0.0:
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
-xterm-addon-search@0.9.0-beta.5:
- version "0.9.0-beta.5"
- resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.5.tgz#e0e60a203d1c9d6c8af933648a46865dba299302"
- integrity sha512-ylfqim0ISBvuuX83LQwgu/06p5GC545QsAo9SssXw03TPpIrcd0zwaVMEnhOftSIzM9EKRRsyx3GbBjgUdiF5w==
-
-xterm-addon-serialize@0.7.0-beta.2:
- version "0.7.0-beta.2"
- resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.2.tgz#ced9f664c74ab88448e7b63850721bc272aa6806"
- integrity sha512-KuSwdx2AAliUv7SvjKYUKHrB7vscbHLv8QsmwSDI3pgL1BpjyLJ8LR99iFFfuNpPW9CG4TX6adKPIJXtqiN3Vg==
-
-xterm-addon-unicode11@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.3.0.tgz#e4435c3c91a5294a7eb8b79c380acbb28a659463"
- integrity sha512-x5fHDZT2j9tlTlHnzPHt++9uKZ2kJ/lYQOj3L6xJA22xoJsS8UQRw/5YIFg2FUHqEAbV77Z1fZij/9NycMSH/A==
-
-xterm-addon-webgl@0.12.0-beta.15:
- version "0.12.0-beta.15"
- resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.15.tgz#9ae82127f2a39b3cb7f5ae45a6af223810c933d4"
- integrity sha512-LWZ3iLspQOCc26OoT8qa+SuyuIcn2cAMRbBkinOuQCk4aW5kjovIrGovj9yVAcXNvOBnPm3sUqmnwGlN579kDA==
-
-xterm-headless@4.15.0-beta.10:
- version "4.15.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.15.0-beta.10.tgz#2dbcb40dfda7ecfdacc7b63889c80da965480ce7"
- integrity sha512-kDAzmaeFX8hAJvbPUJc4dW4SoVBSg4onCVOPyi8QTmxZz1o7I9mX4U7DX1v3PceyfrU27A9k6zXjuTuPjxCCSQ==
-
-xterm@4.15.0-beta.10:
- version "4.15.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.15.0-beta.10.tgz#8cda3d7885e8345f2fc6cf9275a43f3833d29acf"
- integrity sha512-valoh5ZcY/y7Pe+ffgcSAEFeuZfjzVeUUXcthdxTTsrGEiU1s4QR2EOg4U5jn5wye/Nc6mSfLW3s79R6Ac186w==
+xterm-addon-search@0.9.0-beta.6:
+ version "0.9.0-beta.6"
+ resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.6.tgz#8b016baac5580dc0ba93bb52610bc4f5776d3b17"
+ integrity sha512-UAEzas4O+NrF7BSGf0C9N5ngAkmbtr/hSTFvLAM/Rw7EfLUatf8aLMqAWZTggRGMwDjuqR0GXJI4+e5QrJhQfw==
+
+xterm-addon-serialize@0.7.0-beta.3:
+ version "0.7.0-beta.3"
+ resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.3.tgz#a8ce52a59685041bd3b6d6a2a77a3df8bc3daf29"
+ integrity sha512-fgB0h8JiSN1cOMh3slenysprnGfFwbDZ/D38WA0Pdjxf3YDy4j2SwoUajlvXpkFWR7sHjVHmgpw/nHggO731KA==
+
+xterm-addon-unicode11@0.4.0-beta.1:
+ version "0.4.0-beta.1"
+ resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.4.0-beta.1.tgz#aeefd26e87bad15d8dfd8a1e0b804fe408c9b882"
+ integrity sha512-pG8mpxnqpYDry0e20vuEFKhd4kKIcLLNwdNftNvfo+R/EjYRnTYnF+H8L+7eQHq6hqDH61xCEP4H4qR2CyT4pg==
+
+xterm-addon-webgl@0.12.0-beta.16:
+ version "0.12.0-beta.16"
+ resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.16.tgz#63a0f1f5be9e66286e035448e2011e3065769ad5"
+ integrity sha512-g6v3RegOhSsD9Zt8ArWBMNT30QyPUlIWEIvP/xLHAluUZ1S5sDjFyZDB0nJAyn9MwQozJpwb0ylYO1nznN/TzA==
+
+xterm-headless@4.16.0-beta.2:
+ version "4.16.0-beta.2"
+ resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.16.0-beta.2.tgz#62e66a655a30c814e3a311f3542d42c87446cecd"
+ integrity sha512-g92HDaIZcu1TQFlrjq2CHtt7A2qAwSD6s8RwncU/7u1kaq2e7rc9O3OKfu5v3QzgaRSKuugtquMr0OTKjkmLUg==
+
+xterm@4.16.0-beta.2:
+ version "4.16.0-beta.2"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.2.tgz#251beef21a232143f272da74c7005bc4d832ca79"
+ integrity sha512-PD0agueJ7qvbn1/QhZriAQXf+ykaoPKgQN9qiIGf88VMxHs8T47MYHW/+qPsrXagTmbrENtncughTIzOzv8Q5Q==
yauzl@^2.9.2:
version "2.10.0"
diff --git a/resources/darwin/bin/code.sh b/resources/darwin/bin/code.sh
index 6a9a9ec737c..20aee89edf9 100755
--- a/resources/darwin/bin/code.sh
+++ b/resources/darwin/bin/code.sh
@@ -7,5 +7,5 @@ function realpath() { python -c "import os,sys; print(os.path.realpath(sys.argv[
CONTENTS="$(dirname "$(dirname "$(dirname "$(dirname "$(realpath "$0")")")")")"
ELECTRON="$CONTENTS/MacOS/Electron"
CLI="$CONTENTS/Resources/app/out/cli.js"
-ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"
+ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --ms-enable-electron-run-as-node "$@"
exit $?
diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh
index 06973937f14..73ef78f62dc 100755
--- a/resources/linux/bin/code.sh
+++ b/resources/linux/bin/code.sh
@@ -50,5 +50,5 @@ fi
ELECTRON="$VSCODE_PATH/@@NAME@@"
CLI="$VSCODE_PATH/resources/app/out/cli.js"
-ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"
+ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --ms-enable-electron-run-as-node "$@"
exit $?
diff --git a/resources/server/test/test-remote-integration.bat b/resources/server/test/test-remote-integration.bat
index 47ee286f120..c31dff424d2 100644
--- a/resources/server/test/test-remote-integration.bat
+++ b/resources/server/test/test-remote-integration.bat
@@ -21,8 +21,9 @@ IF "%VSCODEUSERDATADIR%" == "" (
set REMOTE_VSCODE=%AUTHORITY%%EXT_PATH%
set VSCODECRASHDIR=%~dp0\..\..\..\.build\crashes
-set VSCODELOGSDIR=%~dp0\..\..\..\.build\logs\remote-integration-tests
+set VSCODELOGSDIR=%~dp0\..\..\..\.build\logs\integration-tests-remote
set TESTRESOLVER_DATA_FOLDER=%TMP%\testresolverdatafolder-%RANDOM%-%TIME:~6,5%
+set TESTRESOLVER_LOGS_FOLDER=%VSCODELOGSDIR%\server
if "%VSCODE_REMOTE_SERVER_PATH%"=="" (
echo "Using remote server out of sources for integration tests"
diff --git a/resources/server/test/test-remote-integration.sh b/resources/server/test/test-remote-integration.sh
index 09d14d50c95..71fee7327b4 100755
--- a/resources/server/test/test-remote-integration.sh
+++ b/resources/server/test/test-remote-integration.sh
@@ -29,7 +29,7 @@ fi
export REMOTE_VSCODE=$AUTHORITY$EXT_PATH
VSCODECRASHDIR=$ROOT/.build/crashes
-VSCODELOGSDIR=$ROOT/.build/logs/remote-integration-tests
+VSCODELOGSDIR=$ROOT/.build/logs/integration-tests-remote
# Figure out which Electron to use for running tests
if [ -z "$INTEGRATION_TEST_ELECTRON_PATH" ]
@@ -74,6 +74,7 @@ else
fi
export TESTRESOLVER_DATA_FOLDER=$TESTRESOLVER_DATA_FOLDER
+export TESTRESOLVER_LOGS_FOLDER=$VSCODELOGSDIR/server
# Figure out which remote server to use for running tests
if [ -z "$VSCODE_REMOTE_SERVER_PATH" ]
diff --git a/resources/win32/bin/code.cmd b/resources/win32/bin/code.cmd
index 33c640f5dd1..c72e9e28333 100644
--- a/resources/win32/bin/code.cmd
+++ b/resources/win32/bin/code.cmd
@@ -2,5 +2,5 @@
setlocal
set VSCODE_DEV=
set ELECTRON_RUN_AS_NODE=1
-"%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" %*
-endlocal \ No newline at end of file
+"%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" --ms-enable-electron-run-as-node %*
+endlocal
diff --git a/resources/win32/bin/code.sh b/resources/win32/bin/code.sh
index 23fbbc9bf20..999a5b5445c 100644
--- a/resources/win32/bin/code.sh
+++ b/resources/win32/bin/code.sh
@@ -43,7 +43,7 @@ if [ $IN_WSL = true ]; then
# use the Remote WSL extension if installed
WSL_EXT_ID="ms-vscode-remote.remote-wsl"
- ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --locate-extension $WSL_EXT_ID >/tmp/remote-wsl-loc.txt 2>/dev/null </dev/null
+ ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --ms-enable-electron-run-as-node --locate-extension $WSL_EXT_ID >/tmp/remote-wsl-loc.txt 2>/dev/null </dev/null
WSL_EXT_WLOC=$(cat /tmp/remote-wsl-loc.txt)
if [ -n "$WSL_EXT_WLOC" ]; then
@@ -58,5 +58,5 @@ elif [ -x "$(command -v cygpath)" ]; then
else
CLI="$VSCODE_PATH/resources/app/out/cli.js"
fi
-ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"
+ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" --ms-enable-electron-run-as-node "$@"
exit $?
diff --git a/scripts/code-cli.bat b/scripts/code-cli.bat
index c2eae24d4d9..2b3c9db3ca3 100644
--- a/scripts/code-cli.bat
+++ b/scripts/code-cli.bat
@@ -24,7 +24,7 @@ set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1
:: Launch Code
-%CODE% --inspect=5874 out\cli.js %~dp0.. %*
+%CODE% --inspect=5874 out\cli.js --ms-enable-electron-run-as-node %~dp0.. %*
goto end
:builtin
diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh
index a792c08532e..cdf75ff785c 100755
--- a/scripts/code-cli.sh
+++ b/scripts/code-cli.sh
@@ -34,7 +34,7 @@ function code() {
VSCODE_DEV=1 \
ELECTRON_ENABLE_LOGGING=1 \
ELECTRON_ENABLE_STACK_DUMPING=1 \
- "$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@"
+ "$CODE" --inspect=5874 "$ROOT/out/cli.js" --ms-enable-electron-run-as-node . "$@"
}
code "$@"
diff --git a/scripts/code.sh b/scripts/code.sh
index 9caa49b1bf7..08fc867ca12 100755
--- a/scripts/code.sh
+++ b/scripts/code.sh
@@ -58,7 +58,7 @@ function code-wsl()
cd $ROOT
export WSLENV=ELECTRON_RUN_AS_NODE/w:VSCODE_DEV/w:$WSLENV
local WSL_EXT_ID="ms-vscode-remote.remote-wsl"
- local WSL_EXT_WLOC=$(echo "" | VSCODE_DEV=1 ELECTRON_RUN_AS_NODE=1 "$ROOT/.build/electron/Code - OSS.exe" "out/cli.js" --locate-extension $WSL_EXT_ID)
+ local WSL_EXT_WLOC=$(echo "" | VSCODE_DEV=1 ELECTRON_RUN_AS_NODE=1 "$ROOT/.build/electron/Code - OSS.exe" "out/cli.js" --ms-enable-electron-run-as-node --locate-extension $WSL_EXT_ID)
cd $CWD
if [ -n "$WSL_EXT_WLOC" ]; then
# replace \r\n with \n in WSL_EXT_WLOC
diff --git a/scripts/node-electron.bat b/scripts/node-electron.bat
index 4ddb95b3cae..c67e2ea607d 100644
--- a/scripts/node-electron.bat
+++ b/scripts/node-electron.bat
@@ -10,9 +10,9 @@ set NAMESHORT=%NAMESHORT: "=%
set NAMESHORT=%NAMESHORT:"=%.exe
set CODE=".build\electron\%NAMESHORT%"
-%CODE% %*
+%CODE% %* --ms-enable-electron-run-as-node
popd
endlocal
-exit /b %errorlevel% \ No newline at end of file
+exit /b %errorlevel%
diff --git a/scripts/node-electron.sh b/scripts/node-electron.sh
index 0a822b6c383..2bf50817c94 100755
--- a/scripts/node-electron.sh
+++ b/scripts/node-electron.sh
@@ -26,9 +26,11 @@ export VSCODE_DEV=1
if [[ "$OSTYPE" == "darwin"* ]]; then
ulimit -n 4096 ; ELECTRON_RUN_AS_NODE=1 \
"$CODE" \
- "$@"
+ "$@" \
+ --ms-enable-electron-run-as-node
else
ELECTRON_RUN_AS_NODE=1 \
"$CODE" \
- "$@"
+ "$@" \
+ --ms-enable-electron-run-as-node
fi
diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat
index 5210ccc55ac..3da6d3c9e62 100644
--- a/scripts/test-integration.bat
+++ b/scripts/test-integration.bat
@@ -26,6 +26,7 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
compile-extension:markdown-language-features^
compile-extension:typescript-language-features^
compile-extension:vscode-custom-editor-tests^
+ compile-extension:vscode-notebook-tests^
compile-extension:emmet^
compile-extension:css-language-features-server^
compile-extension:html-language-features-server^
diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh
index 72e8fdf4d1f..2eb8ce50a73 100755
--- a/scripts/test-integration.sh
+++ b/scripts/test-integration.sh
@@ -32,6 +32,7 @@ else
yarn gulp compile-extension:vscode-api-tests \
compile-extension:vscode-colorize-tests \
compile-extension:vscode-custom-editor-tests \
+ compile-extension:vscode-notebook-tests \
compile-extension:markdown-language-features \
compile-extension:typescript-language-features \
compile-extension:emmet \
diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts
index 334b238ed94..aa9bcfffc0a 100644
--- a/src/vs/base/browser/ui/sash/sash.ts
+++ b/src/vs/base/browser/ui/sash/sash.ts
@@ -163,7 +163,6 @@ export class Sash extends Disposable {
private el: HTMLElement;
private layoutProvider: ISashLayoutProvider;
- private hidden: boolean;
private orientation!: Orientation;
private size: number;
private hoverDelay = globalHoverDelay;
@@ -317,7 +316,6 @@ export class Sash extends Disposable {
this._register(onDidChangeHoverDelay.event(delay => this.hoverDelay = delay));
- this.hidden = false;
this.layoutProvider = layoutProvider;
this.orthogonalStartSash = options.orthogonalStartSash;
@@ -504,22 +502,6 @@ export class Sash extends Disposable {
}
}
- show(): void {
- this.hidden = false;
- this.el.style.removeProperty('display');
- this.el.setAttribute('aria-hidden', 'false');
- }
-
- hide(): void {
- this.hidden = true;
- this.el.style.display = 'none';
- this.el.setAttribute('aria-hidden', 'true');
- }
-
- isHidden(): boolean {
- return this.hidden;
- }
-
private getOrthogonalSash(e: PointerEvent): Sash | undefined {
if (!e.target || !(e.target instanceof HTMLElement)) {
return undefined;
diff --git a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css
index 5d7a2dc705a..d50aa58526c 100644
--- a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css
+++ b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css
@@ -36,7 +36,6 @@
left: 3px;
height: 3px;
width: 100%;
- box-shadow: #DDD 0 6px 6px -6px inset;
}
.monaco-scrollable-element > .shadow.left {
display: block;
@@ -44,7 +43,6 @@
left: 0;
height: 100%;
width: 3px;
- box-shadow: #DDD 6px 0 6px -6px inset;
}
.monaco-scrollable-element > .shadow.top-left-corner {
display: block;
@@ -53,59 +51,3 @@
height: 3px;
width: 3px;
}
-.monaco-scrollable-element > .shadow.top.left {
- box-shadow: #DDD 6px 6px 6px -6px inset;
-}
-
-/* ---------- Default Style ---------- */
-
-.vs .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(100, 100, 100, .4);
-}
-.vs-dark .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(121, 121, 121, .4);
-}
-.hc-black .monaco-scrollable-element > .scrollbar > .slider {
- background: rgba(111, 195, 223, .6);
-}
-
-.monaco-scrollable-element > .scrollbar > .slider:hover {
- background: rgba(100, 100, 100, .7);
-}
-.hc-black .monaco-scrollable-element > .scrollbar > .slider:hover {
- background: rgba(111, 195, 223, .8);
-}
-
-.monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(0, 0, 0, .6);
-}
-.vs-dark .monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(191, 191, 191, .4);
-}
-.hc-black .monaco-scrollable-element > .scrollbar > .slider.active {
- background: rgba(111, 195, 223, 1);
-}
-
-.vs-dark .monaco-scrollable-element .shadow.top {
- box-shadow: none;
-}
-
-.vs-dark .monaco-scrollable-element .shadow.left {
- box-shadow: #000 6px 0 6px -6px inset;
-}
-
-.vs-dark .monaco-scrollable-element .shadow.top.left {
- box-shadow: #000 6px 6px 6px -6px inset;
-}
-
-.hc-black .monaco-scrollable-element .shadow.top {
- box-shadow: none;
-}
-
-.hc-black .monaco-scrollable-element .shadow.left {
- box-shadow: none;
-}
-
-.hc-black .monaco-scrollable-element .shadow.top.left {
- box-shadow: none;
-}
diff --git a/src/vs/base/browser/ui/table/tableWidget.ts b/src/vs/base/browser/ui/table/tableWidget.ts
index c6c174c0d4b..eb298a582c7 100644
--- a/src/vs/base/browser/ui/table/tableWidget.ts
+++ b/src/vs/base/browser/ui/table/tableWidget.ts
@@ -9,7 +9,7 @@ import { IListOptions, IListOptionsUpdate, IListStyles, List } from 'vs/base/bro
import { ISplitViewDescriptor, IView, Orientation, SplitView } from 'vs/base/browser/ui/splitview/splitview';
import { ITableColumn, ITableContextMenuEvent, ITableEvent, ITableGestureEvent, ITableMouseEvent, ITableRenderer, ITableTouchEvent, ITableVirtualDelegate } from 'vs/base/browser/ui/table/table';
import { Emitter, Event } from 'vs/base/common/event';
-import { IDisposable } from 'vs/base/common/lifecycle';
+import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { ISpliceable } from 'vs/base/common/sequence';
import { IThemable } from 'vs/base/common/styler';
@@ -148,9 +148,11 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
readonly domNode: HTMLElement;
private splitview: SplitView;
private list: List<TRow>;
- private columnLayoutDisposable: IDisposable;
- private cachedHeight: number = 0;
private styleElement: HTMLStyleElement;
+ protected readonly disposables = new DisposableStore();
+
+ private cachedWidth: number = 0;
+ private cachedHeight: number = 0;
get onDidChangeFocus(): Event<ITableEvent<TRow>> { return this.list.onDidChangeFocus; }
get onDidChangeSelection(): Event<ITableEvent<TRow>> { return this.list.onDidChangeSelection; }
@@ -196,21 +198,27 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
views: headers.map(view => ({ size: view.column.weight, view }))
};
- this.splitview = new SplitView(this.domNode, {
+ this.splitview = this.disposables.add(new SplitView(this.domNode, {
orientation: Orientation.HORIZONTAL,
scrollbarVisibility: ScrollbarVisibility.Hidden,
getSashOrthogonalSize: () => this.cachedHeight,
descriptor
- });
+ }));
this.splitview.el.style.height = `${virtualDelegate.headerRowHeight}px`;
this.splitview.el.style.lineHeight = `${virtualDelegate.headerRowHeight}px`;
const renderer = new TableListRenderer(columns, renderers, i => this.splitview.getViewSize(i));
- this.list = new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options);
+ this.list = this.disposables.add(new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options));
+
+ Event.any(...headers.map(h => h.onDidLayout))
+ (([index, size]) => renderer.layoutColumn(index, size), null, this.disposables);
- this.columnLayoutDisposable = Event.any(...headers.map(h => h.onDidLayout))
- (([index, size]) => renderer.layoutColumn(index, size));
+ this.splitview.onDidSashReset(index => {
+ const totalWeight = columns.reduce((r, c) => r + c.weight, 0);
+ const size = columns[index].weight / totalWeight * this.cachedWidth;
+ this.splitview.resizeView(index, size);
+ }, null, this.disposables);
this.styleElement = createStyleSheet(this.domNode);
this.style({});
@@ -248,6 +256,7 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
height = height ?? getContentHeight(this.domNode);
width = width ?? getContentWidth(this.domNode);
+ this.cachedWidth = width;
this.cachedHeight = height;
this.splitview.layout(width);
@@ -337,8 +346,6 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
}
dispose(): void {
- this.splitview.dispose();
- this.list.dispose();
- this.columnLayoutDisposable.dispose();
+ this.disposables.dispose();
}
}
diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts
index b9db31257f9..2e3e020856c 100644
--- a/src/vs/base/common/objects.ts
+++ b/src/vs/base/common/objects.ts
@@ -229,9 +229,9 @@ export function getCaseInsensitive(target: obj, key: string): any {
export function filter(obj: obj, predicate: (key: string, value: any) => boolean): obj {
const result = Object.create(null);
- for (const key of Object.keys(obj)) {
- if (predicate(key, obj[key])) {
- result[key] = obj[key];
+ for (const [key, value] of Object.entries(obj)) {
+ if (predicate(key, value)) {
+ result[key] = value;
}
}
return result;
diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
index b7025539667..3736489d8fc 100644
--- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
+++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts
@@ -13,8 +13,9 @@ import { INewScrollPosition, ScrollType } from 'vs/editor/common/editorCommon';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
-import { getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
+import { registerThemingParticipant, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
+import { scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
export class EditorScrollbar extends ViewPart {
@@ -180,3 +181,51 @@ export class EditorScrollbar extends ViewPart {
this.scrollbar.renderNow();
}
}
+
+registerThemingParticipant((theme, collector) => {
+
+ // Scrollbars
+ const scrollbarShadowColor = theme.getColor(scrollbarShadow);
+ if (scrollbarShadowColor) {
+ collector.addRule(`
+ .monaco-scrollable-element > .shadow.top {
+ box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
+ }
+
+ .monaco-scrollable-element > .shadow.left {
+ box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
+ }
+
+ .monaco-scrollable-element > .shadow.top.left {
+ box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
+ }
+ `);
+ }
+
+ const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);
+ if (scrollbarSliderBackgroundColor) {
+ collector.addRule(`
+ .monaco-scrollable-element > .scrollbar > .slider {
+ background: ${scrollbarSliderBackgroundColor};
+ }
+ `);
+ }
+
+ const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);
+ if (scrollbarSliderHoverBackgroundColor) {
+ collector.addRule(`
+ .monaco-scrollable-element > .scrollbar > .slider:hover {
+ background: ${scrollbarSliderHoverBackgroundColor};
+ }
+ `);
+ }
+
+ const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);
+ if (scrollbarSliderActiveBackgroundColor) {
+ collector.addRule(`
+ .monaco-scrollable-element > .scrollbar > .slider.active {
+ background: ${scrollbarSliderActiveBackgroundColor};
+ }
+ `);
+ }
+});
diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts
index fae61d04453..6eda6513b9f 100644
--- a/src/vs/editor/common/config/editorOptions.ts
+++ b/src/vs/editor/common/config/editorOptions.ts
@@ -4373,7 +4373,7 @@ export const EditorOptions = {
default: 0,
minimum: 0,
maximum: 100,
- markdownDescription: nls.localize('codeLensFontSize', "Controls the font size in pixels for CodeLens. When set to `0`, the 90% of `#editor.fontSize#` is used.")
+ markdownDescription: nls.localize('codeLensFontSize', "Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.")
})),
colorDecorators: register(new EditorBooleanOption(
EditorOption.colorDecorators, 'colorDecorators', true,
diff --git a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts
index 279c419a56c..129a4a9f58f 100644
--- a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts
+++ b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts
@@ -11,7 +11,6 @@ import { Disposable, IDisposable, MutableDisposable, toDisposable } from 'vs/bas
import { commonPrefixLength, commonSuffixLength } from 'vs/base/common/strings';
import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
-import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
@@ -43,8 +42,6 @@ export class InlineCompletionsModel extends Disposable implements GhostTextWidge
this._register(commandService.onDidExecuteCommand(e => {
// These commands don't trigger onDidType.
const commands = new Set([
- UndoCommand.id,
- RedoCommand.id,
CoreEditingCommands.Tab.id,
CoreEditingCommands.DeleteLeft.id,
CoreEditingCommands.DeleteRight.id,
diff --git a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts
index cf1a2e73370..671f8e39ad3 100644
--- a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts
+++ b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts
@@ -491,7 +491,6 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
this._resizeSash = this._disposables.add(new Sash(this.domNode, this, { orientation: Orientation.HORIZONTAL }));
if (!this.options.isResizeable) {
- this._resizeSash.hide();
this._resizeSash.state = SashState.Disabled;
}
diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts
index 1d8403c185b..14b5bbb886a 100644
--- a/src/vs/editor/standalone/browser/standaloneLanguages.ts
+++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts
@@ -49,8 +49,8 @@ export function getEncodedLanguageId(languageId: string): number {
* @event
*/
export function onLanguage(languageId: string, callback: () => void): IDisposable {
- let disposable = StaticServices.modeService.get().onDidEncounterLanguage((languageId) => {
- if (languageId === languageId) {
+ let disposable = StaticServices.modeService.get().onDidEncounterLanguage((encounteredLanguageId) => {
+ if (encounteredLanguageId === languageId) {
// stop listening
disposable.dispose();
// invoke actual listener
diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts
index 779f91ebf31..9feb2e1bcb3 100644
--- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts
+++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts
@@ -132,6 +132,19 @@ class StandaloneTheme implements IStandaloneTheme {
encodedTokensColors = baseData.encodedTokensColors;
}
}
+ // Pick up default colors from `editor.foreground` and `editor.background` if available
+ const editorForeground = this.themeData.colors['editor.foreground'];
+ const editorBackground = this.themeData.colors['editor.background'];
+ if (editorForeground || editorBackground) {
+ const rule: ITokenThemeRule = { token: '' };
+ if (editorForeground) {
+ rule.foreground = editorForeground;
+ }
+ if (editorBackground) {
+ rule.background = editorBackground;
+ }
+ rules.push(rule);
+ }
rules = rules.concat(this.themeData.rules);
if (this.themeData.encodedTokensColors) {
encodedTokensColors = this.themeData.encodedTokensColors;
diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts
index a67a1dc44ea..326a4430832 100644
--- a/src/vs/platform/environment/common/argv.ts
+++ b/src/vs/platform/environment/common/argv.ts
@@ -106,4 +106,7 @@ export interface NativeParsedArgs {
'allow-insecure-localhost'?: boolean;
'log-net-log'?: string;
'vmodule'?: string;
+
+ // MS Build command line arg
+ 'ms-enable-electron-run-as-node'?: boolean;
}
diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts
index 7260f87c2c5..821cbf257f6 100644
--- a/src/vs/platform/environment/node/argv.ts
+++ b/src/vs/platform/environment/node/argv.ts
@@ -75,6 +75,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'inspect-extensions': { type: 'string', deprecates: 'debugPluginHost', args: 'port', cat: 't', description: localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI.") },
'inspect-brk-extensions': { type: 'string', deprecates: 'debugBrkPluginHost', args: 'port', cat: 't', description: localize('inspect-brk-extensions', "Allow debugging and profiling of extensions with the extension host being paused after start. Check the developer tools for the connection URI.") },
'disable-gpu': { type: 'boolean', cat: 't', description: localize('disableGPU', "Disable GPU hardware acceleration.") },
+ 'ms-enable-electron-run-as-node': { type: 'boolean' },
'max-memory': { type: 'string', cat: 't', description: localize('maxMemory', "Max memory size for a window (in Mbytes)."), args: 'memory' },
'telemetry': { type: 'boolean', cat: 't', description: localize('telemetry', "Shows all telemetry events which VS code collects.") },
diff --git a/src/vs/platform/environment/node/shellEnv.ts b/src/vs/platform/environment/node/shellEnv.ts
index de217e36abe..a80d1f69863 100644
--- a/src/vs/platform/environment/node/shellEnv.ts
+++ b/src/vs/platform/environment/node/shellEnv.ts
@@ -127,13 +127,14 @@ async function doResolveUnixShellEnv(logService: ILogService, token: Cancellatio
// handle popular non-POSIX shells
const name = basename(systemShellUnix);
let command: string, shellArgs: Array<string>;
+ const extraArgs = (process.versions['electron'] && process.versions['microsoft-build']) ? '--ms-enable-electron-run-as-node' : '';
if (/^pwsh(-preview)?$/.test(name)) {
// Older versions of PowerShell removes double quotes sometimes so we use "double single quotes" which is how
// you escape single quotes inside of a single quoted string.
- command = `& '${process.execPath}' -p '''${mark}'' + JSON.stringify(process.env) + ''${mark}'''`;
+ command = `& '${process.execPath}' ${extraArgs} -p '''${mark}'' + JSON.stringify(process.env) + ''${mark}'''`;
shellArgs = ['-Login', '-Command'];
} else {
- command = `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`;
+ command = `'${process.execPath}' ${extraArgs} -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`;
if (name === 'tcsh') {
shellArgs = ['-ic'];
diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts
index 875f8dc075f..3c14449399f 100644
--- a/src/vs/platform/list/browser/listService.ts
+++ b/src/vs/platform/list/browser/listService.ts
@@ -484,7 +484,6 @@ export class WorkbenchTable<TRow> extends Table<TRow> {
private horizontalScrolling: boolean | undefined;
private _styler: IDisposable | undefined;
private _useAltAsMultipleSelectionModifier: boolean;
- private readonly disposables: DisposableStore;
private navigator: TableResourceNavigator<TRow>;
get onDidOpen(): Event<IOpenEvent<TRow | undefined>> { return this.navigator.onDidOpen; }
@@ -513,7 +512,6 @@ export class WorkbenchTable<TRow> extends Table<TRow> {
}
);
- this.disposables = new DisposableStore();
this.disposables.add(workbenchListOptionsDisposable);
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts
index da5cb11136c..37d19f0bcad 100644
--- a/src/vs/platform/product/common/product.ts
+++ b/src/vs/platform/product/common/product.ts
@@ -57,7 +57,7 @@ else {
// Running out of sources
if (Object.keys(product).length === 0) {
Object.assign(product, {
- version: '1.62.0-dev',
+ version: '1.63.0-dev',
nameShort: 'Code - OSS Dev',
nameLong: 'Code - OSS Dev',
applicationName: 'code-oss',
diff --git a/src/vs/platform/userDataSync/common/userDataSyncAccount.ts b/src/vs/platform/userDataSync/common/userDataSyncAccount.ts
index 514e3d00e6c..1c5c6894c74 100644
--- a/src/vs/platform/userDataSync/common/userDataSyncAccount.ts
+++ b/src/vs/platform/userDataSync/common/userDataSyncAccount.ts
@@ -6,7 +6,7 @@
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
-import { IUserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSync';
+import { IUserDataSyncLogService, IUserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSync';
export interface IUserDataSyncAccount {
readonly authenticationProviderId: string;
@@ -39,10 +39,12 @@ export class UserDataSyncAccountService extends Disposable implements IUserDataS
private wasTokenFailed: boolean = false;
constructor(
- @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService
+ @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
+ @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
) {
super();
this._register(userDataSyncStoreService.onTokenFailed(() => {
+ this.logService.info('Settings Sync auth token failed', this.account?.authenticationProviderId, this.wasTokenFailed);
this.updateAccount(undefined);
this._onTokenFailed.fire(this.wasTokenFailed);
this.wasTokenFailed = true;
diff --git a/src/vs/server/remoteCli.ts b/src/vs/server/remoteCli.ts
index fcc82d710ae..28dfc625974 100644
--- a/src/vs/server/remoteCli.ts
+++ b/src/vs/server/remoteCli.ts
@@ -236,6 +236,7 @@ export function main(desc: ProductDescription, args: string[]): void {
} else {
const cliCwd = dirname(cliCommand);
const env = { ...process.env, ELECTRON_RUN_AS_NODE: '1' };
+ newCommandline.unshift('--ms-enable-electron-run-as-node');
newCommandline.unshift('resources/app/out/cli.js');
if (parsedArgs['verbose']) {
console.log(`Invoking: ${cliCommand} ${newCommandline.join(' ')} in ${cliCwd}`);
diff --git a/src/vs/server/remoteTerminalChannel.ts b/src/vs/server/remoteTerminalChannel.ts
index 2c31f0cd99e..5c47282ff63 100644
--- a/src/vs/server/remoteTerminalChannel.ts
+++ b/src/vs/server/remoteTerminalChannel.ts
@@ -15,7 +15,7 @@ import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { createRandomIPCHandle } from 'vs/base/parts/ipc/node/ipc.net';
import { ILogService } from 'vs/platform/log/common/log';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
-import { IPtyService, IShellLaunchConfig, ITerminalProfile, ITerminalsLayoutInfo } from 'vs/platform/terminal/common/terminal';
+import { IPtyService, IShellLaunchConfig, ITerminalProfile } from 'vs/platform/terminal/common/terminal';
import { IGetTerminalLayoutInfoArgs, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { createRemoteURITransformer } from 'vs/server/remoteUriTransformer';
@@ -124,8 +124,8 @@ export class RemoteTerminalChannel extends Disposable implements IServerChannel<
case '$getProfiles': return this._getProfiles.apply(this, args);
case '$getEnvironment': return this._getEnvironment();
case '$getWslPath': return this._getWslPath(args[0]);
- case '$getTerminalLayoutInfo': return this._getTerminalLayoutInfo(<IGetTerminalLayoutInfoArgs>args);
- case '$setTerminalLayoutInfo': return this._setTerminalLayoutInfo(<ISetTerminalLayoutInfoArgs>args);
+ case '$getTerminalLayoutInfo': return this._ptyService.getTerminalLayoutInfo(<IGetTerminalLayoutInfoArgs>args);
+ case '$setTerminalLayoutInfo': return this._ptyService.setTerminalLayoutInfo(<ISetTerminalLayoutInfoArgs>args);
case '$serializeTerminalState': return this._ptyService.serializeTerminalState.apply(this._ptyService, args);
case '$reviveTerminalProcesses': return this._ptyService.reviveTerminalProcesses.apply(this._ptyService, args);
case '$setUnicodeVersion': return this._ptyService.setUnicodeVersion.apply(this._ptyService, args);
@@ -315,13 +315,6 @@ export class RemoteTerminalChannel extends Disposable implements IServerChannel<
return this._ptyService.getWslPath(original);
}
- private _setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): void {
- this._ptyService.setTerminalLayoutInfo(args);
- }
-
- private async _getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise<ITerminalsLayoutInfo | undefined> {
- return this._ptyService.getTerminalLayoutInfo(args);
- }
private _reduceConnectionGraceTime(): Promise<void> {
return this._ptyService.reduceConnectionGraceTime();
diff --git a/src/vs/workbench/api/browser/mainThreadCodeInsets.ts b/src/vs/workbench/api/browser/mainThreadCodeInsets.ts
index 18dddc41b8c..96a88b5c886 100644
--- a/src/vs/workbench/api/browser/mainThreadCodeInsets.ts
+++ b/src/vs/workbench/api/browser/mainThreadCodeInsets.ts
@@ -10,7 +10,7 @@ import { IActiveCodeEditor, IViewZone } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { reviveWebviewContentOptions } from 'vs/workbench/api/browser/mainThreadWebviews';
-import { ExtHostContext, ExtHostEditorInsetsShape, IExtHostContext, IWebviewOptions, MainContext, MainThreadEditorInsetsShape } from 'vs/workbench/api/common/extHost.protocol';
+import { ExtHostContext, ExtHostEditorInsetsShape, IExtHostContext, IWebviewContentOptions, MainContext, MainThreadEditorInsetsShape } from 'vs/workbench/api/common/extHost.protocol';
import { IWebviewService, IWebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { extHostNamedCustomer } from '../common/extHostCustomers';
@@ -70,7 +70,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
this._disposables.dispose();
}
- async $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void> {
+ async $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewContentOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void> {
let editor: IActiveCodeEditor | undefined;
id = id.substr(0, id.indexOf(',')); //todo@jrieken HACK
@@ -121,7 +121,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
inset.webview.html = value;
}
- $setOptions(handle: number, options: IWebviewOptions): void {
+ $setOptions(handle: number, options: IWebviewContentOptions): void {
const inset = this.getInset(handle);
inset.webview.contentOptions = reviveWebviewContentOptions(options);
}
diff --git a/src/vs/workbench/api/browser/mainThreadSCM.ts b/src/vs/workbench/api/browser/mainThreadSCM.ts
index 75328bdf9ae..0e36a47285a 100644
--- a/src/vs/workbench/api/browser/mainThreadSCM.ts
+++ b/src/vs/workbench/api/browser/mainThreadSCM.ts
@@ -431,15 +431,6 @@ export class MainThreadSCM implements MainThreadSCMShape {
repository.input.visible = visible;
}
- $setInputBoxFocus(sourceControlHandle: number): void {
- const repository = this._repositories.get(sourceControlHandle);
- if (!repository) {
- return;
- }
-
- repository.input.setFocus();
- }
-
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType) {
const repository = this._repositories.get(sourceControlHandle);
if (!repository) {
diff --git a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts
index 1aad68ab99a..d355e0876c4 100644
--- a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts
+++ b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts
@@ -5,17 +5,17 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
-import { URI, UriComponents } from 'vs/base/common/uri';
+import { URI } from 'vs/base/common/uri';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { MainThreadWebviews, reviveWebviewContentOptions, reviveWebviewExtension } from 'vs/workbench/api/browser/mainThreadWebviews';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
-import { EditorInput } from 'vs/workbench/common/editor/editorInput';
-import { EditorGroupColumn, columnToEditorGroup, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
+import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
+import { columnToEditorGroup, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -151,13 +151,8 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
extensionData: extHostProtocol.WebviewExtensionDescription,
handle: extHostProtocol.WebviewHandle,
viewType: string,
- initData: {
- title: string;
- webviewOptions: extHostProtocol.IWebviewOptions;
- panelOptions: extHostProtocol.IWebviewPanelOptions;
- serializeBuffersForPostMessage: boolean;
- },
- showOptions: { viewColumn?: EditorGroupColumn, preserveFocus?: boolean; },
+ initData: extHostProtocol.IWebviewInitData,
+ showOptions: extHostProtocol.WebviewPanelShowOptions,
): void {
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
if (showOptions) {
@@ -192,7 +187,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
webview.setName(value);
}
- public $setIconPath(handle: extHostProtocol.WebviewHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void {
+ public $setIconPath(handle: extHostProtocol.WebviewHandle, value: extHostProtocol.IWebviewIconPath | undefined): void {
const webview = this.getWebviewInput(handle);
webview.iconPath = reviveWebviewIcon(value);
}
@@ -316,12 +311,14 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
}
}
-function reviveWebviewIcon(
- value: { light: UriComponents, dark: UriComponents; } | undefined
-): WebviewIcons | undefined {
- return value
- ? { light: URI.revive(value.light), dark: URI.revive(value.dark) }
- : undefined;
+function reviveWebviewIcon(value: extHostProtocol.IWebviewIconPath | undefined): WebviewIcons | undefined {
+ if (!value) {
+ return undefined;
+ }
+ return {
+ light: URI.revive(value.light),
+ dark: URI.revive(value.dark),
+ };
}
function reviveWebviewOptions(panelOptions: extHostProtocol.IWebviewPanelOptions): WebviewOptions {
diff --git a/src/vs/workbench/api/browser/mainThreadWebviews.ts b/src/vs/workbench/api/browser/mainThreadWebviews.ts
index 0870dcc05d6..25b3f61f574 100644
--- a/src/vs/workbench/api/browser/mainThreadWebviews.ts
+++ b/src/vs/workbench/api/browser/mainThreadWebviews.ts
@@ -55,7 +55,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
webview.html = value;
}
- public $setOptions(handle: extHostProtocol.WebviewHandle, options: extHostProtocol.IWebviewOptions): void {
+ public $setOptions(handle: extHostProtocol.WebviewHandle, options: extHostProtocol.IWebviewContentOptions): void {
const webview = this.getWebview(handle);
webview.contentOptions = reviveWebviewContentOptions(options);
}
@@ -123,10 +123,13 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
export function reviveWebviewExtension(extensionData: extHostProtocol.WebviewExtensionDescription): WebviewExtensionDescription {
- return { id: extensionData.id, location: URI.revive(extensionData.location) };
+ return {
+ id: extensionData.id,
+ location: URI.revive(extensionData.location),
+ };
}
-export function reviveWebviewContentOptions(webviewOptions: extHostProtocol.IWebviewOptions): WebviewContentOptions {
+export function reviveWebviewContentOptions(webviewOptions: extHostProtocol.IWebviewContentOptions): WebviewContentOptions {
return {
allowScripts: webviewOptions.enableScripts,
allowForms: webviewOptions.enableForms,
diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts
index 3313761cc00..84e2a4eb04a 100644
--- a/src/vs/workbench/api/common/extHost.api.impl.ts
+++ b/src/vs/workbench/api/common/extHost.api.impl.ts
@@ -226,7 +226,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const authentication: typeof vscode.authentication = {
getSession(providerId: string, scopes: readonly string[], options?: vscode.AuthenticationGetSessionOptions) {
- if (options?.forceNewSession || options?.silent) {
+ if (options?.forceNewSession) {
checkProposedApiEnabled(extension);
}
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts
index 2291bc2eea0..12c7f9a5bd3 100644
--- a/src/vs/workbench/api/common/extHost.protocol.ts
+++ b/src/vs/workbench/api/common/extHost.protocol.ts
@@ -618,11 +618,11 @@ export interface MainThreadTelemetryShape extends IDisposable {
}
export interface MainThreadEditorInsetsShape extends IDisposable {
- $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void>;
+ $createEditorInset(handle: number, id: string, uri: UriComponents, line: number, height: number, options: IWebviewContentOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): Promise<void>;
$disposeEditorInset(handle: number): void;
$setHtml(handle: number, value: string): void;
- $setOptions(handle: number, options: IWebviewOptions): void;
+ $setOptions(handle: number, options: IWebviewContentOptions): void;
$postMessage(handle: number, value: any): Promise<boolean>;
}
@@ -681,12 +681,12 @@ export interface IWebviewPortMapping {
readonly extensionHostPort: number;
}
-export interface IWebviewOptions {
+export interface IWebviewContentOptions {
readonly enableScripts?: boolean;
readonly enableForms?: boolean;
readonly enableCommandUris?: boolean;
- readonly localResourceRoots?: ReadonlyArray<UriComponents>;
- readonly portMapping?: ReadonlyArray<IWebviewPortMapping>;
+ readonly localResourceRoots?: readonly UriComponents[];
+ readonly portMapping?: readonly IWebviewPortMapping[];
}
export interface IWebviewPanelOptions {
@@ -729,27 +729,34 @@ export interface WebviewMessageArrayBufferReference {
export interface MainThreadWebviewsShape extends IDisposable {
$setHtml(handle: WebviewHandle, value: string): void;
- $setOptions(handle: WebviewHandle, options: IWebviewOptions): void;
+ $setOptions(handle: WebviewHandle, options: IWebviewContentOptions): void;
$postMessage(handle: WebviewHandle, value: string, ...buffers: VSBuffer[]): Promise<boolean>
}
+export interface IWebviewIconPath {
+ readonly light: UriComponents;
+ readonly dark: UriComponents;
+}
+
+export interface IWebviewInitData {
+ readonly title: string;
+ readonly webviewOptions: IWebviewContentOptions;
+ readonly panelOptions: IWebviewPanelOptions;
+ readonly serializeBuffersForPostMessage: boolean;
+}
+
export interface MainThreadWebviewPanelsShape extends IDisposable {
$createWebviewPanel(
extension: WebviewExtensionDescription,
handle: WebviewHandle,
viewType: string,
- initData: {
- title: string;
- webviewOptions: IWebviewOptions;
- panelOptions: IWebviewPanelOptions;
- serializeBuffersForPostMessage: boolean;
- },
+ initData: IWebviewInitData,
showOptions: WebviewPanelShowOptions,
): void;
$disposeWebview(handle: WebviewHandle): void;
$reveal(handle: WebviewHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewHandle, value: string): void;
- $setIconPath(handle: WebviewHandle, value: { light: UriComponents, dark: UriComponents; } | undefined): void;
+ $setIconPath(handle: WebviewHandle, value: IWebviewIconPath | undefined): void;
$registerSerializer(viewType: string, options: { serializeBuffersForPostMessage: boolean }): void;
$unregisterSerializer(viewType: string): void;
@@ -796,7 +803,7 @@ export interface ExtHostWebviewPanelsShape {
initData: {
title: string;
state: any;
- webviewOptions: IWebviewOptions;
+ webviewOptions: IWebviewContentOptions;
panelOptions: IWebviewPanelOptions;
},
position: EditorGroupColumn,
@@ -810,7 +817,7 @@ export interface ExtHostCustomEditorsShape {
viewType: string,
initData: {
title: string;
- webviewOptions: IWebviewOptions;
+ webviewOptions: IWebviewContentOptions;
panelOptions: IWebviewPanelOptions;
},
position: EditorGroupColumn,
@@ -1096,7 +1103,6 @@ export interface MainThreadSCMShape extends IDisposable {
$setInputBoxValue(sourceControlHandle: number, value: string): void;
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
$setInputBoxVisibility(sourceControlHandle: number, visible: boolean): void;
- $setInputBoxFocus(sourceControlHandle: number): void;
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType): void;
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
}
diff --git a/src/vs/workbench/api/common/extHostCustomEditors.ts b/src/vs/workbench/api/common/extHostCustomEditors.ts
index 35eb01c390c..5f9a06d01de 100644
--- a/src/vs/workbench/api/common/extHostCustomEditors.ts
+++ b/src/vs/workbench/api/common/extHostCustomEditors.ts
@@ -253,7 +253,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
viewType: string,
initData: {
title: string;
- webviewOptions: extHostProtocol.IWebviewOptions;
+ webviewOptions: extHostProtocol.IWebviewContentOptions;
panelOptions: extHostProtocol.IWebviewPanelOptions;
},
position: EditorGroupColumn,
diff --git a/src/vs/workbench/api/common/extHostOutput.ts b/src/vs/workbench/api/common/extHostOutput.ts
index 8d7158e8778..186031d7205 100644
--- a/src/vs/workbench/api/common/extHostOutput.ts
+++ b/src/vs/workbench/api/common/extHostOutput.ts
@@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri';
import { Disposable } from 'vs/base/common/lifecycle';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
-import { IExtensionDescription, checkProposedApiEnabled } from 'vs/platform/extensions/common/extensions';
+import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ILogger, ILoggerService } from 'vs/platform/log/common/log';
import { OutputChannelUpdateMode } from 'vs/workbench/contrib/output/common/output';
import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
@@ -127,7 +127,7 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
this.channels.set(channel.id, channel);
channel.visible = channel.id === this.visibleChannelId;
});
- return this.createExtHostOutputChannel(name, extHostOutputChannel, extension);
+ return this.createExtHostOutputChannel(name, extHostOutputChannel);
}
private async doCreateOutputChannel(name: string, extension: IExtensionDescription): Promise<ExtHostOutputChannel> {
@@ -145,58 +145,42 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
return this.outputDirectoryPromise;
}
- private createExtHostOutputChannel(name: string, channelPromise: Promise<ExtHostOutputChannel>, extensionDescription: IExtensionDescription): vscode.OutputChannel {
- const validate = (channel: ExtHostOutputChannel, checkProposedApi?: boolean) => {
- if (checkProposedApi) {
- checkProposedApiEnabled(extensionDescription);
- }
- if (channel.disposed) {
+ private createExtHostOutputChannel(name: string, channelPromise: Promise<ExtHostOutputChannel>): vscode.OutputChannel {
+ let disposed = false;
+ const validate = () => {
+ if (disposed) {
throw new Error('Channel has been closed');
}
};
return {
get name(): string { return name; },
append(value: string): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.append(value);
- });
+ validate();
+ channelPromise.then(channel => channel.append(value));
},
appendLine(value: string): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.appendLine(value);
- });
+ validate();
+ channelPromise.then(channel => channel.appendLine(value));
},
clear(): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.clear();
- });
+ validate();
+ channelPromise.then(channel => channel.clear());
},
replace(value: string): void {
- channelPromise.then(channel => {
- validate(channel, true);
- channel.replace(value);
- });
+ validate();
+ channelPromise.then(channel => channel.replace(value));
},
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.show(columnOrPreserveFocus, preserveFocus);
- });
+ validate();
+ channelPromise.then(channel => channel.show(columnOrPreserveFocus, preserveFocus));
},
hide(): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.hide();
- });
+ validate();
+ channelPromise.then(channel => channel.hide());
},
dispose(): void {
- channelPromise.then(channel => {
- validate(channel);
- channel.dispose();
- });
+ disposed = true;
+ channelPromise.then(channel => channel.dispose());
}
};
}
diff --git a/src/vs/workbench/api/common/extHostQuickOpen.ts b/src/vs/workbench/api/common/extHostQuickOpen.ts
index f05cc14db02..96374d8e4be 100644
--- a/src/vs/workbench/api/common/extHostQuickOpen.ts
+++ b/src/vs/workbench/api/common/extHostQuickOpen.ts
@@ -193,7 +193,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
// ---- QuickInput
createQuickPick<T extends QuickPickItem>(extensionId: ExtensionIdentifier, enableProposedApi: boolean): QuickPick<T> {
- const session: ExtHostQuickPick<T> = new ExtHostQuickPick(extensionId, enableProposedApi, () => this._sessions.delete(session._id));
+ const session: ExtHostQuickPick<T> = new ExtHostQuickPick(extensionId, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
}
@@ -531,7 +531,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
private readonly _onDidChangeSelectionEmitter = new Emitter<T[]>();
private readonly _onDidTriggerItemButtonEmitter = new Emitter<QuickPickItemButtonEvent<T>>();
- constructor(extensionId: ExtensionIdentifier, private readonly enableProposedApi: boolean, onDispose: () => void) {
+ constructor(extensionId: ExtensionIdentifier, onDispose: () => void) {
super(extensionId, onDispose);
this._disposables.push(
this._onDidChangeActiveEmitter,
@@ -561,16 +561,13 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
detail: item.detail,
picked: item.picked,
alwaysShow: item.alwaysShow,
- // Proposed API only at the moment
- buttons: item.buttons && this.enableProposedApi
- ? item.buttons.map<TransferQuickInputButton>((button, i) => {
- return {
- ...getIconPathOrClass(button),
- tooltip: button.tooltip,
- handle: i
- };
- })
- : undefined,
+ buttons: item.buttons?.map<TransferQuickInputButton>((button, i) => {
+ return {
+ ...getIconPathOrClass(button),
+ tooltip: button.tooltip,
+ handle: i
+ };
+ }),
}))
});
}
diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts
index 11aa457b084..26988a5fe22 100644
--- a/src/vs/workbench/api/common/extHostSCM.ts
+++ b/src/vs/workbench/api/common/extHostSCM.ts
@@ -266,16 +266,6 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
// noop
}
- focus(): void {
- checkProposedApiEnabled(this._extension);
-
- if (!this._visible) {
- this.visible = true;
- }
-
- this._proxy.$setInputBoxFocus(this._sourceControlHandle);
- }
-
showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) {
checkProposedApiEnabled(this._extension);
diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts
index d472ed4414d..2eb67a7bf10 100644
--- a/src/vs/workbench/api/common/extHostWebview.ts
+++ b/src/vs/workbench/api/common/extHostWebview.ts
@@ -176,7 +176,7 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
this._logService.warn(`${extensionId} created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp`);
}
- public createNewWebview(handle: string, options: extHostProtocol.IWebviewOptions, extension: IExtensionDescription): ExtHostWebview {
+ public createNewWebview(handle: string, options: extHostProtocol.IWebviewContentOptions, extension: IExtensionDescription): ExtHostWebview {
const webview = new ExtHostWebview(handle, this._webviewProxy, reviveOptions(options), this.initData, this.workspace, extension, this._deprecationService);
this._webviews.set(handle, webview);
@@ -202,7 +202,7 @@ export function serializeWebviewOptions(
extension: IExtensionDescription,
workspace: IExtHostWorkspace | undefined,
options: vscode.WebviewOptions,
-): extHostProtocol.IWebviewOptions {
+): extHostProtocol.IWebviewContentOptions {
return {
enableCommandUris: options.enableCommandUris,
enableScripts: options.enableScripts,
@@ -212,7 +212,7 @@ export function serializeWebviewOptions(
};
}
-export function reviveOptions(options: extHostProtocol.IWebviewOptions): vscode.WebviewOptions {
+export function reviveOptions(options: extHostProtocol.IWebviewContentOptions): vscode.WebviewOptions {
return {
enableCommandUris: options.enableCommandUris,
enableScripts: options.enableScripts,
diff --git a/src/vs/workbench/api/common/extHostWebviewPanels.ts b/src/vs/workbench/api/common/extHostWebviewPanels.ts
index c76c364c392..188bda392c1 100644
--- a/src/vs/workbench/api/common/extHostWebviewPanels.ts
+++ b/src/vs/workbench/api/common/extHostWebviewPanels.ts
@@ -281,7 +281,7 @@ export class ExtHostWebviewPanels implements extHostProtocol.ExtHostWebviewPanel
initData: {
title: string;
state: any;
- webviewOptions: extHostProtocol.IWebviewOptions;
+ webviewOptions: extHostProtocol.IWebviewContentOptions;
panelOptions: extHostProtocol.IWebviewPanelOptions;
},
position: EditorGroupColumn
diff --git a/src/vs/workbench/browser/parts/editor/editorPanes.ts b/src/vs/workbench/browser/parts/editor/editorPanes.ts
index 13e9fbc0e8d..86562c72954 100644
--- a/src/vs/workbench/browser/parts/editor/editorPanes.ts
+++ b/src/vs/workbench/browser/parts/editor/editorPanes.ts
@@ -12,7 +12,7 @@ import { IEditorPaneRegistry, IEditorPaneDescriptor } from 'vs/workbench/browser
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { IEditorProgressService, IOperation, LongRunningOperation } from 'vs/platform/progress/common/progress';
+import { IEditorProgressService, LongRunningOperation } from 'vs/platform/progress/common/progress';
import { IEditorGroupView, DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
import { Emitter } from 'vs/base/common/event';
import { assertIsDefined } from 'vs/base/common/types';
@@ -146,20 +146,8 @@ export class EditorPanes extends Disposable {
// Editor pane
const pane = this.doShowEditorPane(descriptor);
- // Show progress while setting input after a certain timeout.
- // If the workbench is opening be more relaxed about progress
- // showing by increasing the delay a little bit to reduce flicker.
- const operation = this.editorOperation.start(this.layoutService.isRestored() ? 800 : 3200);
-
// Apply input to pane
- let changed: boolean;
- let cancelled: boolean;
- try {
- changed = await this.doSetInput(pane, operation, editor, options, context);
- cancelled = !operation.isCurrent();
- } finally {
- operation.stop();
- }
+ const { changed, cancelled } = await this.doSetInput(pane, editor, options, context);
// Focus unless cancelled
if (!cancelled) {
@@ -263,22 +251,36 @@ export class EditorPanes extends Disposable {
this._onDidChangeSizeConstraints.fire(undefined);
}
- private async doSetInput(editorPane: EditorPane, operation: IOperation, editor: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext): Promise<boolean> {
- const forceReload = options?.forceReload;
- const inputMatches = editorPane.input?.matches(editor);
+ private async doSetInput(editorPane: EditorPane, editor: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext): Promise<{ changed: boolean, cancelled: boolean }> {
- // If the input did not change, return early and only apply the options
- // unless the options instruct us to force open it even if it is the same
- if (inputMatches && !forceReload) {
+ // If the input did not change, return early and only
+ // apply the options unless the options instruct us to
+ // force open it even if it is the same
+ const inputMatches = editorPane.input?.matches(editor);
+ if (inputMatches && !options?.forceReload) {
editorPane.setOptions(options);
+
+ return { changed: false, cancelled: false };
}
- // Otherwise set the input to the editor pane
- else {
+ // Start a new editor input operation to report progress
+ // and to support cancellation. Any new operation that is
+ // started will cancel the previous one.
+ const operation = this.editorOperation.start(this.layoutService.isRestored() ? 800 : 3200);
+
+ // Set the input to the editor pane
+ let cancelled = false;
+ try {
await editorPane.setInput(editor, options, context, operation.token);
+
+ if (!operation.isCurrent()) {
+ cancelled = true;
+ }
+ } finally {
+ operation.stop();
}
- return !inputMatches;
+ return { changed: !inputMatches, cancelled };
}
private doHideActiveEditorPane(): void {
diff --git a/src/vs/workbench/browser/style.ts b/src/vs/workbench/browser/style.ts
index 6971905465e..d7472ac31b2 100644
--- a/src/vs/workbench/browser/style.ts
+++ b/src/vs/workbench/browser/style.ts
@@ -5,7 +5,7 @@
import 'vs/css!./media/style';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
-import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground, toolbarHoverBackground, toolbarActiveBackground, toolbarHoverOutline, listFocusHighlightForeground } from 'vs/platform/theme/common/colorRegistry';
+import { iconForeground, foreground, selectionBackground, focusBorder, listHighlightForeground, inputPlaceholderForeground, toolbarHoverBackground, toolbarActiveBackground, toolbarHoverOutline, listFocusHighlightForeground } from 'vs/platform/theme/common/colorRegistry';
import { WORKBENCH_BACKGROUND, TITLE_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
import { isWeb, isIOS, isMacintosh, isWindows } from 'vs/base/common/platform';
import { createMetaElement } from 'vs/base/browser/dom';
@@ -71,51 +71,6 @@ registerThemingParticipant((theme, collector) => {
`);
}
- // Scrollbars
- const scrollbarShadowColor = theme.getColor(scrollbarShadow);
- if (scrollbarShadowColor) {
- collector.addRule(`
- .monaco-workbench .monaco-scrollable-element > .shadow.top {
- box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
- }
-
- .monaco-workbench .monaco-scrollable-element > .shadow.left {
- box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
- }
-
- .monaco-workbench .monaco-scrollable-element > .shadow.top.left {
- box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
- }
- `);
- }
-
- const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);
- if (scrollbarSliderBackgroundColor) {
- collector.addRule(`
- .monaco-workbench .monaco-scrollable-element > .scrollbar > .slider {
- background: ${scrollbarSliderBackgroundColor};
- }
- `);
- }
-
- const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);
- if (scrollbarSliderHoverBackgroundColor) {
- collector.addRule(`
- .monaco-workbench .monaco-scrollable-element > .scrollbar > .slider:hover {
- background: ${scrollbarSliderHoverBackgroundColor};
- }
- `);
- }
-
- const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);
- if (scrollbarSliderActiveBackgroundColor) {
- collector.addRule(`
- .monaco-workbench .monaco-scrollable-element > .scrollbar > .slider.active {
- background: ${scrollbarSliderActiveBackgroundColor};
- }
- `);
- }
-
// Focus outline
const focusOutline = theme.getColor(focusBorder);
if (focusOutline) {
diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
index 02eb0b0f14b..03526042cdf 100644
--- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
+++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
@@ -574,13 +574,16 @@ class Launch extends AbstractLaunch implements ILaunch {
} catch {
// launch.json not found: create one by collecting launch configs from debugConfigProviders
content = await this.getInitialConfigurationContent(this.workspace.uri, type, token);
- if (content) {
- created = true; // pin only if config file is created #8727
- try {
- await this.textFileService.write(resource, content);
- } catch (error) {
- throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error.message));
- }
+ if (!content) {
+ // Cancelled
+ return { editor: null, created: false };
+ }
+
+ created = true; // pin only if config file is created #8727
+ try {
+ await this.textFileService.write(resource, content);
+ } catch (error) {
+ throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error.message));
}
}
diff --git a/src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts b/src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts
index 7c7ec29e9b9..24a9f06dcee 100644
--- a/src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts
+++ b/src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts
@@ -19,8 +19,6 @@ interface OpenersMemento {
[id: string]: RegisteredExternalOpener;
}
-/**
- */
export class ContributedExternalUriOpenersStore extends Disposable {
private static readonly STORAGE_ID = 'externalUriOpeners';
@@ -37,8 +35,8 @@ export class ContributedExternalUriOpenersStore extends Disposable {
this._memento = new Memento(ContributedExternalUriOpenersStore.STORAGE_ID, storageService);
this._mementoObject = this._memento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
- for (const id of Object.keys(this._mementoObject || {})) {
- this.add(id, this._mementoObject[id].extensionId, { isCurrentlyRegistered: false });
+ for (const [id, value] of Object.entries(this._mementoObject || {})) {
+ this.add(id, value.extensionId, { isCurrentlyRegistered: false });
}
this.invalidateOpenersOnExtensionsChanged();
diff --git a/src/vs/workbench/contrib/logs/common/logs.contribution.ts b/src/vs/workbench/contrib/logs/common/logs.contribution.ts
index 20eabfbdff4..aef0c3f87a1 100644
--- a/src/vs/workbench/contrib/logs/common/logs.contribution.ts
+++ b/src/vs/workbench/contrib/logs/common/logs.contribution.ts
@@ -15,7 +15,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IFileService, whenProviderRegistered } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { IOutputChannelRegistry, Extensions as OutputExt } from 'vs/workbench/services/output/common/output';
-import { Disposable } from 'vs/base/common/lifecycle';
+import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
@@ -24,8 +24,9 @@ import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleane
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
import { supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { IProductService } from 'vs/platform/product/common/productService';
-import { timeout } from 'vs/base/common/async';
-import { getErrorMessage } from 'vs/base/common/errors';
+import { createCancelablePromise, timeout } from 'vs/base/common/async';
+import { canceled, getErrorMessage, isPromiseCanceledError } from 'vs/base/common/errors';
+import { CancellationToken } from 'vs/base/common/cancellation';
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
workbenchActionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(SetLogLevelAction), 'Developer: Set Log Level...', CATEGORIES.Developer.value);
@@ -99,24 +100,31 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution {
await whenProviderRegistered(file, this.fileService);
const outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
try {
- await this.whenFileExists(file, 1);
+ const promise = createCancelablePromise(token => this.whenFileExists(file, 1, token));
+ this._register(toDisposable(() => promise.cancel()));
+ await promise;
outputChannelRegistry.registerChannel({ id, label, file, log: true });
} catch (error) {
- this.logService.error('Error while registering log channel', file.toString(), getErrorMessage(error));
+ if (!isPromiseCanceledError(error)) {
+ this.logService.error('Error while registering log channel', file.toString(), getErrorMessage(error));
+ }
}
}
- private async whenFileExists(file: URI, trial: number): Promise<void> {
+ private async whenFileExists(file: URI, trial: number, token: CancellationToken): Promise<void> {
const exists = await this.fileService.exists(file);
if (exists) {
return;
}
+ if (token.isCancellationRequested) {
+ throw canceled();
+ }
if (trial > 10) {
throw new Error(`Timed out while waiting for file to be created`);
}
this.logService.debug(`[Registering Log Channel] File does not exist. Waiting for 1s to retry.`, file.toString());
- await timeout(1000);
- await this.whenFileExists(file, trial + 1);
+ await timeout(1000, token);
+ await this.whenFileExists(file, trial + 1, token);
}
}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted.ts b/src/vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted.ts
index e13987153f8..18965b389d0 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted.ts
@@ -16,7 +16,7 @@ import { CATEGORIES } from 'vs/workbench/common/actions';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { Memento } from 'vs/workbench/common/memento';
import { HAS_OPENED_NOTEBOOK } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
-import { OpenGettingStarted } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
@@ -45,7 +45,7 @@ export class NotebookGettingStarted extends Disposable implements IWorkbenchCont
hasOpenedNotebook.set(true);
}
- const needToShowGettingStarted = _configurationService.getValue(OpenGettingStarted) && !storedValue[hasShownGettingStartedKey];
+ const needToShowGettingStarted = _configurationService.getValue(NotebookSetting.openGettingStarted) && !storedValue[hasShownGettingStartedKey];
if (!storedValue[hasOpenedNotebookKey] || needToShowGettingStarted) {
const onDidOpenNotebook = () => {
hasOpenedNotebook.set(true);
@@ -83,7 +83,7 @@ registerAction2(class NotebookClearNotebookLayoutAction extends Action2 {
id: 'workbench.notebook.layout.gettingStarted',
title: localize('workbench.notebook.layout.gettingStarted.label', "Reset notebook getting started"),
f1: true,
- precondition: ContextKeyExpr.equals(`config.${OpenGettingStarted}`, true),
+ precondition: ContextKeyExpr.equals(`config.${NotebookSetting.openGettingStarted}`, true),
category: CATEGORIES.Developer,
});
}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts
index c764085038f..fe1c2706c22 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts
@@ -8,7 +8,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { INotebookActionContext, NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
-import { CellToolbarLocation } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const TOGGLE_CELL_TOOLBAR_POSITION = 'notebook.toggleCellToolbarPosition';
@@ -33,9 +33,9 @@ export class ToggleCellToolbarPositionAction extends Action2 {
// from toolbar
const viewType = editor.textModel.viewType;
const configurationService = accessor.get(IConfigurationService);
- const toolbarPosition = configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocation);
+ const toolbarPosition = configurationService.getValue<string | { [key: string]: string }>(NotebookSetting.cellToolbarLocation);
const newConfig = this.togglePosition(viewType, toolbarPosition);
- await configurationService.updateValue(CellToolbarLocation, newConfig);
+ await configurationService.updateValue(NotebookSetting.cellToolbarLocation, newConfig);
}
}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts b/src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts
index 090e1383270..350e3c7e7d1 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts
@@ -9,7 +9,7 @@ import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { localize } from 'vs/nls';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { CellToolbarLocation, CompactView, ConsolidatedRunButton, FocusIndicator, GlobalToolbar, InsertToolbarLocation, ShowCellStatusBar, UndoRedoPerCell } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
@@ -22,34 +22,34 @@ export enum NotebookProfileType {
const profiles = {
[NotebookProfileType.default]: {
- [FocusIndicator]: 'gutter',
- [InsertToolbarLocation]: 'both',
- [GlobalToolbar]: true,
- [CellToolbarLocation]: { default: 'right' },
- [CompactView]: true,
- [ShowCellStatusBar]: 'visible',
- [ConsolidatedRunButton]: true,
- [UndoRedoPerCell]: false
+ [NotebookSetting.focusIndicator]: 'gutter',
+ [NotebookSetting.insertToolbarLocation]: 'both',
+ [NotebookSetting.globalToolbar]: true,
+ [NotebookSetting.cellToolbarLocation]: { default: 'right' },
+ [NotebookSetting.compactView]: true,
+ [NotebookSetting.showCellStatusBar]: 'visible',
+ [NotebookSetting.consolidatedRunButton]: true,
+ [NotebookSetting.undoRedoPerCell]: false
},
[NotebookProfileType.jupyter]: {
- [FocusIndicator]: 'gutter',
- [InsertToolbarLocation]: 'notebookToolbar',
- [GlobalToolbar]: true,
- [CellToolbarLocation]: { default: 'left' },
- [CompactView]: true,
- [ShowCellStatusBar]: 'visible',
- [ConsolidatedRunButton]: false,
- [UndoRedoPerCell]: true
+ [NotebookSetting.focusIndicator]: 'gutter',
+ [NotebookSetting.insertToolbarLocation]: 'notebookToolbar',
+ [NotebookSetting.globalToolbar]: true,
+ [NotebookSetting.cellToolbarLocation]: { default: 'left' },
+ [NotebookSetting.compactView]: true,
+ [NotebookSetting.showCellStatusBar]: 'visible',
+ [NotebookSetting.consolidatedRunButton]: false,
+ [NotebookSetting.undoRedoPerCell]: true
},
[NotebookProfileType.colab]: {
- [FocusIndicator]: 'border',
- [InsertToolbarLocation]: 'betweenCells',
- [GlobalToolbar]: false,
- [CellToolbarLocation]: { default: 'right' },
- [CompactView]: false,
- [ShowCellStatusBar]: 'hidden',
- [ConsolidatedRunButton]: true,
- [UndoRedoPerCell]: false
+ [NotebookSetting.focusIndicator]: 'border',
+ [NotebookSetting.insertToolbarLocation]: 'betweenCells',
+ [NotebookSetting.globalToolbar]: false,
+ [NotebookSetting.cellToolbarLocation]: { default: 'right' },
+ [NotebookSetting.compactView]: false,
+ [NotebookSetting.showCellStatusBar]: 'hidden',
+ [NotebookSetting.consolidatedRunButton]: true,
+ [NotebookSetting.undoRedoPerCell]: false
}
};
@@ -101,13 +101,13 @@ export class NotebookProfileContribution extends Disposable {
return;
} else {
// check if settings are already modified
- const focusIndicator = configService.getValue(FocusIndicator);
- const insertToolbarPosition = configService.getValue(InsertToolbarLocation);
- const globalToolbar = configService.getValue(GlobalToolbar);
- // const cellToolbarLocation = configService.getValue(CellToolbarLocation);
- const compactView = configService.getValue(CompactView);
- const showCellStatusBar = configService.getValue(ShowCellStatusBar);
- const consolidatedRunButton = configService.getValue(ConsolidatedRunButton);
+ const focusIndicator = configService.getValue(NotebookSetting.focusIndicator);
+ const insertToolbarPosition = configService.getValue(NotebookSetting.insertToolbarLocation);
+ const globalToolbar = configService.getValue(NotebookSetting.globalToolbar);
+ // const cellToolbarLocation = configService.getValue(NotebookSetting.cellToolbarLocation);
+ const compactView = configService.getValue(NotebookSetting.compactView);
+ const showCellStatusBar = configService.getValue(NotebookSetting.showCellStatusBar);
+ const consolidatedRunButton = configService.getValue(NotebookSetting.consolidatedRunButton);
if (focusIndicator === 'border'
&& insertToolbarPosition === 'both'
&& globalToolbar === false
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
index 83cdd5c305d..a57d2d97203 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts
@@ -17,7 +17,7 @@ import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cel
import { cellExecutionArgs, CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, executeNotebookCondition, getContextFromActiveEditor, getContextFromUri, INotebookActionContext, INotebookCellActionContext, INotebookCellToolbarActionContext, INotebookCommandContext, NotebookAction, NotebookCellAction, NotebookMultiCellAction, NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT, parseMultiCellExecutionArgs } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_MISSING_KERNEL_EXTENSION } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
-import { CellKind, ConsolidatedRunButton, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, NotebookSetting, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -207,7 +207,7 @@ registerAction2(class ExecuteAboveCells extends NotebookMultiCellAction {
id: MenuId.NotebookCellExecute,
when: ContextKeyExpr.and(
executeCondition,
- ContextKeyExpr.equals(`config.${ConsolidatedRunButton}`, true))
+ ContextKeyExpr.equals(`config.${NotebookSetting.consolidatedRunButton}`, true))
},
{
id: MenuId.NotebookCellTitle,
@@ -215,7 +215,7 @@ registerAction2(class ExecuteAboveCells extends NotebookMultiCellAction {
group: CELL_TITLE_CELL_GROUP_ID,
when: ContextKeyExpr.and(
executeCondition,
- ContextKeyExpr.equals(`config.${ConsolidatedRunButton}`, false))
+ ContextKeyExpr.equals(`config.${NotebookSetting.consolidatedRunButton}`, false))
}
],
icon: icons.executeAboveIcon
@@ -253,7 +253,7 @@ registerAction2(class ExecuteCellAndBelow extends NotebookMultiCellAction {
id: MenuId.NotebookCellExecute,
when: ContextKeyExpr.and(
executeCondition,
- ContextKeyExpr.equals(`config.${ConsolidatedRunButton}`, true))
+ ContextKeyExpr.equals(`config.${NotebookSetting.consolidatedRunButton}`, true))
},
{
id: MenuId.NotebookCellTitle,
@@ -261,7 +261,7 @@ registerAction2(class ExecuteCellAndBelow extends NotebookMultiCellAction {
group: CELL_TITLE_CELL_GROUP_ID,
when: ContextKeyExpr.and(
executeCondition,
- ContextKeyExpr.equals(`config.${ConsolidatedRunButton}`, false))
+ ContextKeyExpr.equals(`config.${NotebookSetting.consolidatedRunButton}`, false))
}
],
icon: icons.executeBelowIcon
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts
index c15d0bfb871..c88434cf848 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts
@@ -16,7 +16,7 @@ import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cel
import { INotebookActionContext, NotebookAction } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_EDITOR_EDITABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
-import { CellKind, GlobalToolbarShowLabel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove';
const INSERT_CODE_CELL_BELOW_COMMAND_ID = 'notebook.cell.insertCodeCellBelow';
@@ -323,7 +323,7 @@ MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'betweenCells'),
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'hidden'),
- ContextKeyExpr.notEquals(`config.${GlobalToolbarShowLabel}`, false)
+ ContextKeyExpr.notEquals(`config.${NotebookSetting.globalToolbarShowLabel}`, false)
)
});
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
index c3f39c3cb4e..9e16c29d0e4 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
@@ -13,7 +13,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
-import { OpenGettingStarted } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
@@ -23,7 +23,7 @@ registerAction2(class NotebookConfigureLayoutAction extends Action2 {
id: 'workbench.notebook.layout.select',
title: localize('workbench.notebook.layout.select.label', "Select between Notebook Layouts"),
f1: true,
- precondition: ContextKeyExpr.equals(`config.${OpenGettingStarted}`, true),
+ precondition: ContextKeyExpr.equals(`config.${NotebookSetting.openGettingStarted}`, true),
category: NOTEBOOK_ACTIONS_CATEGORY,
menu: [
{
@@ -32,7 +32,7 @@ registerAction2(class NotebookConfigureLayoutAction extends Action2 {
when: ContextKeyExpr.and(
NOTEBOOK_IS_ACTIVE_EDITOR,
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true),
- ContextKeyExpr.equals(`config.${OpenGettingStarted}`, true)
+ ContextKeyExpr.equals(`config.${NotebookSetting.openGettingStarted}`, true)
),
order: 0
},
@@ -41,7 +41,7 @@ registerAction2(class NotebookConfigureLayoutAction extends Action2 {
group: 'notebookLayout',
when: ContextKeyExpr.and(
ContextKeyExpr.equals('config.notebook.globalToolbar', true),
- ContextKeyExpr.equals(`config.${OpenGettingStarted}`, true)
+ ContextKeyExpr.equals(`config.${NotebookSetting.openGettingStarted}`, true)
),
order: 0
}
diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts
index 259fda6abfc..14c6dc4b5dd 100644
--- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts
+++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts
@@ -8,13 +8,13 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { DiffElementViewModelBase, getFormatedMetadataJSON, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
+import { DiffElementViewModelBase, getFormatedMetadataJSON, getFormatedOutputJSON, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_INPUT, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
-import { CellEditType, CellUri, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellEditType, CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
@@ -99,6 +99,7 @@ export const fixedDiffEditorOptions: IDiffEditorConstructionOptions = {
class PropertyHeader extends Disposable {
protected _foldingIndicator!: HTMLElement;
protected _statusSpan!: HTMLElement;
+ protected _description!: HTMLElement;
protected _toolbar!: ToolBar;
protected _menu!: IMenu;
protected _propertyExpanded?: IContextKey<boolean>;
@@ -109,7 +110,7 @@ class PropertyHeader extends Disposable {
readonly notebookEditor: INotebookTextDiffEditor,
readonly accessor: {
updateInfoRendering: (renderOutput: boolean) => void;
- checkIfModified: (cell: DiffElementViewModelBase) => boolean;
+ checkIfModified: (cell: DiffElementViewModelBase) => false | { reason: string | undefined };
getFoldingState: (cell: DiffElementViewModelBase) => PropertyFoldingState;
updateFoldingState: (cell: DiffElementViewModelBase, newState: PropertyFoldingState) => void;
unChangedLabel: string;
@@ -132,14 +133,20 @@ class PropertyHeader extends Disposable {
this._foldingIndicator.classList.add(this.accessor.prefix);
this._updateFoldingIcon();
const metadataStatus = DOM.append(this.propertyHeaderContainer, DOM.$('div.property-status'));
+
this._statusSpan = DOM.append(metadataStatus, DOM.$('span'));
+ this._description = DOM.append(metadataStatus, DOM.$('span.property-description'));
if (metadataChanged) {
this._statusSpan.textContent = this.accessor.changedLabel;
this._statusSpan.style.fontWeight = 'bold';
+ if (metadataChanged.reason) {
+ this._description.textContent = metadataChanged.reason;
+ }
this.propertyHeaderContainer.classList.add('modified');
} else {
this._statusSpan.textContent = this.accessor.unChangedLabel;
+ this._description.textContent = '';
this.propertyHeaderContainer.classList.remove('modified');
}
@@ -162,7 +169,7 @@ class PropertyHeader extends Disposable {
const scopedContextKeyService = this.contextKeyService.createScoped(cellToolbarContainer);
this._register(scopedContextKeyService);
const propertyChanged = NOTEBOOK_DIFF_CELL_PROPERTY.bindTo(scopedContextKeyService);
- propertyChanged.set(metadataChanged);
+ propertyChanged.set(!!metadataChanged);
this._propertyExpanded = NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED.bindTo(scopedContextKeyService);
this._menu = this.menuService.createMenu(this.accessor.menuId, scopedContextKeyService);
@@ -224,6 +231,9 @@ class PropertyHeader extends Disposable {
if (metadataChanged) {
this._statusSpan.textContent = this.accessor.changedLabel;
this._statusSpan.style.fontWeight = 'bold';
+ if (metadataChanged.reason) {
+ this._description.textContent = metadataChanged.reason;
+ }
this.propertyHeaderContainer.classList.add('modified');
const actions: IAction[] = [];
createAndFillInActionBarActions(this._menu, undefined, actions);
@@ -231,6 +241,7 @@ class PropertyHeader extends Disposable {
} else {
this._statusSpan.textContent = this.accessor.unChangedLabel;
this._statusSpan.style.fontWeight = 'normal';
+ this._description.textContent = '';
this.propertyHeaderContainer.classList.remove('modified');
this._toolbar.setActions([]);
}
@@ -612,16 +623,12 @@ abstract class AbstractElementRenderer extends Disposable {
}
}
- private _getFormatedOutputJSON(outputs: IOutputDto[]) {
- return JSON.stringify(outputs.map(op => ({ outputs: op.outputs })), undefined, '\t');
- }
-
private _buildOutputEditor() {
this._outputEditorDisposeStore.clear();
if ((this.cell.type === 'modified' || this.cell.type === 'unchanged') && !this.notebookEditor.textModel!.transientOptions.transientOutputs) {
- const originalOutputsSource = this._getFormatedOutputJSON(this.cell.original?.outputs || []);
- const modifiedOutputsSource = this._getFormatedOutputJSON(this.cell.modified?.outputs || []);
+ const originalOutputsSource = getFormatedOutputJSON(this.cell.original?.outputs || []);
+ const modifiedOutputsSource = getFormatedOutputJSON(this.cell.modified?.outputs || []);
if (originalOutputsSource !== modifiedOutputsSource) {
const mode = this.modeService.create('json');
const originalModel = this.modelService.createModel(originalOutputsSource, mode, undefined, true);
@@ -664,7 +671,7 @@ abstract class AbstractElementRenderer extends Disposable {
}));
this._outputEditorDisposeStore.add(this.cell.modified!.textModel.onDidChangeOutputs(() => {
- const modifiedOutputsSource = this._getFormatedOutputJSON(this.cell.modified?.outputs || []);
+ const modifiedOutputsSource = getFormatedOutputJSON(this.cell.modified?.outputs || []);
modifiedModel.setValue(modifiedOutputsSource);
this._outputHeader.refresh();
}));
@@ -684,7 +691,7 @@ abstract class AbstractElementRenderer extends Disposable {
this._outputEditorDisposeStore.add(this._outputEditor);
const mode = this.modeService.create('json');
- const originaloutputSource = this._getFormatedOutputJSON(
+ const originaloutputSource = getFormatedOutputJSON(
this.notebookEditor.textModel!.transientOptions.transientOutputs
? []
: this.cell.type === 'insert'
diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts
index 421d414e96f..fd60f3310ed 100644
--- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts
+++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementViewModel.ts
@@ -12,7 +12,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
import { hash } from 'vs/base/common/hash';
import { format } from 'vs/base/common/jsonFormatter';
import { applyEdits } from 'vs/base/common/jsonEdit';
-import { ICellOutput, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { ICellOutput, IOutputDto, IOutputItemDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel';
import { URI } from 'vs/base/common/uri';
import { NotebookDiffEditorEventDispatcher, NotebookDiffViewEventType } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher';
@@ -274,8 +274,8 @@ export abstract class DiffElementViewModelBase extends Disposable {
this.editorEventDispatcher.emit([{ type: NotebookDiffViewEventType.CellLayoutChanged, source: this._layoutInfo }]);
}
- abstract checkIfOutputsModified(): boolean;
- abstract checkMetadataIfModified(): boolean;
+ abstract checkIfOutputsModified(): false | { reason: string | undefined; };
+ abstract checkMetadataIfModified(): false | { reason: string | undefined; };
abstract isOutputEmpty(): boolean;
abstract getRichOutputTotalHeight(): number;
abstract getCellByUri(cellUri: URI): IGenericCellViewModel;
@@ -375,11 +375,28 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase {
}
checkIfOutputsModified() {
- return !this.mainDocumentTextModel.transientOptions.transientOutputs && !outputsEqual(this.original?.outputs ?? [], this.modified?.outputs ?? []);
+ if (this.mainDocumentTextModel.transientOptions.transientOutputs) {
+ return false;
+ }
+
+ const ret = outputsEqual(this.original?.outputs ?? [], this.modified?.outputs ?? []);
+
+ if (ret === OutputComparison.Unchanged) {
+ return false;
+ }
+
+ return {
+ reason: ret === OutputComparison.Metadata ? 'Output metadata is changed' : undefined
+ };
}
- checkMetadataIfModified(): boolean {
- return hash(getFormatedMetadataJSON(this.mainDocumentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.mainDocumentTextModel, this.modified?.metadata ?? {}, this.modified?.language));
+ checkMetadataIfModified() {
+ const modified = hash(getFormatedMetadataJSON(this.mainDocumentTextModel, this.original?.metadata || {}, this.original?.language)) !== hash(getFormatedMetadataJSON(this.mainDocumentTextModel, this.modified?.metadata ?? {}, this.modified?.language));
+ if (modified) {
+ return { reason: undefined };
+ } else {
+ return false;
+ }
}
updateOutputHeight(diffSide: DiffSide, index: number, height: number) {
@@ -489,11 +506,11 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase {
}
- checkIfOutputsModified(): boolean {
+ checkIfOutputsModified(): false | { reason: string | undefined } {
return false;
}
- checkMetadataIfModified(): boolean {
+ checkMetadataIfModified(): false | { reason: string | undefined } {
return false;
}
@@ -536,9 +553,15 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase {
}
}
+const enum OutputComparison {
+ Unchanged = 0,
+ Metadata = 1,
+ Other = 2
+}
+
function outputsEqual(original: ICellOutput[], modified: ICellOutput[]) {
if (original.length !== modified.length) {
- return false;
+ return OutputComparison.Other;
}
const len = original.length;
@@ -547,11 +570,11 @@ function outputsEqual(original: ICellOutput[], modified: ICellOutput[]) {
const b = modified[i];
if (hash(a.metadata) !== hash(b.metadata)) {
- return false;
+ return OutputComparison.Metadata;
}
if (a.outputs.length !== b.outputs.length) {
- return false;
+ return OutputComparison.Other;
}
for (let j = 0; j < a.outputs.length; j++) {
@@ -559,22 +582,22 @@ function outputsEqual(original: ICellOutput[], modified: ICellOutput[]) {
const bOutputItem = b.outputs[j];
if (aOutputItem.mime !== bOutputItem.mime) {
- return false;
+ return OutputComparison.Other;
}
if (aOutputItem.data.buffer.length !== bOutputItem.data.buffer.length) {
- return false;
+ return OutputComparison.Other;
}
for (let k = 0; k < aOutputItem.data.buffer.length; k++) {
if (aOutputItem.data.buffer[k] !== bOutputItem.data.buffer[k]) {
- return false;
+ return OutputComparison.Other;
}
}
}
}
- return true;
+ return OutputComparison.Unchanged;
}
export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, metadata: NotebookCellMetadata, language?: string) {
@@ -604,3 +627,38 @@ export function getFormatedMetadataJSON(documentTextModel: NotebookTextModel, me
return metadataSource;
}
+
+export function getStreamOutputData(outputs: IOutputItemDto[]) {
+ if (!outputs.length) {
+ return null;
+ }
+
+ const first = outputs[0];
+ const mime = first.mime;
+ const sameStream = !outputs.find(op => op.mime !== mime);
+
+ if (sameStream) {
+ return outputs.map(opit => opit.data.toString()).join('');
+ } else {
+ return null;
+ }
+}
+
+export function getFormatedOutputJSON(outputs: IOutputDto[]) {
+ if (outputs.length === 1) {
+ const streamOutputData = getStreamOutputData(outputs[0].outputs);
+ if (streamOutputData) {
+ return streamOutputData;
+ }
+ }
+
+ return JSON.stringify(outputs.map(output => {
+ return ({
+ metadata: output.metadata,
+ outputItems: output.outputs.map(opit => ({
+ mimeType: opit.mime,
+ data: opit.data.toString()
+ }))
+ });
+ }), undefined, '\t');
+}
diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css
index 45d7774cb88..5dc1777ddb0 100644
--- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css
+++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiff.css
@@ -129,10 +129,15 @@
.notebook-text-diff-editor .cell-diff-editor-container .output-header-container .property-status span,
.notebook-text-diff-editor .cell-diff-editor-container .metadata-header-container .property-status span {
- margin: 0 8px;
+ margin: 0 0 0 8px;
line-height: 21px;
}
+.notebook-text-diff-editor .cell-diff-editor-container .output-header-container .property-status span.property-description,
+.notebook-text-diff-editor .cell-diff-editor-container .metadata-header-container .property-status span.property-description {
+ font-style: italic;
+}
+
.notebook-text-diff-editor {
overflow: hidden;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
index f380458fb38..399f893bed9 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
@@ -30,7 +30,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd
import { isCompositeNotebookEditorInput, NotebookEditorInput, NotebookEditorInputOptions } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl';
-import { CellKind, CellToolbarLocation, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBar, CompactView, FocusIndicator, InsertToolbarLocation, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, NotebookCellEditorOptionsCustomizations, ConsolidatedRunButton, TextOutputLineLimit, GlobalToolbarShowLabel, IOutputItemDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, CellUri, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookWorkingCopyTypeIdentifier, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
@@ -45,7 +45,7 @@ import { NotebookEditorWidgetService } from 'vs/workbench/contrib/notebook/brows
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { Event } from 'vs/base/common/event';
-import { getFormatedMetadataJSON } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
+import { getFormatedMetadataJSON, getStreamOutputData } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { NotebookModelResolverServiceImpl } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl';
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { NotebookKernelService } from 'vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl';
@@ -208,7 +208,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri
) {
super();
- const undoRedoPerCell = configurationService.getValue<boolean>(UndoRedoPerCell);
+ const undoRedoPerCell = configurationService.getValue<boolean>(NotebookSetting.undoRedoPerCell);
this._register(undoRedoService.registerUriComparisonKeyComputer(CellUri.scheme, {
getComparisonKey: (uri: URI): string => {
@@ -372,22 +372,6 @@ class CellInfoContentProvider {
return result;
}
- private _getStreamOutputData(outputs: IOutputItemDto[]) {
- if (!outputs.length) {
- return null;
- }
-
- const first = outputs[0];
- const mime = first.mime;
- const sameStream = !outputs.find(op => op.mime !== mime);
-
- if (sameStream) {
- return outputs.map(opit => opit.data.toString()).join('');
- } else {
- return null;
- }
- }
-
async provideOutputTextContent(resource: URI): Promise<ITextModel | null> {
const existing = this._modelService.getModel(resource);
if (existing) {
@@ -408,7 +392,7 @@ class CellInfoContentProvider {
if (cell.handle === data.handle) {
if (cell.outputs.length === 1) {
// single output
- const streamOutputData = this._getStreamOutputData(cell.outputs[0].outputs);
+ const streamOutputData = getStreamOutputData(cell.outputs[0].outputs);
if (streamOutputData) {
result = this._modelService.createModel(
streamOutputData,
@@ -656,7 +640,7 @@ configurationRegistry.registerConfiguration({
title: nls.localize('notebookConfigurationTitle', "Notebook"),
type: 'object',
properties: {
- [DisplayOrderKey]: {
+ [NotebookSetting.displayOrder]: {
description: nls.localize('notebook.displayOrder.description', "Priority list for output mime types"),
type: ['array'],
items: {
@@ -664,7 +648,7 @@ configurationRegistry.registerConfiguration({
},
default: []
},
- [CellToolbarLocation]: {
+ [NotebookSetting.cellToolbarLocation]: {
description: nls.localize('notebook.cellToolbarLocation.description', "Where the cell toolbar should be shown, or whether it should be hidden."),
type: 'object',
additionalProperties: {
@@ -677,7 +661,7 @@ configurationRegistry.registerConfiguration({
},
tags: ['notebookLayout']
},
- [ShowCellStatusBar]: {
+ [NotebookSetting.showCellStatusBar]: {
description: nls.localize('notebook.showCellStatusbar.description', "Whether the cell status bar should be shown."),
type: 'string',
enum: ['hidden', 'visible', 'visibleAfterExecute'],
@@ -688,39 +672,39 @@ configurationRegistry.registerConfiguration({
default: 'visible',
tags: ['notebookLayout']
},
- [NotebookTextDiffEditorPreview]: {
+ [NotebookSetting.textDiffEditorPreview]: {
description: nls.localize('notebook.diff.enablePreview.description', "Whether to use the enhanced text diff editor for notebook."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [CellToolbarVisibility]: {
+ [NotebookSetting.cellToolbarVisibility]: {
markdownDescription: nls.localize('notebook.cellToolbarVisibility.description', "Whether the cell toolbar should appear on hover or click."),
type: 'string',
enum: ['hover', 'click'],
default: 'click',
tags: ['notebookLayout']
},
- [UndoRedoPerCell]: {
+ [NotebookSetting.undoRedoPerCell]: {
description: nls.localize('notebook.undoRedoPerCell.description', "Whether to use separate undo/redo stack for each cell."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [CompactView]: {
+ [NotebookSetting.compactView]: {
description: nls.localize('notebook.compactView.description', "Control whether the notebook editor should be rendered in a compact form. For example, when turned on, it will decrease the left margin width."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [FocusIndicator]: {
+ [NotebookSetting.focusIndicator]: {
description: nls.localize('notebook.focusIndicator.description', "Controls where the focus indicator is rendered, either along the cell borders or on the left gutter"),
type: 'string',
enum: ['border', 'gutter'],
default: 'gutter',
tags: ['notebookLayout']
},
- [InsertToolbarLocation]: {
+ [NotebookSetting.insertToolbarLocation]: {
description: nls.localize('notebook.insertToolbarPosition.description', "Control where the insert cell actions should appear."),
type: 'string',
enum: ['betweenCells', 'notebookToolbar', 'both', 'hidden'],
@@ -733,19 +717,19 @@ configurationRegistry.registerConfiguration({
default: 'both',
tags: ['notebookLayout']
},
- [GlobalToolbar]: {
+ [NotebookSetting.globalToolbar]: {
description: nls.localize('notebook.globalToolbar.description', "Control whether to render a global toolbar inside the notebook editor."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [ConsolidatedOutputButton]: {
+ [NotebookSetting.consolidatedOutputButton]: {
description: nls.localize('notebook.consolidatedOutputButton.description', "Control whether outputs action should be rendered in the output toolbar."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [ShowFoldingControls]: {
+ [NotebookSetting.showFoldingControls]: {
description: nls.localize('notebook.showFoldingControls.description', "Controls when the Markdown header folding arrow is shown."),
type: 'string',
enum: ['always', 'mouseover'],
@@ -756,30 +740,36 @@ configurationRegistry.registerConfiguration({
default: 'mouseover',
tags: ['notebookLayout']
},
- [DragAndDropEnabled]: {
+ [NotebookSetting.dragAndDropEnabled]: {
description: nls.localize('notebook.dragAndDrop.description', "Control whether the notebook editor should allow moving cells through drag and drop."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [ConsolidatedRunButton]: {
+ [NotebookSetting.consolidatedRunButton]: {
description: nls.localize('notebook.consolidatedRunButton.description', "Control whether extra actions are shown in a dropdown next to the run button."),
type: 'boolean',
default: false,
tags: ['notebookLayout']
},
- [GlobalToolbarShowLabel]: {
+ [NotebookSetting.globalToolbarShowLabel]: {
description: nls.localize('notebook.globalToolbarShowLabel', "Control whether the actions on the notebook toolbar should render label or not."),
type: 'boolean',
default: true,
tags: ['notebookLayout']
},
- [TextOutputLineLimit]: {
+ [NotebookSetting.textOutputLineLimit]: {
description: nls.localize('notebook.textOutputLineLimit', "Control how many lines of text in a text output is rendered."),
type: 'number',
default: 30,
tags: ['notebookLayout']
},
- [NotebookCellEditorOptionsCustomizations]: editorOptionsCustomizationSchema
+ [NotebookSetting.markupFontSize]: {
+ markdownDescription: nls.localize('notebook.markup.fontSize', "Controls the font size of rendered markup in notebooks. When set to `0`, 120% of `#editor.fontSize#` is used."),
+ type: 'number',
+ default: 0,
+ tags: ['notebookLayout']
+ },
+ [NotebookSetting.cellEditorOptionsCustomizations]: editorOptionsCustomizationSchema
}
});
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl.ts
index 56cf615dd92..67d223ef756 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookCellStatusBarServiceImpl.ts
@@ -13,17 +13,15 @@ import { INotebookCellStatusBarItemList, INotebookCellStatusBarItemProvider } fr
export class NotebookCellStatusBarService extends Disposable implements INotebookCellStatusBarService {
- private _onDidChangeProviders = this._register(new Emitter<void>());
+ readonly _serviceBrand: undefined;
+
+ private readonly _onDidChangeProviders = this._register(new Emitter<void>());
readonly onDidChangeProviders: Event<void> = this._onDidChangeProviders.event;
- private _onDidChangeItems = this._register(new Emitter<void>());
+ private readonly _onDidChangeItems = this._register(new Emitter<void>());
readonly onDidChangeItems: Event<void> = this._onDidChangeItems.event;
- private _providers: INotebookCellStatusBarItemProvider[] = [];
-
- constructor() {
- super();
- }
+ private readonly _providers: INotebookCellStatusBarItemProvider[] = [];
registerCellStatusBarItemProvider(provider: INotebookCellStatusBarItemProvider): IDisposable {
this._providers.push(provider);
@@ -52,6 +50,4 @@ export class NotebookCellStatusBarService extends Disposable implements INoteboo
}
}));
}
-
- readonly _serviceBrand: undefined;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
index de441e639c2..33c5df88faf 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
@@ -412,7 +412,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._updateForNotebookConfiguration();
}
- if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.insertToolbarAlignment) {
+ if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment) {
this._styleElement?.remove();
this._createLayoutStyles();
this._webview?.updateOptions(this.notebookOptions.computeWebviewOptions());
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
index c1fd60d25a2..6f309a54847 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
@@ -30,7 +30,7 @@ import { INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/no
import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
-import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookContributionData, INotebookExclusiveDocumentFilter, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, MimeTypeDisplayOrder, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookData, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, NOTEBOOK_DISPLAY_ORDER, RENDERER_EQUIVALENT_EXTENSIONS, RENDERER_NOT_AVAILABLE, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, NotebookSetting, INotebookContributionData, INotebookExclusiveDocumentFilter, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, MimeTypeDisplayOrder, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookData, NotebookEditorPriority, NotebookRendererMatch, NOTEBOOK_DISPLAY_ORDER, RENDERER_EQUIVALENT_EXTENSIONS, RENDERER_NOT_AVAILABLE, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
import { updateEditorTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions';
@@ -161,7 +161,7 @@ export class NotebookProviderInfoStore extends Disposable {
priority: notebookProviderInfo.exclusive ? RegisteredEditorPriority.exclusive : notebookProviderInfo.priority,
};
const notebookEditorOptions = {
- canHandleDiff: () => !!this._configurationService.getValue(NotebookTextDiffEditorPreview) && !this._accessibilityService.isScreenReaderOptimized(),
+ canHandleDiff: () => !!this._configurationService.getValue(NotebookSetting.textDiffEditorPreview) && !this._accessibilityService.isScreenReaderOptimized(),
canSupportResource: (resource: URI) => resource.scheme === Schemas.untitled || resource.scheme === Schemas.vscodeNotebookCell || this._fileService.hasProvider(resource)
};
const notebookEditorInputFactory: EditorInputFactoryFunction = ({ resource, options }) => {
@@ -458,7 +458,7 @@ export class NotebookService extends Disposable implements INotebookService {
const updateOrder = () => {
this._displayOrder = new MimeTypeDisplayOrder(
- this._configurationService.getValue<string[]>(DisplayOrderKey) || [],
+ this._configurationService.getValue<string[]>(NotebookSetting.displayOrder) || [],
this._accessibilityService.isScreenReaderOptimized()
? ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER
: NOTEBOOK_DISPLAY_ORDER,
@@ -468,7 +468,7 @@ export class NotebookService extends Disposable implements INotebookService {
updateOrder();
this._register(this._configurationService.onDidChangeConfiguration(e => {
- if (e.affectedKeys.indexOf(DisplayOrderKey) >= 0) {
+ if (e.affectedKeys.indexOf(NotebookSetting.displayOrder) >= 0) {
updateOrder();
}
}));
@@ -626,7 +626,7 @@ export class NotebookService extends Disposable implements INotebookService {
}
saveMimeDisplayOrder(target: ConfigurationTarget) {
- this._configurationService.updateValue(DisplayOrderKey, this._displayOrder.toArray(), target);
+ this._configurationService.updateValue(NotebookSetting.displayOrder, this._displayOrder.toArray(), target);
}
getRenderers(): INotebookRendererInfo[] {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
index ea32085e655..57f448967a6 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
@@ -6,9 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Mimes } from 'vs/base/common/mime';
-import { dirname } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
-import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
@@ -17,10 +15,10 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
import { ICellOutputViewModel, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { INotebookDelegateForOutput, IOutputTransformContribution as IOutputRendererContribution } from 'vs/workbench/contrib/notebook/browser/view/notebookRenderingCommon';
import { OutputRendererRegistry } from 'vs/workbench/contrib/notebook/browser/view/output/rendererRegistry';
import { truncatedArrayOfString } from 'vs/workbench/contrib/notebook/browser/view/output/transforms/textHelper';
-import { IOutputItemDto, TextOutputLineLimit } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { INotebookDelegateForOutput, IOutputTransformContribution as IOutputRendererContribution } from 'vs/workbench/contrib/notebook/browser/view/notebookRenderingCommon';
+import { IOutputItemDto, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
class JavaScriptRendererContrib extends Disposable implements IOutputRendererContribution {
@@ -76,7 +74,7 @@ class StreamRendererContrib extends Disposable implements IOutputRendererContrib
const text = getStringValue(item);
const contentNode = DOM.$('span.output-stream');
- const lineLimit = this.configurationService.getValue<number>(TextOutputLineLimit) ?? 30;
+ const lineLimit = this.configurationService.getValue<number>(NotebookSetting.textOutputLineLimit) ?? 30;
truncatedArrayOfString(notebookUri, output.cellViewModel, Math.max(lineLimit, 6), contentNode, [text], disposables, linkDetector, this.openerService, this.themeService);
container.appendChild(contentNode);
@@ -180,7 +178,7 @@ class PlainTextRendererContrib extends Disposable implements IOutputRendererCont
const str = getStringValue(item);
const contentNode = DOM.$('.output-plaintext');
- const lineLimit = this.configurationService.getValue<number>(TextOutputLineLimit) ?? 30;
+ const lineLimit = this.configurationService.getValue<number>(NotebookSetting.textOutputLineLimit) ?? 30;
truncatedArrayOfString(notebookUri, output.cellViewModel, Math.max(lineLimit, 6), contentNode, [str], disposables, linkDetector, this.openerService, this.themeService);
container.appendChild(contentNode);
@@ -213,34 +211,6 @@ class HTMLRendererContrib extends Disposable implements IOutputRendererContribut
}
}
-class MdRendererContrib extends Disposable implements IOutputRendererContribution {
- getType() {
- return RenderOutputType.Mainframe;
- }
-
- getMimetypes() {
- return [Mimes.markdown, Mimes.latex];
- }
-
- constructor(
- public notebookEditor: INotebookDelegateForOutput,
- @IInstantiationService private readonly instantiationService: IInstantiationService,
- ) {
- super();
- }
-
- render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
- const disposable = new DisposableStore();
- const str = getStringValue(item);
- const mdOutput = document.createElement('div');
- const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) });
- mdOutput.appendChild(mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }, undefined, { gfm: true }).element);
- container.appendChild(mdOutput);
- disposable.add(mdRenderer);
- return { type: RenderOutputType.Mainframe, disposable };
- }
-}
-
class ImgRendererContrib extends Disposable implements IOutputRendererContribution {
getType() {
return RenderOutputType.Mainframe;
@@ -276,7 +246,6 @@ class ImgRendererContrib extends Disposable implements IOutputRendererContributi
OutputRendererRegistry.registerOutputTransform(JavaScriptRendererContrib);
OutputRendererRegistry.registerOutputTransform(HTMLRendererContrib);
-OutputRendererRegistry.registerOutputTransform(MdRendererContrib);
OutputRendererRegistry.registerOutputTransform(ImgRendererContrib);
OutputRendererRegistry.registerOutputTransform(PlainTextRendererContrib);
OutputRendererRegistry.registerOutputTransform(JSErrorRendererContrib);
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
index d7fc86b2e6c..c50030657da 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
@@ -51,14 +51,6 @@ export interface ICachedInset<K extends ICommonCellInfo> {
cachedCreation: ICreationRequestMessage;
}
-function html(strings: TemplateStringsArray, ...values: any[]): string {
- let str = '';
- strings.forEach((string, i) => {
- str += string + (values[i] || '');
- });
- return str;
-}
-
export interface INotebookWebviewMessage {
message: unknown;
}
@@ -89,6 +81,19 @@ export interface INotebookDelegateForWebview {
triggerScroll(event: IMouseWheelEvent): void;
}
+interface BacklayerWebviewOptions {
+ readonly outputNodePadding: number;
+ readonly outputNodeLeftPadding: number;
+ readonly previewNodePadding: number;
+ readonly markdownLeftMargin: number;
+ readonly leftMargin: number;
+ readonly rightMargin: number;
+ readonly runGutter: number;
+ readonly dragAndDropEnabled: boolean;
+ readonly fontSize: number;
+ readonly markupFontSize: number;
+}
+
export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
element: HTMLElement;
webview: IWebviewElement | undefined = undefined;
@@ -100,7 +105,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
private readonly _onMessage = this._register(new Emitter<INotebookWebviewMessage>());
private readonly _preloadsCache = new Set<string>();
public readonly onMessage: Event<INotebookWebviewMessage> = this._onMessage.event;
- private _initalized?: Promise<void>;
+ private _initialized?: Promise<void>;
private _disposed = false;
private _currentKernel?: INotebookKernel;
@@ -110,17 +115,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
public readonly notebookEditor: INotebookDelegateForWebview,
public readonly id: string,
public readonly documentUri: URI,
- private options: {
- outputNodePadding: number,
- outputNodeLeftPadding: number,
- previewNodePadding: number,
- markdownLeftMargin: number,
- leftMargin: number,
- rightMargin: number,
- runGutter: number,
- dragAndDropEnabled: boolean,
- fontSize: number
- },
+ private options: BacklayerWebviewOptions,
private readonly rendererMessaging: IScopedRendererMessaging | undefined,
@IWebviewService readonly webviewService: IWebviewService,
@IOpenerService readonly openerService: IOpenerService,
@@ -177,17 +172,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
}));
}
- updateOptions(options: {
- outputNodePadding: number,
- outputNodeLeftPadding: number,
- previewNodePadding: number,
- markdownLeftMargin: number,
- leftMargin: number,
- rightMargin: number,
- runGutter: number,
- dragAndDropEnabled: boolean,
- fontSize: number
- }) {
+ updateOptions(options: BacklayerWebviewOptions) {
this.options = options;
this._updateStyles();
this._updateOptions();
@@ -215,10 +200,11 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
'notebook-output-width': `calc(100% - ${this.options.leftMargin + this.options.rightMargin + this.options.runGutter}px)`,
'notebook-output-node-padding': `${this.options.outputNodePadding}px`,
'notebook-run-gutter': `${this.options.runGutter}px`,
- 'notebook-preivew-node-padding': `${this.options.previewNodePadding}px`,
+ 'notebook-preview-node-padding': `${this.options.previewNodePadding}px`,
'notebook-markdown-left-margin': `${this.options.markdownLeftMargin}px`,
'notebook-output-node-left-padding': `${this.options.outputNodeLeftPadding}px`,
'notebook-markdown-min-height': `${this.options.previewNodePadding * 2}px`,
+ 'notebook-markup-font-size': typeof this.options.markupFontSize === 'number' && this.options.markupFontSize > 0 ? `${this.options.markupFontSize}px` : `calc(${this.options.fontSize}px * 1.2)`,
'notebook-cell-output-font-size': `${this.options.fontSize}px`,
'notebook-cell-markup-empty-content': nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit."),
'notebook-cell-renderer-not-found-error': nls.localize({
@@ -238,7 +224,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
this.nonce);
const enableCsp = this.configurationService.getValue('notebook.experimental.enableCsp');
- return html`
+ return /* html */`
<html lang="en">
<head>
<meta charset="UTF-8">
@@ -279,15 +265,17 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
/* markdown */
#container > div.preview {
width: 100%;
- padding-right: var(--notebook-preivew-node-padding);
+ padding-right: var(--notebook-preview-node-padding);
padding-left: var(--notebook-markdown-left-margin);
- padding-top: var(--notebook-preivew-node-padding);
- padding-bottom: var(--notebook-preivew-node-padding);
+ padding-top: var(--notebook-preview-node-padding);
+ padding-bottom: var(--notebook-preview-node-padding);
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
white-space: initial;
+
+ font-size: var(--notebook-markup-font-size);
color: var(--theme-ui-foreground);
}
@@ -434,7 +422,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
let coreDependencies = '';
let resolveFunc: () => void;
- this._initalized = new Promise<void>((resolve, reject) => {
+ this._initialized = new Promise<void>((resolve) => {
resolveFunc = resolve;
});
@@ -483,7 +471,7 @@ var requirejs = (function() {
});
}
- await this._initalized;
+ await this._initialized;
}
private _initialize(content: string) {
@@ -835,7 +823,7 @@ var requirejs = (function() {
allowScripts: true,
localResourceRoots: this.localResourceRootsCache,
}, undefined);
- // console.log(this.localResourceRootsCache);
+
webview.html = content;
return webview;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts
index edc8222bd42..52430aabb78 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts
@@ -10,7 +10,7 @@ interface BaseToWebviewMessage {
readonly __vscode_notebook_message: true;
}
-export interface WebviewIntialized extends BaseToWebviewMessage {
+export interface WebviewInitialized extends BaseToWebviewMessage {
readonly type: 'initialized';
}
@@ -162,22 +162,22 @@ export interface IOutputRequestMetadata {
/**
* Additional attributes of a cell metadata.
*/
- readonly custom?: { [key: string]: unknown; };
+ readonly custom?: { readonly [key: string]: unknown; };
}
export interface IOutputRequestDto {
/**
* { mime_type: value }
*/
- readonly data: { [key: string]: unknown; };
+ readonly data: { readonly [key: string]: unknown; };
readonly metadata?: IOutputRequestMetadata;
readonly outputId: string;
}
export type ICreationContent =
- | { type: RenderOutputType.Html; htmlContent: string; }
- | { type: RenderOutputType.Extension; outputId: string; valueBytes: Uint8Array; metadata: unknown; mimeType: string; };
+ | { readonly type: RenderOutputType.Html; readonly htmlContent: string; }
+ | { readonly type: RenderOutputType.Extension; readonly outputId: string; readonly valueBytes: Uint8Array; readonly metadata: unknown; readonly mimeType: string; };
export interface ICreationRequestMessage {
readonly type: 'html';
@@ -187,7 +187,7 @@ export interface ICreationRequestMessage {
cellTop: number;
outputOffset: number;
readonly left: number;
- readonly requiredPreloads: ReadonlyArray<IControllerPreload>;
+ readonly requiredPreloads: readonly IControllerPreload[];
readonly initiallyHidden?: boolean;
readonly rendererId?: string | undefined;
}
@@ -200,10 +200,15 @@ export interface IContentWidgetTopRequest {
readonly forceDisplay: boolean;
}
+export interface IMarkupCellScrollTops {
+ readonly id: string;
+ readonly top: number;
+}
+
export interface IViewScrollTopRequestMessage {
readonly type: 'view-scroll';
- readonly widgets: IContentWidgetTopRequest[];
- readonly markupCells: { id: string; top: number; }[];
+ readonly widgets: readonly IContentWidgetTopRequest[];
+ readonly markupCells: readonly IMarkupCellScrollTops[];
}
export interface IScrollRequestMessage {
@@ -259,14 +264,14 @@ export interface IControllerPreload {
export interface IUpdateControllerPreloadsMessage {
readonly type: 'preload';
- readonly resources: IControllerPreload[];
+ readonly resources: readonly IControllerPreload[];
}
export interface IUpdateDecorationsMessage {
readonly type: 'decorations';
readonly cellId: string;
- readonly addedClassNames: string[];
- readonly removedClassNames: string[];
+ readonly addedClassNames: readonly string[];
+ readonly removedClassNames: readonly string[];
}
export interface ICustomKernelMessage extends BaseToWebviewMessage {
@@ -324,13 +329,13 @@ export interface IMarkupCellInitialization {
export interface IInitializeMarkupCells {
readonly type: 'initializeMarkup';
- readonly cells: ReadonlyArray<IMarkupCellInitialization>;
+ readonly cells: readonly IMarkupCellInitialization[];
}
export interface INotebookStylesMessage {
readonly type: 'notebookStyles';
readonly styles: {
- [key: string]: string;
+ readonly [key: string]: string;
};
}
@@ -354,7 +359,7 @@ export interface ITokenizedStylesChangedMessage {
readonly css: string;
}
-export type FromWebviewMessage = WebviewIntialized |
+export type FromWebviewMessage = WebviewInitialized |
IDimensionMessage |
IMouseEnterMessage |
IMouseLeaveMessage |
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts
index c3bc9163d90..4459b8f032a 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts
@@ -664,8 +664,8 @@ async function webviewPreloads(ctx: PreloadContext) {
}
// Re-add new properties
- for (const variable of Object.keys(event.data.styles)) {
- documentStyle.setProperty(`--${variable}`, event.data.styles[variable]);
+ for (const [name, value] of Object.entries(event.data.styles)) {
+ documentStyle.setProperty(`--${name}`, value);
}
break;
case 'notebookOptions':
@@ -1007,7 +1007,7 @@ async function webviewPreloads(ctx: PreloadContext) {
}
}
- public updateMarkupScrolls(markupCells: { id: string; top: number; }[]) {
+ public updateMarkupScrolls(markupCells: readonly webviewMessages.IMarkupCellScrollTops[]) {
for (const { id, top } of markupCells) {
const cell = this._markupCells.get(id);
if (cell) {
diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection.ts
index ba3c117629b..2bc631d67e3 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection.ts
@@ -24,11 +24,9 @@ function rangesEqual(a: ICellRange[], b: ICellRange[]) {
// Handle first, then we migrate to ICellRange competely
// Challenge is List View talks about `element`, which needs extra work to convert to ICellRange as we support Folding and Cell Move
export class NotebookCellSelectionCollection extends Disposable {
+
private readonly _onDidChangeSelection = this._register(new Emitter<string>());
get onDidChangeSelection(): Event<string> { return this._onDidChangeSelection.event; }
- constructor() {
- super();
- }
private _primary: ICellRange | null = null;
diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts
index 8e1f4b086e7..2a32670df98 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorToolbar.ts
@@ -23,7 +23,7 @@ import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/controll
import { INotebookEditorDelegate, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem';
import { ActionViewWithLabel } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView';
-import { GlobalToolbarShowLabel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWorkbenchAssignmentService } from 'vs/workbench/services/assignment/common/assignmentService';
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
@@ -114,7 +114,7 @@ export class NotebookEditorToolbar extends Disposable {
this._register(this._notebookGlobalActionsMenu);
this._useGlobalToolbar = this.notebookOptions.getLayoutConfiguration().globalToolbar;
- this._renderLabel = this.configurationService.getValue<boolean>(GlobalToolbarShowLabel);
+ this._renderLabel = this.configurationService.getValue<boolean>(NotebookSetting.globalToolbarShowLabel);
const context = {
ui: true,
@@ -184,8 +184,8 @@ export class NotebookEditorToolbar extends Disposable {
}));
this._register(this.configurationService.onDidChangeConfiguration(e => {
- if (e.affectsConfiguration(GlobalToolbarShowLabel)) {
- this._renderLabel = this.configurationService.getValue<boolean>(GlobalToolbarShowLabel);
+ if (e.affectsConfiguration(NotebookSetting.globalToolbarShowLabel)) {
+ this._renderLabel = this.configurationService.getValue<boolean>(NotebookSetting.globalToolbarShowLabel);
const oldElement = this._notebookLeftToolbar.getElement();
oldElement.parentElement?.removeChild(oldElement);
this._notebookLeftToolbar.dispose();
diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
index badebb06286..c495315f175 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
@@ -579,7 +579,6 @@ const _mimeTypeInfo = new Map<string, MimeTypeInfo>([
['image/svg+xml', { supportedByCore: true }],
['application/json', { alwaysSecure: true, supportedByCore: true }],
[Mimes.latex, { alwaysSecure: true, supportedByCore: true }],
- [Mimes.markdown, { alwaysSecure: true, supportedByCore: true }],
[Mimes.text, { alwaysSecure: true, supportedByCore: true }],
['text/html', { supportedByCore: true }],
['text/x-javascript', { alwaysSecure: true, supportedByCore: true }], // secure because rendered as text, not executed
@@ -902,26 +901,30 @@ export interface INotebookCellStatusBarItemList {
dispose?(): void;
}
-export const DisplayOrderKey = 'notebook.displayOrder';
-export const CellToolbarLocation = 'notebook.cellToolbarLocation';
-export const CellToolbarVisibility = 'notebook.cellToolbarVisibility';
export type ShowCellStatusBarType = 'hidden' | 'visible' | 'visibleAfterExecute';
-export const ShowCellStatusBar = 'notebook.showCellStatusBar';
-export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview';
-export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment';
-export const CompactView = 'notebook.compactView';
-export const FocusIndicator = 'notebook.cellFocusIndicator';
-export const InsertToolbarLocation = 'notebook.insertToolbarLocation';
-export const GlobalToolbar = 'notebook.globalToolbar';
-export const UndoRedoPerCell = 'notebook.undoRedoPerCell';
-export const ConsolidatedOutputButton = 'notebook.consolidatedOutputButton';
-export const ShowFoldingControls = 'notebook.showFoldingControls';
-export const DragAndDropEnabled = 'notebook.dragAndDropEnabled';
-export const NotebookCellEditorOptionsCustomizations = 'notebook.editorOptionsCustomizations';
-export const ConsolidatedRunButton = 'notebook.consolidatedRunButton';
-export const OpenGettingStarted = 'notebook.experimental.openGettingStarted';
-export const TextOutputLineLimit = 'notebook.output.textLineLimit';
-export const GlobalToolbarShowLabel = 'notebook.globalToolbarShowLabel';
+
+export const NotebookSetting = {
+ displayOrder: 'notebook.displayOrder',
+ cellToolbarLocation: 'notebook.cellToolbarLocation',
+ cellToolbarVisibility: 'notebook.cellToolbarVisibility',
+ showCellStatusBar: 'notebook.showCellStatusBar',
+ textDiffEditorPreview: 'notebook.diff.enablePreview',
+ experimentalInsertToolbarAlignment: 'notebook.experimental.insertToolbarAlignment',
+ compactView: 'notebook.compactView',
+ focusIndicator: 'notebook.cellFocusIndicator',
+ insertToolbarLocation: 'notebook.insertToolbarLocation',
+ globalToolbar: 'notebook.globalToolbar',
+ undoRedoPerCell: 'notebook.undoRedoPerCell',
+ consolidatedOutputButton: 'notebook.consolidatedOutputButton',
+ showFoldingControls: 'notebook.showFoldingControls',
+ dragAndDropEnabled: 'notebook.dragAndDropEnabled',
+ cellEditorOptionsCustomizations: 'notebook.editorOptionsCustomizations',
+ consolidatedRunButton: 'notebook.consolidatedRunButton',
+ openGettingStarted: 'notebook.experimental.openGettingStarted',
+ textOutputLineLimit: 'notebook.output.textLineLimit',
+ globalToolbarShowLabel: 'notebook.globalToolbarShowLabel',
+ markupFontSize: 'notebook.markup.fontSize',
+} as const;
export const enum CellStatusbarAlignment {
Left = 1,
diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
index 387fabb158e..040cedd0bd6 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
@@ -6,7 +6,7 @@
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { CellToolbarLocation, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, ConsolidatedRunButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarLocation, NotebookCellEditorOptionsCustomizations, NotebookCellInternalMetadata, ShowCellStatusBar, ShowCellStatusBarType, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookCellInternalMetadata, NotebookSetting, ShowCellStatusBarType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const SCROLLABLE_ELEMENT_PADDING_TOP = 18;
@@ -59,30 +59,32 @@ export interface NotebookLayoutConfiguration {
showFoldingControls: 'always' | 'mouseover';
dragAndDropEnabled: boolean;
fontSize: number;
+ markupFontSize: number;
focusIndicatorLeftMargin: number;
editorOptionsCustomizations: any | undefined;
}
export interface NotebookOptionsChangeEvent {
- cellStatusBarVisibility?: boolean;
- cellToolbarLocation?: boolean;
- cellToolbarInteraction?: boolean;
- editorTopPadding?: boolean;
- compactView?: boolean;
- focusIndicator?: boolean;
- insertToolbarPosition?: boolean;
- insertToolbarAlignment?: boolean;
- globalToolbar?: boolean;
- showFoldingControls?: boolean;
- consolidatedOutputButton?: boolean;
- consolidatedRunButton?: boolean;
- dragAndDropEnabled?: boolean;
- fontSize?: boolean;
- editorOptionsCustomizations?: boolean;
- cellBreakpointMargin?: boolean;
+ readonly cellStatusBarVisibility?: boolean;
+ readonly cellToolbarLocation?: boolean;
+ readonly cellToolbarInteraction?: boolean;
+ readonly editorTopPadding?: boolean;
+ readonly compactView?: boolean;
+ readonly focusIndicator?: boolean;
+ readonly insertToolbarPosition?: boolean;
+ readonly insertToolbarAlignment?: boolean;
+ readonly globalToolbar?: boolean;
+ readonly showFoldingControls?: boolean;
+ readonly consolidatedOutputButton?: boolean;
+ readonly consolidatedRunButton?: boolean;
+ readonly dragAndDropEnabled?: boolean;
+ readonly fontSize?: boolean;
+ readonly markupFontSize?: boolean;
+ readonly editorOptionsCustomizations?: boolean;
+ readonly cellBreakpointMargin?: boolean;
}
-const defaultConfigConstants = {
+const defaultConfigConstants = Object.freeze({
codeCellLeftMargin: 28,
cellRunGutter: 32,
markdownCellTopMargin: 8,
@@ -90,9 +92,9 @@ const defaultConfigConstants = {
markdownCellLeftMargin: 0,
markdownCellGutter: 32,
focusIndicatorLeftMargin: 4
-};
+});
-const compactConfigConstants = {
+const compactConfigConstants = Object.freeze({
codeCellLeftMargin: 8,
cellRunGutter: 36,
markdownCellTopMargin: 6,
@@ -100,7 +102,7 @@ const compactConfigConstants = {
markdownCellLeftMargin: 8,
markdownCellGutter: 36,
focusIndicatorLeftMargin: 4
-};
+});
export class NotebookOptions extends Disposable {
private _layoutConfiguration: NotebookLayoutConfiguration;
@@ -109,21 +111,22 @@ export class NotebookOptions extends Disposable {
constructor(private readonly configurationService: IConfigurationService, private readonly overrides?: { cellToolbarInteraction: string, globalToolbar: boolean }) {
super();
- const showCellStatusBar = this.configurationService.getValue<ShowCellStatusBarType>(ShowCellStatusBar);
- const globalToolbar = overrides?.globalToolbar ?? this.configurationService.getValue<boolean | undefined>(GlobalToolbar) ?? true;
- const consolidatedOutputButton = this.configurationService.getValue<boolean | undefined>(ConsolidatedOutputButton) ?? true;
- const consolidatedRunButton = this.configurationService.getValue<boolean | undefined>(ConsolidatedRunButton) ?? false;
- const dragAndDropEnabled = this.configurationService.getValue<boolean | undefined>(DragAndDropEnabled) ?? true;
- const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string; }>(CellToolbarLocation) ?? { 'default': 'right' };
- const cellToolbarInteraction = overrides?.cellToolbarInteraction ?? this.configurationService.getValue<string>(CellToolbarVisibility);
- const compactView = this.configurationService.getValue<boolean | undefined>(CompactView) ?? true;
+ const showCellStatusBar = this.configurationService.getValue<ShowCellStatusBarType>(NotebookSetting.showCellStatusBar);
+ const globalToolbar = overrides?.globalToolbar ?? this.configurationService.getValue<boolean | undefined>(NotebookSetting.globalToolbar) ?? true;
+ const consolidatedOutputButton = this.configurationService.getValue<boolean | undefined>(NotebookSetting.consolidatedOutputButton) ?? true;
+ const consolidatedRunButton = this.configurationService.getValue<boolean | undefined>(NotebookSetting.consolidatedRunButton) ?? false;
+ const dragAndDropEnabled = this.configurationService.getValue<boolean | undefined>(NotebookSetting.dragAndDropEnabled) ?? true;
+ const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string; }>(NotebookSetting.cellToolbarLocation) ?? { 'default': 'right' };
+ const cellToolbarInteraction = overrides?.cellToolbarInteraction ?? this.configurationService.getValue<string>(NotebookSetting.cellToolbarVisibility);
+ const compactView = this.configurationService.getValue<boolean | undefined>(NotebookSetting.compactView) ?? true;
const focusIndicator = this._computeFocusIndicatorOption();
const insertToolbarPosition = this._computeInsertToolbarPositionOption();
const insertToolbarAlignment = this._computeInsertToolbarAlignmentOption();
const showFoldingControls = this._computeShowFoldingControlsOption();
// const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition, insertToolbarAlignment);
const fontSize = this.configurationService.getValue<number>('editor.fontSize');
- const editorOptionsCustomizations = this.configurationService.getValue(NotebookCellEditorOptionsCustomizations);
+ const markupFontSize = this.configurationService.getValue<number>(NotebookSetting.markupFontSize);
+ const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations);
this._layoutConfiguration = {
...(compactView ? compactConfigConstants : defaultConfigConstants),
@@ -153,6 +156,7 @@ export class NotebookOptions extends Disposable {
insertToolbarAlignment,
showFoldingControls,
fontSize,
+ markupFontSize,
editorOptionsCustomizations,
};
@@ -169,20 +173,21 @@ export class NotebookOptions extends Disposable {
}
private _updateConfiguration(e: IConfigurationChangeEvent) {
- const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBar);
- const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocation);
- const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility);
- const compactView = e.affectsConfiguration(CompactView);
- const focusIndicator = e.affectsConfiguration(FocusIndicator);
- const insertToolbarPosition = e.affectsConfiguration(InsertToolbarLocation);
- const insertToolbarAlignment = e.affectsConfiguration(ExperimentalInsertToolbarAlignment);
- const globalToolbar = e.affectsConfiguration(GlobalToolbar);
- const consolidatedOutputButton = e.affectsConfiguration(ConsolidatedOutputButton);
- const consolidatedRunButton = e.affectsConfiguration(ConsolidatedRunButton);
- const showFoldingControls = e.affectsConfiguration(ShowFoldingControls);
- const dragAndDropEnabled = e.affectsConfiguration(DragAndDropEnabled);
+ const cellStatusBarVisibility = e.affectsConfiguration(NotebookSetting.showCellStatusBar);
+ const cellToolbarLocation = e.affectsConfiguration(NotebookSetting.cellToolbarLocation);
+ const cellToolbarInteraction = e.affectsConfiguration(NotebookSetting.cellToolbarVisibility);
+ const compactView = e.affectsConfiguration(NotebookSetting.compactView);
+ const focusIndicator = e.affectsConfiguration(NotebookSetting.focusIndicator);
+ const insertToolbarPosition = e.affectsConfiguration(NotebookSetting.insertToolbarLocation);
+ const insertToolbarAlignment = e.affectsConfiguration(NotebookSetting.experimentalInsertToolbarAlignment);
+ const globalToolbar = e.affectsConfiguration(NotebookSetting.globalToolbar);
+ const consolidatedOutputButton = e.affectsConfiguration(NotebookSetting.consolidatedOutputButton);
+ const consolidatedRunButton = e.affectsConfiguration(NotebookSetting.consolidatedRunButton);
+ const showFoldingControls = e.affectsConfiguration(NotebookSetting.showFoldingControls);
+ const dragAndDropEnabled = e.affectsConfiguration(NotebookSetting.dragAndDropEnabled);
const fontSize = e.affectsConfiguration('editor.fontSize');
- const editorOptionsCustomizations = e.affectsConfiguration(NotebookCellEditorOptionsCustomizations);
+ const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize);
+ const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations);
if (
!cellStatusBarVisibility
@@ -198,6 +203,7 @@ export class NotebookOptions extends Disposable {
&& !showFoldingControls
&& !dragAndDropEnabled
&& !fontSize
+ && !markupFontSize
&& !editorOptionsCustomizations) {
return;
}
@@ -205,15 +211,15 @@ export class NotebookOptions extends Disposable {
let configuration = Object.assign({}, this._layoutConfiguration);
if (cellStatusBarVisibility) {
- configuration.showCellStatusBar = this.configurationService.getValue<ShowCellStatusBarType>(ShowCellStatusBar);
+ configuration.showCellStatusBar = this.configurationService.getValue<ShowCellStatusBarType>(NotebookSetting.showCellStatusBar);
}
if (cellToolbarLocation) {
- configuration.cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string; }>(CellToolbarLocation) ?? { 'default': 'right' };
+ configuration.cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string; }>(NotebookSetting.cellToolbarLocation) ?? { 'default': 'right' };
}
if (cellToolbarInteraction && !this.overrides?.cellToolbarInteraction) {
- configuration.cellToolbarInteraction = this.configurationService.getValue<string>(CellToolbarVisibility);
+ configuration.cellToolbarInteraction = this.configurationService.getValue<string>(NotebookSetting.cellToolbarVisibility);
}
if (focusIndicator) {
@@ -221,7 +227,7 @@ export class NotebookOptions extends Disposable {
}
if (compactView) {
- const compactViewValue = this.configurationService.getValue<boolean | undefined>(CompactView) ?? true;
+ const compactViewValue = this.configurationService.getValue<boolean | undefined>(NotebookSetting.compactView) ?? true;
configuration = Object.assign(configuration, {
...(compactViewValue ? compactConfigConstants : defaultConfigConstants),
});
@@ -237,15 +243,15 @@ export class NotebookOptions extends Disposable {
}
if (globalToolbar && this.overrides?.globalToolbar === undefined) {
- configuration.globalToolbar = this.configurationService.getValue<boolean>(GlobalToolbar) ?? true;
+ configuration.globalToolbar = this.configurationService.getValue<boolean>(NotebookSetting.globalToolbar) ?? true;
}
if (consolidatedOutputButton) {
- configuration.consolidatedOutputButton = this.configurationService.getValue<boolean>(ConsolidatedOutputButton) ?? true;
+ configuration.consolidatedOutputButton = this.configurationService.getValue<boolean>(NotebookSetting.consolidatedOutputButton) ?? true;
}
if (consolidatedRunButton) {
- configuration.consolidatedRunButton = this.configurationService.getValue<boolean>(ConsolidatedRunButton) ?? true;
+ configuration.consolidatedRunButton = this.configurationService.getValue<boolean>(NotebookSetting.consolidatedRunButton) ?? true;
}
if (showFoldingControls) {
@@ -253,15 +259,19 @@ export class NotebookOptions extends Disposable {
}
if (dragAndDropEnabled) {
- configuration.dragAndDropEnabled = this.configurationService.getValue<boolean>(DragAndDropEnabled) ?? true;
+ configuration.dragAndDropEnabled = this.configurationService.getValue<boolean>(NotebookSetting.dragAndDropEnabled) ?? true;
}
if (fontSize) {
configuration.fontSize = this.configurationService.getValue<number>('editor.fontSize');
}
+ if (markupFontSize) {
+ configuration.markupFontSize = this.configurationService.getValue<number>(NotebookSetting.markupFontSize);
+ }
+
if (editorOptionsCustomizations) {
- configuration.editorOptionsCustomizations = this.configurationService.getValue(NotebookCellEditorOptionsCustomizations);
+ configuration.editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations);
}
this._layoutConfiguration = Object.freeze(configuration);
@@ -281,24 +291,25 @@ export class NotebookOptions extends Disposable {
consolidatedRunButton,
dragAndDropEnabled,
fontSize,
+ markupFontSize,
editorOptionsCustomizations
});
}
private _computeInsertToolbarPositionOption() {
- return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(InsertToolbarLocation) ?? 'both';
+ return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(NotebookSetting.insertToolbarLocation) ?? 'both';
}
private _computeInsertToolbarAlignmentOption() {
- return this.configurationService.getValue<'left' | 'center'>(ExperimentalInsertToolbarAlignment) ?? 'center';
+ return this.configurationService.getValue<'left' | 'center'>(NotebookSetting.experimentalInsertToolbarAlignment) ?? 'center';
}
private _computeShowFoldingControlsOption() {
- return this.configurationService.getValue<'always' | 'mouseover'>(ShowFoldingControls) ?? 'mouseover';
+ return this.configurationService.getValue<'always' | 'mouseover'>(NotebookSetting.showFoldingControls) ?? 'mouseover';
}
private _computeFocusIndicatorOption() {
- return this.configurationService.getValue<'border' | 'gutter'>(FocusIndicator) ?? 'gutter';
+ return this.configurationService.getValue<'border' | 'gutter'>(NotebookSetting.focusIndicator) ?? 'gutter';
}
getLayoutConfiguration(): NotebookLayoutConfiguration {
@@ -456,7 +467,8 @@ export class NotebookOptions extends Disposable {
rightMargin: this._layoutConfiguration.cellRightMargin,
runGutter: this._layoutConfiguration.cellRunGutter,
dragAndDropEnabled: this._layoutConfiguration.dragAndDropEnabled,
- fontSize: this._layoutConfiguration.fontSize
+ fontSize: this._layoutConfiguration.fontSize,
+ markupFontSize: this._layoutConfiguration.markupFontSize,
};
}
@@ -470,7 +482,8 @@ export class NotebookOptions extends Disposable {
rightMargin: 0,
runGutter: 0,
dragAndDropEnabled: false,
- fontSize: this._layoutConfiguration.fontSize
+ fontSize: this._layoutConfiguration.fontSize,
+ markupFontSize: this._layoutConfiguration.markupFontSize,
};
}
diff --git a/src/vs/workbench/contrib/notebook/test/notebookDiff.test.ts b/src/vs/workbench/contrib/notebook/test/notebookDiff.test.ts
index 4881945cbf4..cab9ddc108d 100644
--- a/src/vs/workbench/contrib/notebook/test/notebookDiff.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/notebookDiff.test.ts
@@ -374,7 +374,7 @@ suite('NotebookCommon', () => {
assert.strictEqual(diffViewModels.viewModels[0].type, 'unchanged');
assert.strictEqual(diffViewModels.viewModels[0].checkIfOutputsModified(), false);
assert.strictEqual(diffViewModels.viewModels[1].type, 'modified');
- assert.strictEqual(diffViewModels.viewModels[1].checkIfOutputsModified(), true);
+ assert.deepStrictEqual(diffViewModels.viewModels[1].checkIfOutputsModified(), { reason: undefined });
});
});
diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts
index 44b34029af1..f12bf278726 100644
--- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts
+++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts
@@ -122,7 +122,7 @@ export class SettingsEditor2 extends EditorPane {
return false;
}
return type === SettingValueType.Enum ||
- type === SettingValueType.StringOrEnumArray ||
+ type === SettingValueType.Array ||
type === SettingValueType.BooleanObject ||
type === SettingValueType.Object ||
type === SettingValueType.Complex ||
diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts
index c4676688baf..d5b6f5b6156 100644
--- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts
+++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts
@@ -1101,8 +1101,7 @@ export class SettingArrayRenderer extends AbstractSettingRenderer implements ITr
common.toDispose.add(
listWidget.onDidChangeList(e => {
const newList = this.computeNewList(template, e);
- this.onDidChangeList(template, newList);
- if (newList !== null && template.onChange) {
+ if (template.onChange) {
template.onChange(newList);
}
})
@@ -1111,8 +1110,8 @@ export class SettingArrayRenderer extends AbstractSettingRenderer implements ITr
return template;
}
- private onDidChangeList(template: ISettingListItemTemplate, newList: string[] | undefined | null): void {
- if (!template.context || newList === null) {
+ private onDidChangeList(template: ISettingListItemTemplate, newList: unknown[] | undefined): void {
+ if (!template.context || !newList) {
return;
}
@@ -1179,7 +1178,7 @@ export class SettingArrayRenderer extends AbstractSettingRenderer implements ITr
super.renderSettingElement(element, index, templateData);
}
- protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingListItemTemplate, onChange: (value: string[] | undefined) => void): void {
+ protected renderValue(dataElement: SettingsTreeSettingElement, template: ISettingListItemTemplate, onChange: (value: string[] | number[] | undefined) => void): void {
const value = getListDisplayValue(dataElement);
const keySuggester = dataElement.setting.enum ? createArraySuggester(dataElement) : undefined;
template.listWidget.setValue(value, {
@@ -1193,8 +1192,17 @@ export class SettingArrayRenderer extends AbstractSettingRenderer implements ITr
}));
template.onChange = (v) => {
- onChange(v);
- renderArrayValidations(dataElement, template, v, false);
+ if (!renderArrayValidations(dataElement, template, v, false)) {
+ let arrToSave;
+ const itemType = dataElement.setting.arrayItemType;
+ if (v && (itemType === 'number' || itemType === 'integer')) {
+ arrToSave = v.map(a => +a);
+ } else {
+ arrToSave = v;
+ }
+ this.onDidChangeList(template, arrToSave);
+ onChange(arrToSave);
+ }
};
renderArrayValidations(dataElement, template, value.map(v => v.value.data.toString()), true);
@@ -2000,12 +2008,15 @@ function renderValidations(dataElement: SettingsTreeSettingElement, template: IS
return false;
}
+/**
+ * Validate and render any error message for arrays. Returns true if the value is invalid.
+ */
function renderArrayValidations(
dataElement: SettingsTreeSettingElement,
template: ISettingListItemTemplate | ISettingObjectItemTemplate,
value: string[] | Record<string, unknown> | undefined,
calledOnStartup: boolean
-) {
+): boolean {
template.containerElement.classList.add('invalid-input');
if (dataElement.setting.validator) {
const errMsg = dataElement.setting.validator(value);
@@ -2015,12 +2026,13 @@ function renderArrayValidations(
const validationError = localize('validationError', "Validation Error.");
template.containerElement.setAttribute('aria-label', [dataElement.setting.key, validationError, errMsg].join(' '));
if (!calledOnStartup) { ariaAlert(validationError + ' ' + errMsg); }
- return;
+ return true;
} else {
template.containerElement.setAttribute('aria-label', dataElement.setting.key);
template.containerElement.classList.remove('invalid-input');
}
}
+ return false;
}
function cleanRenderedMarkdown(element: Node): void {
@@ -2154,7 +2166,7 @@ class SettingsTreeDelegate extends CachedListVirtualDelegate<SettingsTreeGroupCh
return SETTINGS_ENUM_TEMPLATE_ID;
}
- if (element.valueType === SettingValueType.StringOrEnumArray) {
+ if (element.valueType === SettingValueType.Array) {
return SETTINGS_ARRAY_TEMPLATE_ID;
}
diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts
index 3fae861e143..19a507ea512 100644
--- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts
+++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts
@@ -241,8 +241,9 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
this.valueType = SettingValueType.Number;
} else if (this.setting.type === 'boolean') {
this.valueType = SettingValueType.Boolean;
- } else if (this.setting.type === 'array' && (this.setting.arrayItemType === 'string' || this.setting.arrayItemType === 'enum')) {
- this.valueType = SettingValueType.StringOrEnumArray;
+ } else if (this.setting.type === 'array' && this.setting.arrayItemType &&
+ ['string', 'enum', 'number', 'integer'].includes(this.setting.arrayItemType)) {
+ this.valueType = SettingValueType.Array;
} else if (isArray(this.setting.type) && this.setting.type.includes(SettingValueType.Null) && this.setting.type.length === 2) {
if (this.setting.type.includes(SettingValueType.Integer)) {
this.valueType = SettingValueType.NullableInteger;
diff --git a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts
index 056788ec1f9..057203bbeaa 100644
--- a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts
+++ b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts
@@ -824,7 +824,7 @@ export class ListSettingWidget extends AbstractListSettingWidget<IListDataItem>
deleteActionTooltip: localize('removeItem', "Remove Item"),
editActionTooltip: localize('editItem', "Edit Item"),
addButtonLabel: localize('addItem', "Add Item"),
- inputPlaceholder: localize('itemInputPlaceholder', "String Item..."),
+ inputPlaceholder: localize('itemInputPlaceholder', "Item..."),
siblingInputPlaceholder: localize('listSiblingInputPlaceholder', "Sibling..."),
};
}
diff --git a/src/vs/workbench/contrib/scm/browser/scmViewService.ts b/src/vs/workbench/contrib/scm/browser/scmViewService.ts
index f157881dc8c..78ac23a1588 100644
--- a/src/vs/workbench/contrib/scm/browser/scmViewService.ts
+++ b/src/vs/workbench/contrib/scm/browser/scmViewService.ts
@@ -11,7 +11,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { SCMMenus } from 'vs/workbench/contrib/scm/browser/menus';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { debounce } from 'vs/base/common/decorators';
-import { ILogService } from 'vs/platform/log/common/log';
function getProviderStorageKey(provider: ISCMProvider): string {
return `${provider.contextValue}:${provider.label}${provider.rootUri ? `:${provider.rootUri.toString()}` : ''}`;
@@ -100,8 +99,7 @@ export class SCMViewService implements ISCMViewService {
constructor(
@ISCMService private readonly scmService: ISCMService,
@IInstantiationService instantiationService: IInstantiationService,
- @IStorageService private readonly storageService: IStorageService,
- @ILogService private readonly logService: ILogService
+ @IStorageService private readonly storageService: IStorageService
) {
this.menus = instantiationService.createInstance(SCMMenus);
@@ -123,8 +121,6 @@ export class SCMViewService implements ISCMViewService {
}
private onDidAddRepository(repository: ISCMRepository): void {
- this.logService.trace('SCMViewService#onDidAddRepository', getProviderStorageKey(repository.provider));
-
if (!this.didFinishLoading) {
this.eventuallyFinishLoading();
}
@@ -135,8 +131,6 @@ export class SCMViewService implements ISCMViewService {
const index = this.previousState.all.indexOf(getProviderStorageKey(repository.provider));
if (index === -1) { // saw a repo we did not expect
- this.logService.trace('SCMViewService#onDidAddRepository', 'This is a new repository, so we stop the heuristics');
-
const added: ISCMRepository[] = [];
for (const repo of this.scmService.repositories) { // all should be visible
if (!this._visibleRepositoriesSet.has(repo)) {
@@ -179,8 +173,6 @@ export class SCMViewService implements ISCMViewService {
}
private onDidRemoveRepository(repository: ISCMRepository): void {
- this.logService.trace('SCMViewService#onDidRemoveRepository', getProviderStorageKey(repository.provider));
-
if (!this.didFinishLoading) {
this.eventuallyFinishLoading();
}
@@ -257,7 +249,6 @@ export class SCMViewService implements ISCMViewService {
@debounce(2000)
private eventuallyFinishLoading(): void {
- this.logService.trace('SCMViewService#eventuallyFinishLoading');
this.finishLoading();
}
@@ -266,7 +257,6 @@ export class SCMViewService implements ISCMViewService {
return;
}
- this.logService.trace('SCMViewService#finishLoading');
this.didFinishLoading = true;
this.previousState = undefined;
}
diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css
index cf005b14e5a..bd605002ca4 100644
--- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css
+++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css
@@ -40,24 +40,57 @@
.monaco-workbench .editor-instance .terminal-wrapper,
.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper {
display: none;
- margin: 0 10px;
height: 100%;
- padding-bottom: 2px;
box-sizing: border-box;
}
+.monaco-workbench .editor-instance .xterm,
+.monaco-workbench .pane-body.integrated-terminal .xterm {
+ /* All terminals have at least 10px left/right edge padding and 2 padding on the bottom (so underscores on last line are visible */
+ padding: 0 10px 2px;
+ /* Bottom align the terminal withing the split pane */
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.monaco-workbench .editor-instance .terminal-wrapper.fixed-dims .xterm,
+.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper.fixed-dims .xterm {
+ position: static;
+}
+
+.monaco-workbench .editor-instance .xterm-viewport,
+.monaco-workbench .pane-body.integrated-terminal .xterm-viewport {
+ z-index: 30;
+}
+
+.monaco-workbench .editor-instance .xterm-screen,
+.monaco-workbench .pane-body.integrated-terminal .xterm-screen {
+ z-index: 31;
+}
+
+.xterm .xterm-screen {
+ cursor: text;
+}
+
+/* Apply cursor styles to xterm-screen as well due to how .xterm-viewport/.xterm are positioned */
+.xterm.enable-mouse-events .xterm-screen { cursor: default; }
+.xterm.xterm-cursor-pointer .xterm-screen { cursor: pointer; }
+.xterm.column-select.focus .xterm-screen { cursor: crosshair; }
+
.monaco-workbench .editor-instance .terminal-wrapper.active,
.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper.active {
display: block;
}
-.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .terminal-wrapper,
-.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .terminal-wrapper {
- margin-left: 20px;
+.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .xterm,
+.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:first-child .xterm {
+ padding-left: 20px;
}
-.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .terminal-wrapper,
-.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .terminal-wrapper {
- margin-right: 20px;
+.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .xterm,
+.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .xterm {
+ padding-right: 20px;
}
.monaco-workbench .editor-instance .xterm a:not(.xterm-invalid-link),
@@ -69,22 +102,24 @@
.monaco-workbench .editor-instance .terminal-wrapper > div,
.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper > div {
height: 100%;
- /* Align the viewport and canvases to the bottom of the panel */
- display: flex;
- align-items: flex-end;
}
.monaco-workbench .editor-instance .xterm-viewport,
.monaco-workbench .pane-body.integrated-terminal .xterm-viewport {
box-sizing: border-box;
- margin-right: -10px;
+}
+
+.monaco-workbench .editor-instance .terminal-wrapper.fixed-dims,
+.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper.fixed-dims {
+ /* The viewport should be positioned against this so it does't conflict with a fixed dimensions terminal horizontal scroll bar*/
+ position: relative;
+}
+
+.monaco-workbench .editor-instance .terminal-wrapper:not(.fixed-dims) .xterm-viewport,
+.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper:not(.fixed-dims) .xterm-viewport {
/* Override xterm.js' width as we want to size the viewport to fill the panel so the scrollbar is on the right edge */
width: auto !important;
}
-.monaco-workbench .editor-instance .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .xterm-viewport,
-.monaco-workbench .pane-body.integrated-terminal .terminal-group .monaco-split-view2.horizontal .split-view-view:last-child .xterm-viewport {
- margin-right: -20px;
-}
.monaco-workbench .pane-body.integrated-terminal {
font-variant-ligatures: none;
diff --git a/src/vs/workbench/contrib/terminal/browser/media/widgets.css b/src/vs/workbench/contrib/terminal/browser/media/widgets.css
index 51a9ab8eff2..3ed2086bebe 100644
--- a/src/vs/workbench/contrib/terminal/browser/media/widgets.css
+++ b/src/vs/workbench/contrib/terminal/browser/media/widgets.css
@@ -26,12 +26,12 @@
.monaco-workbench .terminal-env-var-info {
position: absolute;
- right: 2px;
+ right: 10px; /* room for scroll bar */
top: 0;
width: 28px;
height: 28px;
text-align: center;
- z-index: 10;
+ z-index: 32;
opacity: 0.5;
}
@@ -40,11 +40,6 @@
opacity: 1;
}
-.monaco-workbench .pane-body.integrated-terminal .monaco-split-view2.horizontal .split-view-view:last-child .terminal-env-var-info {
- /* Adjust for reduced margin in splits */
- right: -8px;
-}
-
.monaco-workbench .terminal-env-var-info.codicon {
line-height: 28px;
}
diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css
index 018a797e85b..3a8f3534809 100644
--- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css
+++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css
@@ -40,9 +40,9 @@
*/
.xterm {
- font-feature-settings: "liga" 0;
position: relative;
user-select: none;
+ -ms-user-select: none;
-webkit-user-select: none;
}
diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
index d32a431a437..6ddd5af7baf 100644
--- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
+++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
@@ -337,7 +337,7 @@ class RemoteTerminalBackend extends Disposable implements ITerminalBackend {
return this._remoteTerminalChannel?.getWslPath(original) || original;
}
- setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise<void> {
+ async setTerminalLayoutInfo(layout?: ITerminalsLayoutInfoById): Promise<void> {
if (!this._remoteTerminalChannel) {
throw new Error(`Cannot call setActiveInstanceId when there is no remote`);
}
diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts
index b9a3fccbf94..7f2d006ee3f 100644
--- a/src/vs/workbench/contrib/terminal/browser/terminal.ts
+++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts
@@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri';
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource, TerminalShellType, IExtensionTerminalProfile, TerminalLocation, ProcessPropertyType, ProcessCapability, IProcessPropertyMap } from 'vs/platform/terminal/common/terminal';
-import { ICommandTracker, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
+import { ICommandTracker, INavigationMode, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalFont, ITerminalBackend, ITerminalProcessExtHostProxy, IRegisterContributedProfileArgs } from 'vs/workbench/contrib/terminal/common/terminal';
import type { Terminal as XTermTerminal } from 'xterm';
import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
@@ -19,6 +19,7 @@ import { IEditableData } from 'vs/workbench/common/views';
import { DeserializedTerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorSerializer';
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
+import { IKeyMods } from 'vs/platform/quickinput/common/quickInput';
export const ITerminalService = createDecorator<ITerminalService>('terminalService');
export const ITerminalEditorService = createDecorator<ITerminalEditorService>('terminalEditorService');
@@ -73,6 +74,11 @@ export const enum Direction {
Down = 3
}
+export interface IQuickPickTerminalObject {
+ config: IRegisterContributedProfileArgs | ITerminalProfile | { profile: IExtensionTerminalProfile, options: { icon?: string, color?: string } } | undefined,
+ keyMods: IKeyMods | undefined
+}
+
export interface ITerminalGroup {
activeInstance: ITerminalInstance | undefined;
terminalInstances: ITerminalInstance[];
@@ -387,6 +393,8 @@ export interface ITerminalInstance {
readonly rows: number;
readonly maxCols: number;
readonly maxRows: number;
+ readonly fixedCols?: number;
+ readonly fixedRows?: number;
readonly icon?: TerminalIcon;
readonly color?: string;
diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
index 3be66b94032..08ffd2a1e3a 100644
--- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
+++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
@@ -29,7 +29,7 @@ import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { ITerminalInstanceService, ITerminalInstance, ITerminalExternalLinkProvider, IRequestAddInstanceToGroupEvent } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager';
-import type { Terminal as XTermTerminal, IBuffer, ITerminalAddon } from 'xterm';
+import type { Terminal as XTermTerminal, ITerminalAddon } from 'xterm';
import { NavigationModeAddon } from 'vs/workbench/contrib/terminal/browser/xterm/navigationModeAddon';
import { IViewsService, IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
import { EnvironmentVariableInfoWidget } from 'vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget';
@@ -128,6 +128,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
private _fixedRows: number | undefined;
private _cwd: string | undefined = undefined;
private _initialCwd: string | undefined = undefined;
+ private _layoutSettingsChanged: boolean = true;
private _dimensionsOverride: ITerminalDimensionsOverride | undefined;
private _titleReadyPromise: Promise<string>;
private _titleReadyComplete: ((title: string) => any) | undefined;
@@ -364,6 +365,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
if (this._fixedCols) {
await this._addScrollbar();
}
+ }).catch((err) => {
+ // Ignore exceptions if the terminal is already disposed
+ if (!this._isDisposed) {
+ throw err;
+ }
});
this.addDisposable(this._configurationService.onDidChangeConfiguration(async e => {
@@ -381,6 +387,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
'editor.fontFamily'
];
if (layoutSettings.some(id => e.affectsConfiguration(id))) {
+ this._layoutSettingsChanged = true;
await this._resize();
}
if (e.affectsConfiguration(TerminalSettingId.UnicodeVersion)) {
@@ -441,9 +448,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return;
}
- const computedStyle = window.getComputedStyle(this._wrapperElement!);
- const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10);
- const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10);
+ const computedStyle = window.getComputedStyle(this._container);
+ const width = parseInt(computedStyle.width);
+ const height = parseInt(computedStyle.height);
+
this._evaluateColsAndRows(width, height);
}
@@ -514,10 +522,15 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return undefined;
}
- if (!this._wrapperElement) {
+ if (!this._wrapperElement || !this.xterm?.raw.element) {
return undefined;
}
- TerminalInstance._lastKnownCanvasDimensions = new dom.Dimension(Math.min(Constants.MaxCanvasWidth, width), height + (this._hasScrollBar && !this._horizontalScrollbar ? -scrollbarHeight - 2 : 0)/* bottom padding */);
+ const computedStyle = window.getComputedStyle(this.xterm.raw.element);
+ const horizontalPadding = parseInt(computedStyle.paddingLeft) + parseInt(computedStyle.paddingRight);
+ const verticalPadding = parseInt(computedStyle.paddingTop) + parseInt(computedStyle.paddingBottom);
+ TerminalInstance._lastKnownCanvasDimensions = new dom.Dimension(
+ Math.min(Constants.MaxCanvasWidth, width - horizontalPadding),
+ height + (this._hasScrollBar && !this._horizontalScrollbar ? -scrollbarHeight : 0) - 2/* bottom padding */ - verticalPadding);
return TerminalInstance._lastKnownCanvasDimensions;
}
@@ -543,8 +556,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
*/
protected async _createXterm(): Promise<XtermTerminal> {
const Terminal = await this._getXtermConstructor();
+ if (this._isDisposed) {
+ throw new Error('Terminal disposed of during xterm.js creation');
+ }
- // TODO: Move cols/rows over to XtermTerminal
const xterm = this._instantiationService.createInstance(XtermTerminal, Terminal, this._configHelper, this._cols, this._rows);
this.xterm = xterm;
const lineDataEventAddon = new LineDataEventAddon();
@@ -600,7 +615,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
lineDataEventAddon.setOperatingSystem(this._processManager.os);
}
if (this._processManager.os === OperatingSystem.Windows) {
- xterm.raw.setOption('windowsMode', processTraits.requiresWindowsMode || false);
+ xterm.raw.options.windowsMode = processTraits.requiresWindowsMode || false;
}
this._linkManager = this._instantiationService.createInstance(TerminalLinkManager, xterm.raw, this._processManager!);
this._areLinksReady = true;
@@ -763,13 +778,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
xterm.raw.focus();
}));
- this._register(dom.addDisposableListener(xterm.raw.element, 'wheel', (e) => {
- if (this._hasScrollBar && e.shiftKey) {
- e.stopImmediatePropagation();
- e.preventDefault();
- }
- }));
-
// xterm.js currently drops selection on keyup as we need to handle this case.
this._register(dom.addDisposableListener(xterm.raw.element, 'keyup', () => {
// Wait until keyup has propagated through the DOM before evaluating
@@ -1080,7 +1088,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
});
this._processManager.onEnvironmentVariableInfoChanged(e => this._onEnvironmentVariableInfoChanged(e));
this._processManager.onPtyDisconnect(() => {
- this._safeSetOption('disableStdin', true);
+ if (this.xterm) {
+ this.xterm.raw.options.disableStdin = true;
+ }
this.statusList.add({
id: TerminalStatus.Disconnected,
severity: Severity.Error,
@@ -1089,7 +1099,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
});
});
this._processManager.onPtyReconnect(() => {
- this._safeSetOption('disableStdin', false);
+ if (this.xterm) {
+ this.xterm.raw.options.disableStdin = false;
+ }
this.statusList.remove(TerminalStatus.Disconnected);
});
}
@@ -1223,7 +1235,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
xterm.raw.write(formatMessageForTerminal(this._shellLaunchConfig.waitOnExit));
}
// Disable all input if the terminal is exiting and listen for next keypress
- xterm.raw.setOption('disableStdin', true);
+ xterm.raw.options.disableStdin = true;
if (xterm.raw.textarea) {
this._attachPressAnyKeyToCloseListener(xterm.raw);
}
@@ -1305,7 +1317,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
// Clean up waitOnExit state
if (this._isExiting && this._shellLaunchConfig.waitOnExit) {
- this.xterm.raw.setOption('disableStdin', false);
+ this.xterm.raw.options.disableStdin = false;
this._isExiting = false;
}
}
@@ -1389,7 +1401,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._navigationModeAddon?.dispose();
this._navigationModeAddon = undefined;
}
- this.xterm!.raw.setOption('screenReaderMode', isEnabled);
+ this.xterm!.raw.options.screenReaderMode = isEnabled;
}
private _setCommandsToSkipShell(commands: string[]): void {
@@ -1399,16 +1411,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}).concat(commands);
}
- private _safeSetOption(key: string, value: any): void {
- if (!this.xterm) {
- return;
- }
-
- if (this.xterm.raw.getOption(key) !== value) {
- this.xterm.raw.setOption(key, value);
- }
- }
-
layout(dimension: dom.Dimension): void {
this._lastLayoutDimensions = dimension;
if (this.disableLayout) {
@@ -1421,6 +1423,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return;
}
+ // Evaluate columns and rows, exclude the wrapper element's margin
const terminalWidth = this._evaluateColsAndRows(dimension.width, dimension.height);
if (!terminalWidth) {
return;
@@ -1444,21 +1447,23 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
if (this.xterm) {
// Only apply these settings when the terminal is visible so that
// the characters are measured correctly.
- if (this._isVisible) {
- const font = this.xterm ? this.xterm.getFont() : this._configHelper.getFont();
+ if (this._isVisible && this._layoutSettingsChanged) {
+ const font = this.xterm.getFont();
const config = this._configHelper.config;
- this._safeSetOption('letterSpacing', font.letterSpacing);
- this._safeSetOption('lineHeight', font.lineHeight);
- this._safeSetOption('fontSize', font.fontSize);
- this._safeSetOption('fontFamily', font.fontFamily);
- this._safeSetOption('fontWeight', config.fontWeight);
- this._safeSetOption('fontWeightBold', config.fontWeightBold);
+ this.xterm.raw.options.letterSpacing = font.letterSpacing;
+ this.xterm.raw.options.lineHeight = font.lineHeight;
+ this.xterm.raw.options.fontSize = font.fontSize;
+ this.xterm.raw.options.fontFamily = font.fontFamily;
+ this.xterm.raw.options.fontWeight = config.fontWeight;
+ this.xterm.raw.options.fontWeightBold = config.fontWeightBold;
// Any of the above setting changes could have changed the dimensions of the
// terminal, re-evaluate now.
this._initDimensions();
cols = this.cols;
rows = this.rows;
+
+ this._layoutSettingsChanged = false;
}
if (isNaN(cols) || isNaN(rows)) {
@@ -1599,6 +1604,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return;
}
this._fixedCols = this._parseFixedDimension(cols);
+ this._labelComputer?.refreshLabel();
this._terminalHasFixedWidth.set(!!this._fixedCols);
const rows = await this._quickInputService.input({
title: nls.localize('setTerminalDimensionsRow', "Set Fixed Dimensions: Row"),
@@ -1609,7 +1615,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return;
}
this._fixedRows = this._parseFixedDimension(rows);
- this._addScrollbar();
+ this._labelComputer?.refreshLabel();
+ await this._refreshScrollbar();
this._resize();
this.focus();
}
@@ -1636,37 +1643,37 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._hasScrollBar = false;
this._initDimensions();
await this._resize();
- this._horizontalScrollbar?.setScrollDimensions({ scrollWidth: 0 });
} else {
- let maxCols = 0;
- if (!this.xterm.raw.buffer.active.getLine(0)) {
- return;
- }
- const lineWidth = this.xterm.raw.buffer.active.getLine(0)!.length;
- for (let i = this.xterm.raw.buffer.active.length - 1; i >= this.xterm.raw.buffer.active.viewportY; i--) {
- const lineInfo = this._getWrappedLineCount(i, this.xterm.raw.buffer.active);
- maxCols = Math.max(maxCols, ((lineInfo.lineCount * lineWidth) - lineInfo.endSpaces) || 0);
- i = lineInfo.currentIndex;
+ // Fixed columns should be at least xterm.js' regular column count
+ const proposedCols = Math.max(this.maxCols, Math.min(this.xterm.getLongestViewportWrappedLineLength(), Constants.MaxSupportedCols));
+ // Don't switch to fixed dimensions if the content already fits as it makes the scroll
+ // bar look bad being off the edge
+ if (proposedCols > this.xterm.raw.cols) {
+ this._fixedCols = proposedCols;
}
- maxCols = Math.min(maxCols, Constants.MaxSupportedCols);
- this._fixedCols = maxCols;
- await this._addScrollbar();
}
+ await this._refreshScrollbar();
+ this._labelComputer?.refreshLabel();
this.focus();
}
+ private _refreshScrollbar(): Promise<void> {
+ if (this._fixedCols || this._fixedRows) {
+ return this._addScrollbar();
+ }
+ return this._removeScrollbar();
+ }
+
private async _addScrollbar(): Promise<void> {
const charWidth = (this.xterm ? this.xterm.getFont() : this._configHelper.getFont()).charWidth;
if (!this.xterm?.raw.element || !this._wrapperElement || !this._container || !charWidth || !this._fixedCols) {
return;
}
- if (this._fixedCols < this.xterm.raw.buffer.active.getLine(0)!.length) {
- // no scrollbar needed
- return;
- }
+ this._wrapperElement.classList.add('fixed-dims');
this._hasScrollBar = true;
this._initDimensions();
- this._fixedRows = this.rows;
+ // Always remove a row to make room for the scroll bar
+ this._fixedRows = this._rows - 1;
await this._resize();
this._terminalHasFixedWidth.set(true);
if (!this._horizontalScrollbar) {
@@ -1679,39 +1686,31 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}));
this._container.appendChild(this._horizontalScrollbar.getDomNode());
}
- this._horizontalScrollbar.setScrollDimensions(
- {
- width: this.xterm.raw.element.clientWidth,
- scrollWidth: this._fixedCols * charWidth
- });
- this._horizontalScrollbar!.getDomNode().style.paddingBottom = '16px';
+ this._horizontalScrollbar.setScrollDimensions({
+ width: this.xterm.raw.element.clientWidth,
+ scrollWidth: this._fixedCols * charWidth + 40 // Padding + scroll bar
+ });
+ this._horizontalScrollbar.getDomNode().style.paddingBottom = '16px';
// work around for https://github.com/xtermjs/xterm.js/issues/3482
- for (let i = this.xterm.raw.buffer.active.viewportY; i < this.xterm.raw.buffer.active.length; i++) {
- let line = this.xterm.raw.buffer.active.getLine(i);
- (line as any)._line.isWrapped = false;
+ if (isWindows) {
+ for (let i = this.xterm.raw.buffer.active.viewportY; i < this.xterm.raw.buffer.active.length; i++) {
+ let line = this.xterm.raw.buffer.active.getLine(i);
+ (line as any)._line.isWrapped = false;
+ }
}
}
- private _getWrappedLineCount(index: number, buffer: IBuffer): { lineCount: number, currentIndex: number, endSpaces: number } {
- let line = buffer.getLine(index);
- if (!line) {
- throw new Error('Could not get line');
- }
- let currentIndex = index;
- let endSpaces = -1;
- for (let i = line?.length || 0; i > 0; i--) {
- if (line && !line?.getCell(i)?.getChars()) {
- endSpaces++;
- } else {
- break;
- }
- }
- while (line?.isWrapped && currentIndex > 0) {
- currentIndex--;
- line = buffer.getLine(currentIndex);
+ private async _removeScrollbar(): Promise<void> {
+ if (!this._container || !this._wrapperElement || !this._horizontalScrollbar) {
+ return;
}
- return { lineCount: index - currentIndex + 1, currentIndex, endSpaces };
+ this._horizontalScrollbar.getDomNode().remove();
+ this._horizontalScrollbar.dispose();
+ this._horizontalScrollbar = undefined;
+ this._wrapperElement.remove();
+ this._wrapperElement.classList.remove('fixed-dims');
+ this._container.appendChild(this._wrapperElement);
}
private _setResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void {
@@ -1782,8 +1781,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
async toggleEscapeSequenceLogging(): Promise<void> {
const xterm = await this._xtermReadyPromise;
- const isDebug = xterm.raw.getOption('logLevel') === 'debug';
- xterm.raw.setOption('logLevel', isDebug ? 'info' : 'debug');
+ xterm.raw.options.logLevel = xterm.raw.options.logLevel === 'debug' ? 'info' : 'debug';
}
async getInitialCwd(): Promise<string> {
@@ -2065,6 +2063,7 @@ export interface ITerminalLabelTemplateProperties {
process?: string | null | undefined;
sequence?: string | null | undefined;
task?: string | null | undefined;
+ fixedDimensions?: string | null | undefined;
separator?: string | ISeparator | null | undefined;
}
@@ -2083,11 +2082,12 @@ export class TerminalLabelComputer extends Disposable {
readonly onDidChangeLabel = this._onDidChangeLabel.event;
constructor(
private readonly _configHelper: TerminalConfigHelper,
- private readonly _instance: Pick<ITerminalInstance, 'shellLaunchConfig' | 'cwd' | 'initialCwd' | 'processName' | 'sequence' | 'userHome' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'>,
+ private readonly _instance: Pick<ITerminalInstance, 'shellLaunchConfig' | 'cwd' | 'fixedCols' | 'fixedRows' | 'initialCwd' | 'processName' | 'sequence' | 'userHome' | 'workspaceFolder' | 'staticTitle' | 'capabilities' | 'title' | 'description'>,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService
) {
super();
}
+
refreshLabel(): void {
this._title = this.computeLabel(this._configHelper.config.tabs.title, TerminalLabelType.Title);
this._description = this.computeLabel(this._configHelper.config.tabs.description, TerminalLabelType.Description);
@@ -2108,6 +2108,9 @@ export class TerminalLabelComputer extends Disposable {
process: this._instance.processName,
sequence: this._instance.sequence,
task: this._instance.shellLaunchConfig.description === 'Task' ? 'Task' : undefined,
+ fixedDimensions: this._instance.fixedCols
+ ? (this._instance.fixedRows ? `\u2194${this._instance.fixedCols} \u2195${this._instance.fixedRows}` : `\u2194${this._instance.fixedCols}`)
+ : (this._instance.fixedRows ? `\u2195${this._instance.fixedRows}` : ''),
separator: { label: this._configHelper.config.tabs.separator }
};
labelTemplate = labelTemplate.trim();
diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts
new file mode 100644
index 00000000000..e7dac04a1c1
--- /dev/null
+++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileQuickpick.ts
@@ -0,0 +1,240 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { iconRegistry, Codicon } from 'vs/base/common/codicons';
+import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IQuickInputService, IKeyMods, IPickOptions, IQuickPickSeparator, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
+import { IExtensionTerminalProfile, ITerminalProfile, ITerminalProfileObject, TerminalSettingPrefix } from 'vs/platform/terminal/common/terminal';
+import { getUriClasses, getColorClass, getColorStyleElement } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
+import { configureTerminalProfileIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons';
+import * as nls from 'vs/nls';
+import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
+import { ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
+import { IQuickPickTerminalObject } from 'vs/workbench/contrib/terminal/browser/terminal';
+
+
+type DefaultProfileName = string;
+export class TerminalProfileQuickpick {
+ constructor(
+ @ITerminalProfileService private readonly _terminalProfileService: ITerminalProfileService,
+ @IConfigurationService private readonly _configurationService: IConfigurationService,
+ @IQuickInputService private readonly _quickInputService: IQuickInputService,
+ @IThemeService private readonly _themeService: IThemeService
+ ) { }
+
+ async showAndGetResult(type: 'setDefault' | 'createInstance'): Promise<IQuickPickTerminalObject | DefaultProfileName | undefined> {
+ const platformKey = await this._terminalProfileService.getPlatformKey();
+ const profilesKey = TerminalSettingPrefix.Profiles + platformKey;
+ const result = await this._createAndShow(type);
+ const defaultProfileKey = `${TerminalSettingPrefix.DefaultProfile}${platformKey}`;
+ if (!result) {
+ return;
+ }
+ if (type === 'setDefault') {
+ if ('command' in result.profile) {
+ return; // Should never happen
+ } else if ('id' in result.profile) {
+ // extension contributed profile
+ await this._configurationService.updateValue(defaultProfileKey, result.profile.title, ConfigurationTarget.USER);
+ return {
+ config: {
+ extensionIdentifier: result.profile.extensionIdentifier,
+ id: result.profile.id,
+ title: result.profile.title,
+ options: {
+ color: result.profile.color,
+ icon: result.profile.icon
+ }
+ },
+ keyMods: result.keyMods
+ };
+ }
+
+ // Add the profile to settings if necessary
+ if ('isAutoDetected' in result.profile) {
+ const profilesConfig = await this._configurationService.getValue(profilesKey);
+ if (typeof profilesConfig === 'object') {
+ const newProfile: ITerminalProfileObject = {
+ path: result.profile.path
+ };
+ if (result.profile.args) {
+ newProfile.args = result.profile.args;
+ }
+ (profilesConfig as { [key: string]: ITerminalProfileObject })[result.profile.profileName] = newProfile;
+ }
+ await this._configurationService.updateValue(profilesKey, profilesConfig, ConfigurationTarget.USER);
+ }
+ // Set the default profile
+ await this._configurationService.updateValue(defaultProfileKey, result.profileName, ConfigurationTarget.USER);
+ } else if (type === 'createInstance') {
+ if ('id' in result.profile) {
+ return {
+ config: {
+ extensionIdentifier: result.profile.extensionIdentifier,
+ id: result.profile.id,
+ title: result.profile.title,
+ options: {
+ icon: result.profile.icon,
+ color: result.profile.color,
+ }
+ },
+ keyMods: result.keyMods
+ };
+ } else {
+ return { config: result.profile, keyMods: result.keyMods };
+ }
+ }
+ // for tests
+ return 'profileName' in result.profile ? result.profile.profileName : result.profile.title;
+ }
+
+ private async _createAndShow(type: 'setDefault' | 'createInstance'): Promise<IProfileQuickPickItem | undefined> {
+ const platformKey = await this._terminalProfileService.getPlatformKey();
+ const profiles = this._terminalProfileService.availableProfiles;
+ const profilesKey = TerminalSettingPrefix.Profiles + platformKey;
+ const defaultProfileName = this._terminalProfileService.getDefaultProfileName();
+ let keyMods: IKeyMods | undefined;
+ const options: IPickOptions<IProfileQuickPickItem> = {
+ placeHolder: type === 'createInstance' ? nls.localize('terminal.integrated.selectProfileToCreate', "Select the terminal profile to create") : nls.localize('terminal.integrated.chooseDefaultProfile', "Select your default terminal profile"),
+ onDidTriggerItemButton: async (context) => {
+ if ('command' in context.item.profile) {
+ return;
+ }
+ if ('id' in context.item.profile) {
+ return;
+ }
+ const configProfiles: { [key: string]: any } = this._configurationService.getValue(TerminalSettingPrefix.Profiles + platformKey);
+ const existingProfiles = !!configProfiles ? Object.keys(configProfiles) : [];
+ const name = await this._quickInputService.input({
+ prompt: nls.localize('enterTerminalProfileName', "Enter terminal profile name"),
+ value: context.item.profile.profileName,
+ validateInput: async input => {
+ if (existingProfiles.includes(input)) {
+ return nls.localize('terminalProfileAlreadyExists', "A terminal profile already exists with that name");
+ }
+ return undefined;
+ }
+ });
+ if (!name) {
+ return;
+ }
+ const newConfigValue: { [key: string]: ITerminalProfileObject } = { ...configProfiles } ?? {};
+ newConfigValue[name] = {
+ path: context.item.profile.path,
+ args: context.item.profile.args
+ };
+ await this._configurationService.updateValue(profilesKey, newConfigValue, ConfigurationTarget.USER);
+ },
+ onKeyMods: mods => keyMods = mods
+ };
+
+ // Build quick pick items
+ const quickPickItems: (IProfileQuickPickItem | IQuickPickSeparator)[] = [];
+ const configProfiles = profiles.filter(e => !e.isAutoDetected);
+ const autoDetectedProfiles = profiles.filter(e => e.isAutoDetected);
+
+ if (configProfiles.length > 0) {
+ quickPickItems.push({ type: 'separator', label: nls.localize('terminalProfiles', "profiles") });
+ quickPickItems.push(...this._sortProfileQuickPickItems(configProfiles.map(e => this._createProfileQuickPickItem(e)), defaultProfileName!));
+ }
+
+ quickPickItems.push({ type: 'separator', label: nls.localize('ICreateContributedTerminalProfileOptions', "contributed") });
+ const contributedProfiles: IProfileQuickPickItem[] = [];
+ for (const contributed of this._terminalProfileService.contributedProfiles) {
+ if (typeof contributed.icon === 'string' && contributed.icon.startsWith('$(')) {
+ contributed.icon = contributed.icon.substring(2, contributed.icon.length - 1);
+ }
+ const icon = contributed.icon && typeof contributed.icon === 'string' ? (iconRegistry.get(contributed.icon) || Codicon.terminal) : Codicon.terminal;
+ const uriClasses = getUriClasses(contributed, this._themeService.getColorTheme().type, true);
+ const colorClass = getColorClass(contributed);
+ const iconClasses = [];
+ if (uriClasses) {
+ iconClasses.push(...uriClasses);
+ }
+ if (colorClass) {
+ iconClasses.push(colorClass);
+ }
+ contributedProfiles.push({
+ label: `$(${icon.id}) ${contributed.title}`,
+ profile: {
+ extensionIdentifier: contributed.extensionIdentifier,
+ title: contributed.title,
+ icon: contributed.icon,
+ id: contributed.id,
+ color: contributed.color
+ },
+ profileName: contributed.title,
+ iconClasses
+ });
+ }
+
+ if (contributedProfiles.length > 0) {
+ quickPickItems.push(...this._sortProfileQuickPickItems(contributedProfiles, defaultProfileName!));
+ }
+
+ if (autoDetectedProfiles.length > 0) {
+ quickPickItems.push({ type: 'separator', label: nls.localize('terminalProfiles.detected', "detected") });
+ quickPickItems.push(...this._sortProfileQuickPickItems(autoDetectedProfiles.map(e => this._createProfileQuickPickItem(e)), defaultProfileName!));
+ }
+ const styleElement = getColorStyleElement(this._themeService.getColorTheme());
+ document.body.appendChild(styleElement);
+
+ const result = await this._quickInputService.pick(quickPickItems, options);
+ document.body.removeChild(styleElement);
+ if (!result) {
+ return undefined;
+ }
+ if (keyMods) {
+ result.keyMods = keyMods;
+ }
+ return result;
+ }
+
+ private _createProfileQuickPickItem(profile: ITerminalProfile): IProfileQuickPickItem {
+ const buttons: IQuickInputButton[] = [{
+ iconClass: ThemeIcon.asClassName(configureTerminalProfileIcon),
+ tooltip: nls.localize('createQuickLaunchProfile', "Configure Terminal Profile")
+ }];
+ const icon = (profile.icon && ThemeIcon.isThemeIcon(profile.icon)) ? profile.icon : Codicon.terminal;
+ const label = `$(${icon.id}) ${profile.profileName}`;
+ const colorClass = getColorClass(profile);
+ const iconClasses = [];
+ if (colorClass) {
+ iconClasses.push(colorClass);
+ }
+
+ if (profile.args) {
+ if (typeof profile.args === 'string') {
+ return { label, description: `${profile.path} ${profile.args}`, profile, profileName: profile.profileName, buttons, iconClasses };
+ }
+ const argsString = profile.args.map(e => {
+ if (e.includes(' ')) {
+ return `"${e.replace('/"/g', '\\"')}"`;
+ }
+ return e;
+ }).join(' ');
+ return { label, description: `${profile.path} ${argsString}`, profile, profileName: profile.profileName, buttons, iconClasses };
+ }
+ return { label, description: profile.path, profile, profileName: profile.profileName, buttons, iconClasses };
+ }
+
+ private _sortProfileQuickPickItems(items: IProfileQuickPickItem[], defaultProfileName: string) {
+ return items.sort((a, b) => {
+ if (b.profileName === defaultProfileName) {
+ return 1;
+ }
+ if (a.profileName === defaultProfileName) {
+ return -1;
+ }
+ return a.profileName.localeCompare(b.profileName);
+ });
+ }
+}
+
+export interface IProfileQuickPickItem extends IQuickPickItem {
+ profile: ITerminalProfile | IExtensionTerminalProfile;
+ profileName: string;
+ keyMods?: IKeyMods | undefined;
+}
diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileService.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileService.ts
index 7e30984367a..00f3aa099d6 100644
--- a/src/vs/workbench/contrib/terminal/browser/terminalProfileService.ts
+++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileService.ts
@@ -11,12 +11,12 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { isMacintosh, isWeb, isWindows, OperatingSystem, OS } from 'vs/base/common/platform';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
-import { ITerminalProfile, IExtensionTerminalProfile, TerminalSettingPrefix, TerminalSettingId, ICreateContributedTerminalProfileOptions, ITerminalProfileObject, IShellLaunchConfig } from 'vs/platform/terminal/common/terminal';
+import { ITerminalProfile, IExtensionTerminalProfile, TerminalSettingPrefix, TerminalSettingId, ITerminalProfileObject, IShellLaunchConfig } from 'vs/platform/terminal/common/terminal';
import { registerTerminalDefaultProfileConfiguration } from 'vs/platform/terminal/common/terminalPlatformConfiguration';
import { terminalIconsEqual, terminalProfileArgsMatch } from 'vs/platform/terminal/common/terminalProfiles';
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { refreshTerminalActions } from 'vs/workbench/contrib/terminal/browser/terminalActions';
-import { ITerminalProfileProvider, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
+import { IRegisterContributedProfileArgs, ITerminalProfileProvider, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@@ -61,7 +61,7 @@ export class TerminalProfileService implements ITerminalProfileService {
this._extensionService.onDidChangeExtensions(() => this.refreshAvailableProfiles());
this._configurationService.onDidChangeConfiguration(async e => {
- const platformKey = await this._getPlatformKey();
+ const platformKey = await this.getPlatformKey();
if (e.affectsConfiguration(TerminalSettingPrefix.DefaultProfile + platformKey) ||
e.affectsConfiguration(TerminalSettingPrefix.Profiles + platformKey) ||
e.affectsConfiguration(TerminalSettingId.UseWslProfiles)) {
@@ -112,7 +112,7 @@ export class TerminalProfileService implements ITerminalProfileService {
}
private async _updateContributedProfiles(): Promise<boolean> {
- const platformKey = await this._getPlatformKey();
+ const platformKey = await this.getPlatformKey();
const excludedContributedProfiles: string[] = [];
const configProfiles: { [key: string]: any } = this._configurationService.getValue(TerminalSettingPrefix.Profiles + platformKey);
for (const [profileName, value] of Object.entries(configProfiles)) {
@@ -136,7 +136,7 @@ export class TerminalProfileService implements ITerminalProfileService {
if (!primaryBackend) {
return this._availableProfiles || [];
}
- const platform = await this._getPlatformKey();
+ const platform = await this.getPlatformKey();
this._defaultProfileName = this._configurationService.getValue(`${TerminalSettingPrefix.DefaultProfile}${platform}`) ?? undefined;
return primaryBackend.getProfiles(this._configurationService.getValue(`${TerminalSettingPrefix.Profiles}${platform}`), this._defaultProfileName, includeDetectedProfiles);
}
@@ -151,7 +151,7 @@ export class TerminalProfileService implements ITerminalProfileService {
refreshTerminalActions(profiles);
}
- private async _getPlatformKey(): Promise<string> {
+ async getPlatformKey(): Promise<string> {
const env = await this._remoteAgentService.getEnvironment();
if (env) {
return env.os === OperatingSystem.Windows ? 'windows' : (env.os === OperatingSystem.Macintosh ? 'osx' : 'linux');
@@ -169,19 +169,19 @@ export class TerminalProfileService implements ITerminalProfileService {
return toDisposable(() => this._profileProviders.delete(id));
}
- async registerContributedProfile(extensionIdentifier: string, id: string, title: string, options: ICreateContributedTerminalProfileOptions): Promise<void> {
- const platformKey = await this._getPlatformKey();
+ async registerContributedProfile(args: IRegisterContributedProfileArgs): Promise<void> {
+ const platformKey = await this.getPlatformKey();
const profilesConfig = await this._configurationService.getValue(`${TerminalSettingPrefix.Profiles}${platformKey}`);
if (typeof profilesConfig === 'object') {
const newProfile: IExtensionTerminalProfile = {
- extensionIdentifier: extensionIdentifier,
- icon: options.icon,
- id,
- title: title,
- color: options.color
+ extensionIdentifier: args.extensionIdentifier,
+ icon: args.options.icon,
+ id: args.id,
+ title: args.title,
+ color: args.options.color
};
- (profilesConfig as { [key: string]: ITerminalProfileObject })[title] = newProfile;
+ (profilesConfig as { [key: string]: ITerminalProfileObject })[args.title] = newProfile;
}
await this._configurationService.updateValue(`${TerminalSettingPrefix.Profiles}${platformKey}`, profilesConfig, ConfigurationTarget.USER);
return;
@@ -191,7 +191,7 @@ export class TerminalProfileService implements ITerminalProfileService {
// prevents recursion with the MainThreadTerminalService call to create terminal
// and defers to the provided launch config when an executable is provided
if (shellLaunchConfig && !shellLaunchConfig.extHostTerminalId && !('executable' in shellLaunchConfig)) {
- const key = await this._getPlatformKey();
+ const key = await this.getPlatformKey();
const defaultProfileName = this._configurationService.getValue(`${TerminalSettingPrefix.DefaultProfile}${key}`);
const contributedDefaultProfile = this.contributedProfiles.find(p => p.title === defaultProfileName);
return contributedDefaultProfile;
diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts
index 05016499524..ef444259b8a 100644
--- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts
+++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts
@@ -10,18 +10,16 @@ import { debounce } from 'vs/base/common/decorators';
import { Emitter, Event } from 'vs/base/common/event';
import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
-import { isMacintosh, isWeb, isWindows, OperatingSystem } from 'vs/base/common/platform';
+import { isMacintosh, isWeb } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
import * as nls from 'vs/nls';
-import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
-import { IKeyMods, IPickOptions, IQuickInputButton, IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
-import { ICreateContributedTerminalProfileOptions, IExtensionTerminalProfile, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalLocation, TerminalLocationString, TerminalSettingPrefix } from 'vs/platform/terminal/common/terminal';
+import { ICreateContributedTerminalProfileOptions, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalLocation, TerminalLocationString } from 'vs/platform/terminal/common/terminal';
import { iconForeground } from 'vs/platform/theme/common/colorRegistry';
import { IconDefinition } from 'vs/platform/theme/common/iconRegistry';
import { ColorScheme } from 'vs/platform/theme/common/theme';
@@ -31,8 +29,7 @@ import { IEditableData, IViewsService } from 'vs/workbench/common/views';
import { ICreateTerminalOptions, IRequestAddInstanceToGroupEvent, ITerminalEditorService, ITerminalExternalLinkProvider, ITerminalFindHost, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalLocationOptions, ITerminalService, ITerminalServiceNativeDelegate, TerminalConnectionState, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TerminalEditor } from 'vs/workbench/contrib/terminal/browser/terminalEditor';
-import { getColorClass, getColorStyleContent, getColorStyleElement, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
-import { configureTerminalProfileIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons';
+import { getColorStyleContent, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
import { getInstanceFromResource, getTerminalUri, parseTerminalUri } from 'vs/workbench/contrib/terminal/browser/terminalUri';
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
import { IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalBackend, ITerminalProcessExtHostProxy, ITerminalProfileService, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
@@ -46,6 +43,8 @@ import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/ed
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
+import { TerminalProfileQuickpick } from 'vs/workbench/contrib/terminal/browser/terminalProfileQuickpick';
+import { IKeyMods } from 'vs/base/parts/quickinput/common/quickInput';
export class TerminalService implements ITerminalService {
declare _serviceBrand: undefined;
@@ -66,7 +65,7 @@ export class TerminalService implements ITerminalService {
private _configHelper: TerminalConfigHelper;
private _remoteTerminalsInitPromise: Promise<void> | undefined;
private _localTerminalsInitPromise: Promise<void> | undefined;
- private _connectionState: TerminalConnectionState;
+ private _connectionState: TerminalConnectionState = TerminalConnectionState.Connecting;
private _nativeDelegate?: ITerminalServiceNativeDelegate;
private _shutdownWindowCount?: number;
@@ -144,8 +143,6 @@ export class TerminalService implements ITerminalService {
@IDialogService private _dialogService: IDialogService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IRemoteAgentService private _remoteAgentService: IRemoteAgentService,
- @IQuickInputService private _quickInputService: IQuickInputService,
- @IConfigurationService private _configurationService: IConfigurationService,
@IViewsService private _viewsService: IViewsService,
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@@ -154,7 +151,6 @@ export class TerminalService implements ITerminalService {
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
@IEditorResolverService editorResolverService: IEditorResolverService,
@IEditorGroupsService private readonly _editorGroupsService: IEditorGroupsService,
- @IThemeService private readonly _themeService: IThemeService,
@ITerminalProfileService private readonly _terminalProfileService: ITerminalProfileService,
@IExtensionService private readonly _extensionService: IExtensionService,
@INotificationService private readonly _notificationService: INotificationService
@@ -236,29 +232,67 @@ export class TerminalService implements ITerminalService {
}
});
- const enableTerminalReconnection = this.configHelper.config.enablePersistentSessions;
-
- // Connect to the extension host if it's there, set the connection state to connected when
- // it's done. This should happen even when there is no extension host.
- this._connectionState = TerminalConnectionState.Connecting;
+ // Create async as the class depends on `this`
+ timeout(0).then(() => this._instantiationService.createInstance(TerminalEditorStyle, document.head));
+ }
+ async showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise<ITerminalInstance | undefined> {
+ const quickPick = this._instantiationService.createInstance(TerminalProfileQuickpick);
+ const result = await quickPick.showAndGetResult(type);
+ if (!result) {
+ return;
+ }
+ if (typeof result === 'string') {
+ return;
+ }
+ let keyMods: IKeyMods | undefined = result.keyMods;
+ if (type === 'createInstance') {
+ const activeInstance = this.getDefaultInstanceHost().activeInstance;
+ let instance;
- const isPersistentRemote = !!this._environmentService.remoteAuthority && enableTerminalReconnection;
+ if (result.config && 'id' in result?.config) {
+ await this.createContributedTerminalProfile(result.config.extensionIdentifier, result.config.id, {
+ icon: result.config.options?.icon,
+ color: result.config.options?.color,
+ location: !!(keyMods?.alt && activeInstance) ? { splitActiveTerminal: true } : this.defaultLocation
+ });
+ return;
+ } else if (result.config && 'profileName' in result.config) {
+ if (keyMods?.alt && activeInstance) {
+ // create split, only valid if there's an active instance
+ instance = await this.createTerminal({ location: { parentTerminal: activeInstance }, config: result.config });
+ } else {
+ instance = await this.createTerminal({ location: this.defaultLocation, config: result.config, cwd });
+ }
+ }
- if (isPersistentRemote) {
- this._remoteTerminalsInitPromise = this._reconnectToRemoteTerminals();
- } else if (enableTerminalReconnection) {
- this._localTerminalsInitPromise = this._reconnectToLocalTerminals();
- } else {
- this._connectionState = TerminalConnectionState.Connected;
+ if (instance && this.defaultLocation !== TerminalLocation.Editor) {
+ this._terminalGroupService.showPanel(true);
+ this.setActiveInstance(instance);
+ return instance;
+ }
}
-
- // Create async as the class depends on `this`
- timeout(0).then(() => this._instantiationService.createInstance(TerminalEditorStyle, document.head));
+ return undefined;
}
handleNewRegisteredBackend(backend: ITerminalBackend) {
if (backend.remoteAuthority === this._environmentService.remoteAuthority) {
this._primaryBackend = backend;
+ const enableTerminalReconnection = this.configHelper.config.enablePersistentSessions;
+
+ // Connect to the extension host if it's there, set the connection state to connected when
+ // it's done. This should happen even when there is no extension host.
+ this._connectionState = TerminalConnectionState.Connecting;
+
+ const isPersistentRemote = !!this._environmentService.remoteAuthority && enableTerminalReconnection;
+
+ if (isPersistentRemote) {
+ this._remoteTerminalsInitPromise = this._reconnectToRemoteTerminals();
+ } else if (enableTerminalReconnection) {
+ this._localTerminalsInitPromise = this._reconnectToLocalTerminals();
+ } else {
+ this._connectionState = TerminalConnectionState.Connected;
+ }
+
backend.onDidRequestDetach(async (e) => {
const instanceToDetach = this.getInstanceFromResource(getTerminalUri(e.workspaceId, e.instanceId));
if (instanceToDetach) {
@@ -848,172 +882,6 @@ export class TerminalService implements ITerminalService {
return !res.confirmed;
}
- private async _getPlatformKey(): Promise<string> {
- const env = await this._remoteAgentService.getEnvironment();
- if (env) {
- return env.os === OperatingSystem.Windows ? 'windows' : (env.os === OperatingSystem.Macintosh ? 'osx' : 'linux');
- }
- return isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux');
- }
-
- async showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise<ITerminalInstance | undefined> {
- let keyMods: IKeyMods | undefined;
- const profiles = this._terminalProfileService.availableProfiles;
- const platformKey = await this._getPlatformKey();
- const profilesKey = `${TerminalSettingPrefix.Profiles}${platformKey}`;
- const defaultProfileKey = `${TerminalSettingPrefix.DefaultProfile}${platformKey}`;
- const defaultProfileName = this._configurationService.getValue<string>(defaultProfileKey);
-
- const options: IPickOptions<IProfileQuickPickItem> = {
- placeHolder: type === 'createInstance' ? nls.localize('terminal.integrated.selectProfileToCreate', "Select the terminal profile to create") : nls.localize('terminal.integrated.chooseDefaultProfile', "Select your default terminal profile"),
- onDidTriggerItemButton: async (context) => {
- if ('command' in context.item.profile) {
- return;
- }
- if ('id' in context.item.profile) {
- return;
- }
- const configProfiles = this._configurationService.getValue<{ [key: string]: ITerminalProfileObject }>(profilesKey);
- const existingProfiles = configProfiles ? Object.keys(configProfiles) : [];
- const name = await this._quickInputService.input({
- prompt: nls.localize('enterTerminalProfileName', "Enter terminal profile name"),
- value: context.item.profile.profileName,
- validateInput: async input => {
- if (existingProfiles.includes(input)) {
- return nls.localize('terminalProfileAlreadyExists', "A terminal profile already exists with that name");
- }
- return undefined;
- }
- });
- if (!name) {
- return;
- }
- const newConfigValue: { [key: string]: ITerminalProfileObject } = { ...configProfiles } ?? {};
- newConfigValue[name] = {
- path: context.item.profile.path,
- args: context.item.profile.args
- };
- await this._configurationService.updateValue(profilesKey, newConfigValue, ConfigurationTarget.USER);
- },
- onKeyMods: mods => keyMods = mods
- };
-
- // Build quick pick items
- const quickPickItems: (IProfileQuickPickItem | IQuickPickSeparator)[] = [];
- const configProfiles = profiles.filter(e => !e.isAutoDetected);
- const autoDetectedProfiles = profiles.filter(e => e.isAutoDetected);
-
- if (configProfiles.length > 0) {
- quickPickItems.push({ type: 'separator', label: nls.localize('terminalProfiles', "profiles") });
- quickPickItems.push(...this._sortProfileQuickPickItems(configProfiles.map(e => this._createProfileQuickPickItem(e)), defaultProfileName));
- }
-
- quickPickItems.push({ type: 'separator', label: nls.localize('ICreateContributedTerminalProfileOptions', "contributed") });
- const contributedProfiles: IProfileQuickPickItem[] = [];
- for (const contributed of this._terminalProfileService.contributedProfiles) {
- if (typeof contributed.icon === 'string' && contributed.icon.startsWith('$(')) {
- contributed.icon = contributed.icon.substring(2, contributed.icon.length - 1);
- }
- const icon = contributed.icon && typeof contributed.icon === 'string' ? (iconRegistry.get(contributed.icon) || Codicon.terminal) : Codicon.terminal;
- const uriClasses = getUriClasses(contributed, this._themeService.getColorTheme().type, true);
- const colorClass = getColorClass(contributed);
- const iconClasses = [];
- if (uriClasses) {
- iconClasses.push(...uriClasses);
- }
- if (colorClass) {
- iconClasses.push(colorClass);
- }
- contributedProfiles.push({
- label: `$(${icon.id}) ${contributed.title}`,
- profile: {
- extensionIdentifier: contributed.extensionIdentifier,
- title: contributed.title,
- icon: contributed.icon,
- id: contributed.id,
- color: contributed.color
- },
- profileName: contributed.title,
- iconClasses
- });
- }
-
- if (contributedProfiles.length > 0) {
- quickPickItems.push(...this._sortProfileQuickPickItems(contributedProfiles, defaultProfileName));
- }
-
- if (autoDetectedProfiles.length > 0) {
- quickPickItems.push({ type: 'separator', label: nls.localize('terminalProfiles.detected', "detected") });
- quickPickItems.push(...this._sortProfileQuickPickItems(autoDetectedProfiles.map(e => this._createProfileQuickPickItem(e)), defaultProfileName));
- }
- const styleElement = getColorStyleElement(this._themeService.getColorTheme());
- document.body.appendChild(styleElement);
-
- const value = await this._quickInputService.pick(quickPickItems, options);
- document.body.removeChild(styleElement);
- if (!value) {
- return;
- }
- if (type === 'createInstance') {
- const activeInstance = this.getDefaultInstanceHost().activeInstance;
- let instance;
-
- if ('id' in value.profile) {
- await this.createContributedTerminalProfile(value.profile.extensionIdentifier, value.profile.id, {
- icon: value.profile.icon,
- color: value.profile.color,
- location: !!(keyMods?.alt && activeInstance) ? { splitActiveTerminal: true } : this.defaultLocation
- });
- return;
- } else {
- if (keyMods?.alt && activeInstance) {
- // create split, only valid if there's an active instance
- instance = await this.createTerminal({ location: { parentTerminal: activeInstance }, config: value.profile });
- } else {
- instance = await this.createTerminal({ location: this.defaultLocation, config: value.profile, cwd });
- }
- }
-
- if (instance && this.defaultLocation !== TerminalLocation.Editor) {
- this._terminalGroupService.showPanel(true);
- this.setActiveInstance(instance);
- return instance;
- }
- } else { // setDefault
- if ('command' in value.profile) {
- return; // Should never happen
- } else if ('id' in value.profile) {
- // extension contributed profile
- await this._configurationService.updateValue(defaultProfileKey, value.profile.title, ConfigurationTarget.USER);
-
- this._terminalProfileService.registerContributedProfile(value.profile.extensionIdentifier, value.profile.id, value.profile.title, {
- color: value.profile.color,
- icon: value.profile.icon
- });
- return;
- }
- }
-
- // Add the profile to settings if necessary
- if (value.profile.isAutoDetected) {
- const profilesConfig = await this._configurationService.getValue(profilesKey);
- if (typeof profilesConfig === 'object') {
- const newProfile: ITerminalProfileObject = {
- path: value.profile.path
- };
- if (value.profile.args) {
- newProfile.args = value.profile.args;
- }
- (profilesConfig as { [key: string]: ITerminalProfileObject })[value.profile.profileName] = newProfile;
- }
- await this._configurationService.updateValue(profilesKey, profilesConfig, ConfigurationTarget.USER);
- }
- // Set the default profile
- await this._configurationService.updateValue(defaultProfileKey, value.profile.profileName, ConfigurationTarget.USER);
- return undefined;
- }
-
-
getDefaultInstanceHost(): ITerminalInstanceHost {
if (this.defaultLocation === TerminalLocation.Editor) {
return this._terminalEditorService;
@@ -1042,46 +910,6 @@ export class TerminalService implements ITerminalService {
return instance?.target === TerminalLocation.Editor ? this._terminalEditorService : this._terminalGroupService;
}
- private _createProfileQuickPickItem(profile: ITerminalProfile): IProfileQuickPickItem {
- const buttons: IQuickInputButton[] = [{
- iconClass: ThemeIcon.asClassName(configureTerminalProfileIcon),
- tooltip: nls.localize('createQuickLaunchProfile', "Configure Terminal Profile")
- }];
- const icon = (profile.icon && ThemeIcon.isThemeIcon(profile.icon)) ? profile.icon : Codicon.terminal;
- const label = `$(${icon.id}) ${profile.profileName}`;
- const colorClass = getColorClass(profile);
- const iconClasses = [];
- if (colorClass) {
- iconClasses.push(colorClass);
- }
-
- if (profile.args) {
- if (typeof profile.args === 'string') {
- return { label, description: `${profile.path} ${profile.args}`, profile, profileName: profile.profileName, buttons, iconClasses };
- }
- const argsString = profile.args.map(e => {
- if (e.includes(' ')) {
- return `"${e.replace('/"/g', '\\"')}"`;
- }
- return e;
- }).join(' ');
- return { label, description: `${profile.path} ${argsString}`, profile, profileName: profile.profileName, buttons, iconClasses };
- }
- return { label, description: profile.path, profile, profileName: profile.profileName, buttons, iconClasses };
- }
-
- private _sortProfileQuickPickItems(items: IProfileQuickPickItem[], defaultProfileName: string) {
- return items.sort((a, b) => {
- if (b.profileName === defaultProfileName) {
- return 1;
- }
- if (a.profileName === defaultProfileName) {
- return -1;
- }
- return a.profileName.localeCompare(b.profileName);
- });
- }
-
private _convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile?: IShellLaunchConfig | ITerminalProfile, cwd?: string | URI): IShellLaunchConfig {
if (shellLaunchConfigOrProfile && 'profileName' in shellLaunchConfigOrProfile) {
const profile = shellLaunchConfigOrProfile;
@@ -1297,11 +1125,6 @@ export class TerminalService implements ITerminalService {
}
}
-interface IProfileQuickPickItem extends IQuickPickItem {
- profile: ITerminalProfile | IExtensionTerminalProfile;
- profileName: string;
-}
-
class TerminalEditorStyle extends Themable {
private _styleElement: HTMLElement;
diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
index dfc69cec4fd..3b5aa91c7fe 100644
--- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
+++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import type { ITheme, RendererType, Terminal as RawXtermTerminal } from 'xterm';
+import type { IBuffer, ITheme, RendererType, Terminal as RawXtermTerminal } from 'xterm';
import type { ISearchOptions, SearchAddon as SearchAddonType } from 'xterm-addon-search';
import type { Unicode11Addon as Unicode11AddonType } from 'xterm-addon-unicode11';
import type { WebglAddon as WebglAddonType } from 'xterm-addon-webgl';
@@ -157,27 +157,27 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
updateConfig(): void {
const config = this._configHelper.config;
- this._safeSetOption('altClickMovesCursor', config.altClickMovesCursor);
+ this.raw.options.altClickMovesCursor = config.altClickMovesCursor;
this._setCursorBlink(config.cursorBlinking);
this._setCursorStyle(config.cursorStyle);
this._setCursorWidth(config.cursorWidth);
- this._safeSetOption('scrollback', config.scrollback);
- this._safeSetOption('drawBoldTextInBrightColors', config.drawBoldTextInBrightColors);
- this._safeSetOption('minimumContrastRatio', config.minimumContrastRatio);
- this._safeSetOption('fastScrollSensitivity', config.fastScrollSensitivity);
- this._safeSetOption('scrollSensitivity', config.mouseWheelScrollSensitivity);
- this._safeSetOption('macOptionIsMeta', config.macOptionIsMeta);
+ this.raw.options.scrollback = config.scrollback;
+ this.raw.options.drawBoldTextInBrightColors = config.drawBoldTextInBrightColors;
+ this.raw.options.minimumContrastRatio = config.minimumContrastRatio;
+ this.raw.options.fastScrollSensitivity = config.fastScrollSensitivity;
+ this.raw.options.scrollSensitivity = config.mouseWheelScrollSensitivity;
+ this.raw.options.macOptionIsMeta = config.macOptionIsMeta;
const editorOptions = this._configurationService.getValue<IEditorOptions>('editor');
- this._safeSetOption('altClickMovesCursor', config.altClickMovesCursor && editorOptions.multiCursorModifier === 'alt');
- this._safeSetOption('macOptionClickForcesSelection', config.macOptionClickForcesSelection);
- this._safeSetOption('rightClickSelectsWord', config.rightClickBehavior === 'selectWord');
- this._safeSetOption('wordSeparator', config.wordSeparators);
- this._safeSetOption('customGlyphs', config.customGlyphs);
+ this.raw.options.altClickMovesCursor = config.altClickMovesCursor && editorOptions.multiCursorModifier === 'alt';
+ this.raw.options.macOptionClickForcesSelection = config.macOptionClickForcesSelection;
+ this.raw.options.rightClickSelectsWord = config.rightClickBehavior === 'selectWord';
+ this.raw.options.wordSeparator = config.wordSeparators;
+ this.raw.options.customGlyphs = config.customGlyphs;
if ((!isSafari && config.gpuAcceleration === 'auto' && XtermTerminal._suggestedRendererType === undefined) || config.gpuAcceleration === 'on') {
this._enableWebglRenderer();
} else {
this._disposeOfWebglRenderer();
- this._safeSetOption('rendererType', this._getBuiltInXtermRenderer(config.gpuAcceleration, XtermTerminal._suggestedRendererType));
+ this.raw.options.rendererType = this._getBuiltInXtermRenderer(config.gpuAcceleration, XtermTerminal._suggestedRendererType);
}
}
@@ -222,6 +222,38 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
return this._configHelper.getFont(this._core);
}
+ getLongestViewportWrappedLineLength(): number {
+ let maxLineLength = 0;
+ for (let i = this.raw.buffer.active.length - 1; i >= this.raw.buffer.active.viewportY; i--) {
+ const lineInfo = this._getWrappedLineCount(i, this.raw.buffer.active);
+ maxLineLength = Math.max(maxLineLength, ((lineInfo.lineCount * this.raw.cols) - lineInfo.endSpaces) || 0);
+ i = lineInfo.currentIndex;
+ }
+ return maxLineLength;
+ }
+
+ private _getWrappedLineCount(index: number, buffer: IBuffer): { lineCount: number, currentIndex: number, endSpaces: number } {
+ let line = buffer.getLine(index);
+ if (!line) {
+ throw new Error('Could not get line');
+ }
+ let currentIndex = index;
+ let endSpaces = 0;
+ // line.length may exceed cols as it doesn't necessarily trim the backing array on resize
+ for (let i = Math.min(line.length, this.raw.cols) - 1; i >= 0; i--) {
+ if (line && !line?.getCell(i)?.getChars()) {
+ endSpaces++;
+ } else {
+ break;
+ }
+ }
+ while (line?.isWrapped && currentIndex > 0) {
+ currentIndex--;
+ line = buffer.getLine(currentIndex);
+ }
+ return { lineCount: index - currentIndex + 1, currentIndex, endSpaces };
+ }
+
scrollDownLine(): void {
this.raw.scrollLines(1);
}
@@ -250,30 +282,23 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
this.raw.clear();
}
- private _safeSetOption(key: string, value: any): void {
- if (this.raw.getOption(key) !== value) {
- this.raw.setOption(key, value);
- }
- }
-
private _setCursorBlink(blink: boolean): void {
- if (this.raw.getOption('cursorBlink') !== blink) {
- this.raw.setOption('cursorBlink', blink);
+ if (this.raw.options.cursorBlink !== blink) {
+ this.raw.options.cursorBlink = blink;
this.raw.refresh(0, this.raw.rows - 1);
}
}
- private _setCursorStyle(style: string): void {
- if (this.raw.getOption('cursorStyle') !== style) {
+ private _setCursorStyle(style: 'block' | 'underline' | 'bar' | 'line'): void {
+ if (this.raw.options.cursorStyle !== style) {
// 'line' is used instead of bar in VS Code to be consistent with editor.cursorStyle
- const xtermOption = style === 'line' ? 'bar' : style;
- this.raw.setOption('cursorStyle', xtermOption);
+ this.raw.options.cursorStyle = (style === 'line') ? 'bar' : style;
}
}
private _setCursorWidth(width: number): void {
- if (this.raw.getOption('cursorWidth') !== width) {
- this.raw.setOption('cursorWidth', width);
+ if (this.raw.options.cursorWidth !== width) {
+ this.raw.options.cursorWidth = width;
}
}
@@ -296,7 +321,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
this._webglAddon.onContextLoss(() => {
this._logService.info(`Webgl lost context, disposing of webgl renderer`);
this._disposeOfWebglRenderer();
- this._safeSetOption('rendererType', 'dom');
+ this.raw.options.rendererType = 'dom';
});
} catch (e) {
this._logService.warn(`Webgl could not be loaded. Falling back to the canvas renderer type.`, e);
@@ -305,7 +330,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal {
if (!neverMeasureRenderTime && this._configHelper.config.gpuAcceleration !== 'off') {
this._measureRenderTime();
}
- this._safeSetOption('rendererType', 'canvas');
+ this.raw.options.rendererType = 'canvas';
XtermTerminal._suggestedRendererType = 'canvas';
this._disposeOfWebglRenderer();
}
diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
index 6812a399682..6bc36af3107 100644
--- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
+++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
@@ -261,11 +261,11 @@ export class RemoteTerminalChannelClient {
return this._channel.call('$getWslPath', [original]);
}
- setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise<void> {
+ setTerminalLayoutInfo(layout?: ITerminalsLayoutInfoById): Promise<void> {
const workspace = this._workspaceContextService.getWorkspace();
const args: ISetTerminalLayoutInfoArgs = {
workspaceId: workspace.id,
- tabs: layout.tabs
+ tabs: layout ? layout.tabs : []
};
return this._channel.call<void>('$setTerminalLayoutInfo', args);
}
diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts
index bf99ce95676..35bdcce9826 100644
--- a/src/vs/workbench/contrib/terminal/common/terminal.ts
+++ b/src/vs/workbench/contrib/terminal/common/terminal.ts
@@ -57,17 +57,22 @@ export interface ITerminalProfileResolverService {
createProfileFromShellAndShellArgs(shell?: unknown, shellArgs?: unknown): Promise<ITerminalProfile | string>;
}
+export interface IRegisterContributedProfileArgs {
+ extensionIdentifier: string, id: string, title: string, options: ICreateContributedTerminalProfileOptions;
+}
+
export const ITerminalProfileService = createDecorator<ITerminalProfileService>('terminalProfileService');
export interface ITerminalProfileService {
readonly _serviceBrand: undefined;
readonly availableProfiles: ITerminalProfile[];
readonly contributedProfiles: IExtensionTerminalProfile[];
readonly profilesReady: Promise<void>;
+ getPlatformKey(): Promise<string>;
refreshAvailableProfiles(): void;
getDefaultProfileName(): string | undefined;
onDidChangeAvailableProfiles: Event<ITerminalProfile[]>;
getContributedDefaultProfile(shellLaunchConfig: IShellLaunchConfig): Promise<IExtensionTerminalProfile | undefined>;
- registerContributedProfile(extensionIdentifier: string, id: string, title: string, options: ICreateContributedTerminalProfileOptions): Promise<void>;
+ registerContributedProfile(args: IRegisterContributedProfileArgs): Promise<void>;
getContributedProfileProvider(extensionIdentifier: string, id: string): ITerminalProfileProvider | undefined;
registerTerminalProfileProvider(extensionIdentifier: string, id: string, profileProvider: ITerminalProfileProvider): IDisposable;
}
diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.test.ts
index e5e070b430e..7a92132511c 100644
--- a/src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.test.ts
+++ b/src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.test.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
-import { ITerminalConfiguration, ITerminalBackend } from 'vs/workbench/contrib/terminal/common/terminal';
+import { ITerminalConfiguration, ITerminalBackend, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TestExtensionService } from 'vs/workbench/test/common/workbenchTestServices';
import { TerminalProfileService } from 'vs/workbench/contrib/terminal/browser/terminalProfileService';
@@ -19,12 +19,16 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
-import { ThemeIcon } from 'vs/platform/theme/common/themeService';
+import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { Codicon } from 'vs/base/common/codicons';
import { deepStrictEqual } from 'assert';
import { Emitter } from 'vs/base/common/event';
+import { IProfileQuickPickItem, TerminalProfileQuickpick } from 'vs/workbench/contrib/terminal/browser/terminalProfileQuickpick';
+import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
+import { IPickOptions, IQuickInputService, Omit, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
+import { CancellationToken } from 'vs/base/common/cancellation';
-class TestTerminalProfileService extends TerminalProfileService {
+class TestTerminalProfileService extends TerminalProfileService implements Partial<ITerminalProfileService>{
hasRefreshedProfiles: Promise<void> | undefined;
override refreshAvailableProfiles(): void {
this.hasRefreshedProfiles = this._refreshAvailableProfilesNow();
@@ -38,6 +42,46 @@ class TestTerminalProfileService extends TerminalProfileService {
}
}
+class MockTerminalProfileService implements Partial<ITerminalProfileService>{
+ hasRefreshedProfiles: Promise<void> | undefined;
+ _defaultProfileName: string | undefined;
+ availableProfiles?: ITerminalProfile[] | undefined = [];
+ contributedProfiles?: IExtensionTerminalProfile[] | undefined = [];
+ async getPlatformKey(): Promise<string> {
+ return 'linux';
+ }
+ getDefaultProfileName(): string | undefined {
+ return this._defaultProfileName;
+ }
+ setProfiles(profiles: ITerminalProfile[], contributed: IExtensionTerminalProfile[]): void {
+ this.availableProfiles = profiles;
+ this.contributedProfiles = contributed;
+ }
+ setDefaultProfileName(name: string): void {
+ this._defaultProfileName = name;
+ }
+}
+
+
+class MockQuickInputService implements Partial<IQuickInputService> {
+ _pick: IProfileQuickPickItem = powershellPick;
+ pick(picks: QuickPickInput<IProfileQuickPickItem>[] | Promise<QuickPickInput<IProfileQuickPickItem>[]>, options?: IPickOptions<IProfileQuickPickItem> & { canPickMany: true; }, token?: CancellationToken): Promise<IProfileQuickPickItem[] | undefined>;
+ pick(picks: QuickPickInput<IProfileQuickPickItem>[] | Promise<QuickPickInput<IProfileQuickPickItem>[]>, options?: IPickOptions<IProfileQuickPickItem> & { canPickMany: false; }, token?: CancellationToken): Promise<IProfileQuickPickItem | undefined>;
+ pick(picks: QuickPickInput<IProfileQuickPickItem>[] | Promise<QuickPickInput<IProfileQuickPickItem>[]>, options?: Omit<IPickOptions<IProfileQuickPickItem>, 'canPickMany'>, token?: CancellationToken): Promise<IProfileQuickPickItem | undefined>;
+ async pick(picks: any, options?: any, token?: any): Promise<IProfileQuickPickItem | IProfileQuickPickItem[] | undefined> {
+ Promise.resolve(picks);
+ return this._pick;
+ }
+
+ setPick(pick: IProfileQuickPickItem) {
+ this._pick = pick;
+ }
+}
+
+class TestTerminalProfileQuickpick extends TerminalProfileQuickpick {
+
+}
+
class TestTerminalExtensionService extends TestExtensionService {
readonly _onDidChangeExtensions = new Emitter<void>();
}
@@ -96,7 +140,8 @@ let jsdebugProfile = {
id: 'extension.js-debug.debugTerminal',
title: 'JavaScript Debug Terminal'
};
-
+let powershellPick = { label: 'Powershell', profile: powershellProfile, profileName: powershellProfile.profileName };
+let jsdebugPick = { label: 'Javascript Debug Terminal', profile: jsdebugProfile, profileName: jsdebugProfile.title };
suite('TerminalProfileService', () => {
let configurationService: TestConfigurationService;
@@ -115,6 +160,7 @@ suite('TerminalProfileService', () => {
environmentService = { configuration: {}, remoteAuthority: undefined } as IWorkbenchEnvironmentService;
instantiationService = new TestInstantiationService();
+ let themeService = new TestThemeService();
let terminalContributionService = new TestTerminalContributionService();
let contextKeyService = new MockContextKeyService();
@@ -125,6 +171,7 @@ suite('TerminalProfileService', () => {
instantiationService.stub(ITerminalContributionService, terminalContributionService);
instantiationService.stub(ITerminalInstanceService, terminalInstanceService);
instantiationService.stub(IWorkbenchEnvironmentService, environmentService);
+ instantiationService.stub(IThemeService, themeService);
terminalProfileService = instantiationService.createInstance(TestTerminalProfileService);
@@ -283,4 +330,62 @@ suite('TerminalProfileService', () => {
deepStrictEqual(terminalProfileService.availableProfiles, [powershellProfile]);
deepStrictEqual(terminalProfileService.contributedProfiles, [jsdebugProfile]);
});
+ suite('Profiles Quickpick', () => {
+ let quickInputService: MockQuickInputService;
+ let mockTerminalProfileService: MockTerminalProfileService;
+ let terminalProfileQuickpick: TestTerminalProfileQuickpick;
+ setup(async () => {
+ quickInputService = new MockQuickInputService();
+ mockTerminalProfileService = new MockTerminalProfileService();
+ instantiationService.stub(IQuickInputService, quickInputService);
+ instantiationService.stub(ITerminalProfileService, mockTerminalProfileService);
+ terminalProfileQuickpick = instantiationService.createInstance(TestTerminalProfileQuickpick);
+ });
+ test('setDefault', async () => {
+ powershellProfile.isDefault = false;
+ mockTerminalProfileService.setProfiles([powershellProfile], [jsdebugProfile]);
+ mockTerminalProfileService.setDefaultProfileName(jsdebugProfile.title);
+ const result = await terminalProfileQuickpick.showAndGetResult('setDefault');
+ deepStrictEqual(result, powershellProfile.profileName);
+ });
+ test('setDefault to contributed', async () => {
+ mockTerminalProfileService.setDefaultProfileName(powershellProfile.profileName);
+ quickInputService.setPick(jsdebugPick);
+ const result = await terminalProfileQuickpick.showAndGetResult('setDefault');
+ const expected = {
+ config: {
+ extensionIdentifier: jsdebugProfile.extensionIdentifier,
+ id: jsdebugProfile.id,
+ options: { color: undefined, icon: 'debug' },
+ title: jsdebugProfile.title,
+ },
+ keyMods: undefined
+ };
+ deepStrictEqual(result, expected);
+ });
+
+ test('createInstance', async () => {
+ mockTerminalProfileService.setDefaultProfileName(powershellProfile.profileName);
+ const pick = { ...powershellPick, keyMods: { alt: true, ctrlCmd: false } };
+ quickInputService.setPick(pick);
+ const result = await terminalProfileQuickpick.showAndGetResult('createInstance');
+ deepStrictEqual(result, { config: powershellProfile, keyMods: { alt: true, ctrlCmd: false } });
+ });
+
+ test('createInstance with contributed', async () => {
+ const pick = { ...jsdebugPick, keyMods: { alt: true, ctrlCmd: false } };
+ quickInputService.setPick(pick);
+ const result = await terminalProfileQuickpick.showAndGetResult('createInstance');
+ const expected = {
+ config: {
+ extensionIdentifier: jsdebugProfile.extensionIdentifier,
+ id: jsdebugProfile.id,
+ options: { color: undefined, icon: 'debug' },
+ title: jsdebugProfile.title,
+ },
+ keyMods: { alt: true, ctrlCmd: false }
+ };
+ deepStrictEqual(result, expected);
+ });
+ });
});
diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts
index 26efb1ed53e..32e53a531b8 100644
--- a/src/vs/workbench/contrib/webview/browser/webview.ts
+++ b/src/vs/workbench/contrib/webview/browser/webview.ts
@@ -16,10 +16,18 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { IWebviewPortMapping } from 'vs/platform/webview/common/webviewPortMapping';
/**
- * Set when the find widget in a webview is visible.
+ * Set when the find widget in a webview in a webview is visible.
*/
export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('webviewFindWidgetVisible', false);
+
+/**
+ * Set when the find widget in a webview is focused.
+ */
export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('webviewFindWidgetFocused', false);
+
+/**
+ * Set when the find widget in a webview is enabled in a webview
+ */
export const KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED = new RawContextKey<boolean>('webviewFindWidgetEnabled', false);
export const IWebviewService = createDecorator<IWebviewService>('webviewService');
@@ -72,27 +80,58 @@ export const enum WebviewContentPurpose {
WebviewView = 'webviewView',
}
-export type WebviewStyles = { [key: string]: string | number; };
+export type WebviewStyles = { readonly [key: string]: string | number; };
export interface WebviewOptions {
- // The purpose of the webview; this is (currently) only used for filtering in js-debug
+ /**
+ * The purpose of the webview; this is (currently) only used for filtering in js-debug
+ */
readonly purpose?: WebviewContentPurpose;
readonly customClasses?: string;
readonly enableFindWidget?: boolean;
readonly tryRestoreScrollPosition?: boolean;
readonly retainContextWhenHidden?: boolean;
- transformCssVariables?(styles: Readonly<WebviewStyles>): Readonly<WebviewStyles>;
+ transformCssVariables?(styles: WebviewStyles): WebviewStyles;
}
+/**
+ *
+ */
export interface WebviewContentOptions {
+ /**
+ * Should the webview allow `acquireVsCodeApi` to be called multiple times? Defaults to false.
+ */
readonly allowMultipleAPIAcquire?: boolean;
+
+ /**
+ * Should scripts be enabled in the webview? Defaults to false.
+ */
readonly allowScripts?: boolean;
+
+ /**
+ * Should forms be enabled in the webview? Defaults to the value of {@link allowScripts}.
+ */
readonly allowForms?: boolean;
- readonly localResourceRoots?: ReadonlyArray<URI>;
- readonly portMapping?: ReadonlyArray<IWebviewPortMapping>;
+
+ /**
+ * Set of root paths from which the webview can load local resources.
+ */
+ readonly localResourceRoots?: readonly URI[];
+
+ /**
+ * Set of localhost port mappings to apply inside the webview.
+ */
+ readonly portMapping?: readonly IWebviewPortMapping[];
+
+ /**
+ * Are command uris enabled in the webview? Defaults to false.
+ */
readonly enableCommandUris?: boolean;
}
+/**
+ * Check if two {@link WebviewContentOptions} are equal.
+ */
export function areWebviewContentOptionsEqual(a: WebviewContentOptions, b: WebviewContentOptions): boolean {
return (
a.allowMultipleAPIAcquire === b.allowMultipleAPIAcquire
@@ -110,8 +149,8 @@ export interface WebviewExtensionDescription {
}
export interface IDataLinkClickEvent {
- dataURL: string;
- downloadName?: string;
+ readonly dataURL: string;
+ readonly downloadName?: string;
}
export interface WebviewMessageReceivedEvent {
@@ -137,7 +176,7 @@ export interface IWebview extends IDisposable {
readonly onDidDispose: Event<void>;
readonly onDidClickLink: Event<string>;
- readonly onDidScroll: Event<{ scrollYPercentage: number }>;
+ readonly onDidScroll: Event<{ readonly scrollYPercentage: number }>;
readonly onDidWheel: Event<IMouseWheelEvent>;
readonly onDidUpdateState: Event<string | undefined>;
readonly onDidReload: Event<void>;
diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css
index 26d4d8a30db..85b0163d359 100644
--- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css
+++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css
@@ -717,6 +717,8 @@
.monaco-workbench .part.editor>.content .gettingStartedContainer .gettingStartedSlide .openAWalkthrough>button, .monaco-workbench .part.editor>.content .gettingStartedContainer .gettingStartedSlide .showOnStartup {
text-align: center;
+ display: flex;
+ justify-content: center;
}
.monaco-workbench .part.editor>.content .gettingStartedContainer .gettingStartedSlide .getting-started-checkbox {
diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts
index 62c5ac5b7fb..2218e71c907 100644
--- a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts
+++ b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts
@@ -9,7 +9,7 @@ import { localize } from 'vs/nls';
import { Codicon } from 'vs/base/common/codicons';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
-import { OpenGettingStarted } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const setupIcon = registerIcon('getting-started-setup', Codicon.zap, localize('getting-started-setup-icon', "Icon used for the setup category of welcome page"));
@@ -483,7 +483,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
description: '',
icon: setupIcon,
isFeatured: false,
- when: `config.${OpenGettingStarted} && userHasOpenedNotebook`,
+ when: `config.${NotebookSetting.openGettingStarted} && userHasOpenedNotebook`,
content: {
type: 'steps',
steps: [
diff --git a/src/vs/workbench/electron-sandbox/parts/dialogs/dialogHandler.ts b/src/vs/workbench/electron-sandbox/parts/dialogs/dialogHandler.ts
index 40094f38189..a4728e73b7d 100644
--- a/src/vs/workbench/electron-sandbox/parts/dialogs/dialogHandler.ts
+++ b/src/vs/workbench/electron-sandbox/parts/dialogs/dialogHandler.ts
@@ -166,8 +166,8 @@ export class NativeDialogHandler implements IDialogHandler {
const osProps = await this.nativeHostService.getOSProperties();
const detailString = (useAgo: boolean): string => {
- return localize({ key: 'aboutDetail', comment: ['Electron, Chrome, Node.js and V8 are product names that need no translation'] },
- "Version: {0}\nCommit: {1}\nDate: {2}\nElectron: {3}\nChrome: {4}\nNode.js: {5}\nV8: {6}\nOS: {7}",
+ return localize({ key: 'aboutDetail', comment: ['Electron, Chromium, Node.js and V8 are product names that need no translation'] },
+ "Version: {0}\nCommit: {1}\nDate: {2}\nElectron: {3}\nChromium: {4}\nNode.js: {5}\nV8: {6}\nOS: {7}",
version,
this.productService.commit || 'Unknown',
this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts
index 29b74dbc6a4..777123794b1 100644
--- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts
+++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts
@@ -362,6 +362,8 @@ export class LocalProcessExtensionHost implements IExtensionHost {
let startupTimeoutHandle: any;
if (!this._environmentService.isBuilt && !this._environmentService.remoteAuthority || this._isExtensionDevHost) {
startupTimeoutHandle = setTimeout(() => {
+ this._logService.error(`[LocalProcessExtensionHost]: Extension host did not start in 10 seconds (debugBrk: ${this._isExtensionDevDebugBrk})`);
+
const msg = this._isExtensionDevDebugBrk
? nls.localize('extensionHost.startupFailDebug', "Extension host did not start in 10 seconds, it might be stopped on the first line and needs a debugger to continue.")
: nls.localize('extensionHost.startupFail', "Extension host did not start in 10 seconds, that might be a problem.");
diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts
index f2b6d8c39eb..bad2c3faee7 100644
--- a/src/vs/workbench/services/preferences/common/preferences.ts
+++ b/src/vs/workbench/services/preferences/common/preferences.ts
@@ -28,7 +28,7 @@ export enum SettingValueType {
Integer = 'integer',
Number = 'number',
Boolean = 'boolean',
- StringOrEnumArray = 'string-or-enum-array',
+ Array = 'array',
Exclude = 'exclude',
Complex = 'complex',
NullableInteger = 'nullable-integer',
diff --git a/src/vs/workbench/services/preferences/common/preferencesValidation.ts b/src/vs/workbench/services/preferences/common/preferencesValidation.ts
index c991e059885..b722a3cee43 100644
--- a/src/vs/workbench/services/preferences/common/preferencesValidation.ts
+++ b/src/vs/workbench/services/preferences/common/preferencesValidation.ts
@@ -26,15 +26,15 @@ export function createValidator(prop: IConfigurationPropertySchema): (value: any
const numericValidations = getNumericValidators(prop);
const stringValidations = getStringValidators(prop);
- const stringArrayValidator = getArrayOfStringValidator(prop);
+ const arrayValidator = getArrayValidator(prop);
const objectValidator = getObjectValidator(prop);
return value => {
if (isNullable && isNullOrEmpty(value)) { return ''; }
const errors: string[] = [];
- if (stringArrayValidator) {
- const err = stringArrayValidator(value);
+ if (arrayValidator) {
+ const err = arrayValidator(value);
if (err) {
errors.push(err);
}
@@ -52,7 +52,7 @@ export function createValidator(prop: IConfigurationPropertySchema): (value: any
}
if (isNumeric) {
- if (isNullOrEmpty(value) || isNaN(+value)) {
+ if (isNullOrEmpty(value) || typeof value === 'boolean' || Array.isArray(value) || isNaN(+value)) {
errors.push(nls.localize('validations.expectedNumeric', "Value must be a number."));
} else {
errors.push(...numericValidations.filter(validator => !validator.isValid(+value)).map(validator => validator.message));
@@ -205,7 +205,6 @@ function getNumericValidators(prop: IConfigurationPropertySchema): Validator<num
isValid: ((value: number) => value > exclusiveMin!),
message: nls.localize('validations.exclusiveMin', "Value must be strictly greater than {0}.", exclusiveMin)
},
-
{
enabled: prop.maximum !== undefined && (exclusiveMax === undefined || exclusiveMax > prop.maximum),
isValid: ((value: number) => value <= prop.maximum!),
@@ -229,10 +228,10 @@ function getNumericValidators(prop: IConfigurationPropertySchema): Validator<num
].filter(validation => validation.enabled);
}
-function getArrayOfStringValidator(prop: IConfigurationPropertySchema): ((value: any) => (string | null)) | null {
- if (prop.type === 'array' && prop.items && !isArray(prop.items) && prop.items.type === 'string') {
+function getArrayValidator(prop: IConfigurationPropertySchema): ((value: any) => (string | null)) | null {
+ if (prop.type === 'array' && prop.items && !isArray(prop.items)) {
const propItems = prop.items;
- if (propItems && !isArray(propItems) && propItems.type === 'string') {
+ if (propItems && !isArray(propItems.type)) {
const withQuotes = (s: string) => `'` + s + `'`;
return value => {
if (!value) {
@@ -241,58 +240,72 @@ function getArrayOfStringValidator(prop: IConfigurationPropertySchema): ((value:
let message = '';
- if (!isStringArray(value)) {
- message += nls.localize('validations.stringArrayIncorrectType', 'Incorrect type. Expected a string array.');
+ if (!isArray(value)) {
+ message += nls.localize('validations.arrayIncorrectType', 'Incorrect type. Expected an array.');
message += '\n';
return message;
}
- const stringArrayValue = value;
-
+ const arrayValue = value as unknown[];
if (prop.uniqueItems) {
- if (new Set(stringArrayValue).size < stringArrayValue.length) {
+ if (new Set(arrayValue).size < arrayValue.length) {
message += nls.localize('validations.stringArrayUniqueItems', 'Array has duplicate items');
message += '\n';
}
}
- if (prop.minItems && stringArrayValue.length < prop.minItems) {
+ if (prop.minItems && arrayValue.length < prop.minItems) {
message += nls.localize('validations.stringArrayMinItem', 'Array must have at least {0} items', prop.minItems);
message += '\n';
}
- if (prop.maxItems && stringArrayValue.length > prop.maxItems) {
+ if (prop.maxItems && arrayValue.length > prop.maxItems) {
message += nls.localize('validations.stringArrayMaxItem', 'Array must have at most {0} items', prop.maxItems);
message += '\n';
}
- if (typeof propItems.pattern === 'string') {
- const patternRegex = new RegExp(propItems.pattern);
- stringArrayValue.forEach(v => {
- if (!patternRegex.test(v)) {
- message +=
- propItems.patternErrorMessage ||
- nls.localize(
- 'validations.stringArrayItemPattern',
- 'Value {0} must match regex {1}.',
+ if (propItems.type === 'string') {
+ if (!isStringArray(arrayValue)) {
+ message += nls.localize('validations.stringArrayIncorrectType', 'Incorrect type. Expected a string array.');
+ message += '\n';
+ return message;
+ }
+
+ if (typeof propItems.pattern === 'string') {
+ const patternRegex = new RegExp(propItems.pattern);
+ arrayValue.forEach(v => {
+ if (!patternRegex.test(v)) {
+ message +=
+ propItems.patternErrorMessage ||
+ nls.localize(
+ 'validations.stringArrayItemPattern',
+ 'Value {0} must match regex {1}.',
+ withQuotes(v),
+ withQuotes(propItems.pattern!)
+ );
+ }
+ });
+ }
+
+ const propItemsEnum = propItems.enum;
+ if (propItemsEnum) {
+ arrayValue.forEach(v => {
+ if (propItemsEnum.indexOf(v) === -1) {
+ message += nls.localize(
+ 'validations.stringArrayItemEnum',
+ 'Value {0} is not one of {1}',
withQuotes(v),
- withQuotes(propItems.pattern!)
+ '[' + propItemsEnum.map(withQuotes).join(', ') + ']'
);
- }
- });
- }
-
- const propItemsEnum = propItems.enum;
- if (propItemsEnum) {
- stringArrayValue.forEach(v => {
- if (propItemsEnum.indexOf(v) === -1) {
- message += nls.localize(
- 'validations.stringArrayItemEnum',
- 'Value {0} is not one of {1}',
- withQuotes(v),
- '[' + propItemsEnum.map(withQuotes).join(', ') + ']'
- );
- message += '\n';
+ message += '\n';
+ }
+ });
+ }
+ } else if (propItems.type === 'integer' || propItems.type === 'number') {
+ arrayValue.forEach(v => {
+ const errorMessage = getErrorsForSchema(propItems, v);
+ if (errorMessage) {
+ message += `${v}: ${errorMessage}\n`;
}
});
}
diff --git a/src/vs/workbench/services/preferences/test/common/preferencesValidation.test.ts b/src/vs/workbench/services/preferences/test/common/preferencesValidation.test.ts
index 0ee46bad8e7..a849aa2f780 100644
--- a/src/vs/workbench/services/preferences/test/common/preferencesValidation.test.ts
+++ b/src/vs/workbench/services/preferences/test/common/preferencesValidation.test.ts
@@ -279,6 +279,31 @@ suite('Preferences Validation', () => {
}
});
+ test('numerical objects work', () => {
+ {
+ const obj = new Tester({ type: 'object', properties: { 'b': { type: 'number' } } });
+ obj.accepts({ 'b': 2.5 });
+ obj.accepts({ 'b': -2.5 });
+ obj.accepts({ 'b': 0 });
+ obj.accepts({ 'b': '0.12' });
+ obj.rejects({ 'b': 'abc' });
+ obj.rejects({ 'b': [] });
+ obj.rejects({ 'b': false });
+ obj.rejects({ 'b': null });
+ obj.rejects({ 'b': undefined });
+ }
+ {
+ const obj = new Tester({ type: 'object', properties: { 'b': { type: 'integer', minimum: 2, maximum: 5.5 } } });
+ obj.accepts({ 'b': 2 });
+ obj.accepts({ 'b': 3 });
+ obj.accepts({ 'b': '3.0' });
+ obj.accepts({ 'b': 5 });
+ obj.rejects({ 'b': 1 });
+ obj.rejects({ 'b': 6 });
+ obj.rejects({ 'b': 5.5 });
+ }
+ });
+
test('patterns work', () => {
{
const urls = new Tester({ pattern: '^(hello)*$', type: 'string' });
@@ -312,7 +337,7 @@ suite('Preferences Validation', () => {
this.validator = createValidator(settings)!;
}
- public accepts(input: string[]) {
+ public accepts(input: unknown[]) {
assert.strictEqual(this.validator(input), '', `Expected ${JSON.stringify(this.settings)} to accept \`${JSON.stringify(input)}\`. Got ${this.validator(input)}.`);
}
@@ -365,6 +390,39 @@ suite('Preferences Validation', () => {
}
});
+ test('array of numbers', () => {
+ // We accept parseable strings since the view handles strings
+ {
+ const arr = new ArrayTester({ type: 'array', items: { type: 'number' } });
+ arr.accepts([]);
+ arr.accepts([2]);
+ arr.accepts([2, 3]);
+ arr.accepts(['2', '3']);
+ arr.accepts([6.6, '3', 7]);
+ arr.rejects(76);
+ arr.rejects(7.6);
+ arr.rejects([6, 'a', 7]);
+ }
+ {
+ const arr = new ArrayTester({ type: 'array', items: { type: 'integer', minimum: -2, maximum: 3 }, maxItems: 4 });
+ arr.accepts([]);
+ arr.accepts([-2, 3]);
+ arr.accepts([2, 3]);
+ arr.accepts(['2', '3']);
+ arr.accepts(['-2', '0', '3']);
+ arr.accepts(['-2', 0.0, '3']);
+ arr.rejects(2);
+ arr.rejects(76);
+ arr.rejects([6, '3', 7]);
+ arr.rejects([2, 'a', 3]);
+ arr.rejects([-2, 4]);
+ arr.rejects([-1.2, 2.1]);
+ arr.rejects([-3, 3]);
+ arr.rejects([-3, 4]);
+ arr.rejects([2, 2, 2, 2, 2]);
+ }
+ });
+
test('min-max and enum', () => {
const arr = new ArrayTester({ type: 'array', items: { type: 'string', enum: ['a', 'b'] }, minItems: 1, maxItems: 2 });
diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts
index 667b02954c4..d156f7dfea1 100644
--- a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts
+++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts
@@ -657,8 +657,10 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
if (this._cachedCurrentSessionId !== cachedSessionId) {
this._cachedCurrentSessionId = cachedSessionId;
if (cachedSessionId === undefined) {
+ this.logService.info('Settings Sync: Reset current session');
this.storageService.remove(UserDataSyncWorkbenchService.CACHED_SESSION_STORAGE_KEY, StorageScope.GLOBAL);
} else {
+ this.logService.info('Settings Sync: Updated current session', cachedSessionId);
this.storageService.store(UserDataSyncWorkbenchService.CACHED_SESSION_STORAGE_KEY, cachedSessionId, StorageScope.GLOBAL, StorageTarget.MACHINE);
}
}
diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts
index 02f02c68f19..6ee7e8240d8 100644
--- a/src/vscode-dts/vscode.d.ts
+++ b/src/vscode-dts/vscode.d.ts
@@ -1672,6 +1672,12 @@ declare module 'vscode' {
* Always show this item.
*/
alwaysShow?: boolean;
+
+ /**
+ * Optional buttons that will be rendered on this particular item. These buttons will trigger
+ * an {@link QuickPickItemButtonEvent} when clicked.
+ */
+ buttons?: readonly QuickInputButton[];
}
/**
@@ -5657,6 +5663,13 @@ declare module 'vscode' {
appendLine(value: string): void;
/**
+ * Replaces all output from the channel with the given value.
+ *
+ * @param value A string, falsy values will not be printed.
+ */
+ replace(value: string): void;
+
+ /**
* Removes all output from the channel.
*/
clear(): void;
@@ -10193,6 +10206,12 @@ declare module 'vscode' {
readonly onDidTriggerButton: Event<QuickInputButton>;
/**
+ * An event signaling when a button in a particular {@link QuickPickItem} was triggered.
+ * This event does not fire for buttons in the title bar.
+ */
+ readonly onDidTriggerItemButton: Event<QuickPickItemButtonEvent<T>>;
+
+ /**
* Items to pick from. This can be read and updated by the extension.
*/
items: readonly T[];
@@ -10212,6 +10231,11 @@ declare module 'vscode' {
*/
matchOnDetail: boolean;
+ /*
+ * An optional flag to maintain the scroll position of the quick pick when the quick pick items are updated. Defaults to false.
+ */
+ keepScrollPosition?: boolean;
+
/**
* Active items. This can be read and updated by the extension.
*/
@@ -10324,6 +10348,21 @@ declare module 'vscode' {
}
/**
+ * An event signaling when a button in a particular {@link QuickPickItem} was triggered.
+ * This event does not fire for buttons in the title bar.
+ */
+ export interface QuickPickItemButtonEvent<T extends QuickPickItem> {
+ /**
+ * The button that was clicked.
+ */
+ readonly button: QuickInputButton;
+ /**
+ * The item that the button belongs to.
+ */
+ readonly item: T;
+ }
+
+ /**
* An event describing an individual change in the text of a {@link TextDocument document}.
*/
export interface TextDocumentContentChangeEvent {
@@ -13849,6 +13888,17 @@ declare module 'vscode' {
*/
export interface AuthenticationGetSessionOptions {
/**
+ * Whether the existing user session preference should be cleared.
+ *
+ * For authentication providers that support being signed into multiple accounts at once, the user will be
+ * prompted to select an account to use when {@link authentication.getSession getSession} is called. This preference
+ * is remembered until {@link authentication.getSession getSession} is called with this flag.
+ *
+ * Defaults to false.
+ */
+ clearSessionPreference?: boolean;
+
+ /**
* Whether login should be performed if there is no matching session.
*
* If true, a modal dialog will be shown asking the user to sign in. If false, a numbered badge will be shown
@@ -13859,19 +13909,23 @@ declare module 'vscode' {
* will also result in an immediate modal dialog, and false will add a numbered badge to the accounts icon.
*
* Defaults to false.
+ *
+ * Note: you cannot use this option with {@link silent}.
*/
createIfNone?: boolean;
+
/**
- * Whether the existing user session preference should be cleared.
+ * Whether we should show the indication to sign in in the Accounts menu.
*
- * For authentication providers that support being signed into multiple accounts at once, the user will be
- * prompted to select an account to use when {@link authentication.getSession getSession} is called. This preference
- * is remembered until {@link authentication.getSession getSession} is called with this flag.
+ * If false, the user will be shown a badge on the Accounts menu with an option to sign in for the extension.
+ * If true, no indication will be shown.
*
* Defaults to false.
+ *
+ * Note: you cannot use this option with any other options that prompt the user like {@link createIfNone}.
*/
- clearSessionPreference?: boolean;
+ silent?: boolean;
}
/**
diff --git a/src/vscode-dts/vscode.proposed.d.ts b/src/vscode-dts/vscode.proposed.d.ts
index f5f1304f3d9..9ee5a94af5d 100644
--- a/src/vscode-dts/vscode.proposed.d.ts
+++ b/src/vscode-dts/vscode.proposed.d.ts
@@ -16,8 +16,7 @@
declare module 'vscode' {
- // eslint-disable-next-line vscode-dts-region-comments
- //#region @alexdima - resolvers
+ //#region resolvers: @alexdima
export interface MessageOptions {
/**
@@ -184,15 +183,6 @@ declare module 'vscode' {
* Defaults to false.
*/
forceNewSession?: boolean | { detail: string };
- /**
- * Whether we should show the indication to sign in in the Accounts menu.
- *
- * If false, the user will be shown a badge on the Accounts menu with an option to sign in for the extension.
- * If true, no indication will be shown.
- *
- * Defaults to false.
- */
- silent?: boolean;
}
export namespace authentication {
@@ -277,7 +267,7 @@ declare module 'vscode' {
//#endregion
- //#region editor insets: https://github.com/microsoft/vscode/issues/85682
+ //#region editorInsets: https://github.com/microsoft/vscode/issues/85682
export interface WebviewEditorInset {
readonly editor: TextEditor;
@@ -294,7 +284,7 @@ declare module 'vscode' {
//#endregion
- //#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515
+ //#region fsChunks: https://github.com/microsoft/vscode/issues/84515
export interface FileSystemProvider {
open?(resource: Uri, options: { create: boolean; }): number | Thenable<number>;
@@ -305,7 +295,7 @@ declare module 'vscode' {
//#endregion
- //#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921
+ //#region textSearchProvider: https://github.com/microsoft/vscode/issues/59921
/**
* The parameters of a query for text search.
@@ -562,7 +552,7 @@ declare module 'vscode' {
//#endregion
- //#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524
+ //#region fileSearchProvider: https://github.com/microsoft/vscode/issues/73524
/**
* The parameters of a query for file search.
@@ -728,7 +718,7 @@ declare module 'vscode' {
//#endregion
- //#region diff command: https://github.com/microsoft/vscode/issues/84899
+ //#region diffCommand: https://github.com/microsoft/vscode/issues/84899
/**
* The contiguous set of modified lines in a diff.
@@ -805,8 +795,7 @@ declare module 'vscode' {
//#endregion
- // eslint-disable-next-line vscode-dts-region-comments
- //#region @joaomoreno: SCM validation
+ // #region scmValidation: @joaomoreno:
/**
* Represents the validation type of the Source Control input.
@@ -861,8 +850,7 @@ declare module 'vscode' {
//#endregion
- // eslint-disable-next-line vscode-dts-region-comments
- //#region @joaomoreno: SCM selected provider
+ //#region scmSelectedProvider: @joaomoreno:
export interface SourceControl {
@@ -879,7 +867,7 @@ declare module 'vscode' {
//#endregion
- //#region Terminal data write event https://github.com/microsoft/vscode/issues/78502
+ //#region terminalDataWriteEvent: https://github.com/microsoft/vscode/issues/78502
export interface TerminalDataWriteEvent {
/**
@@ -903,7 +891,7 @@ declare module 'vscode' {
//#endregion
- //#region Terminal dimensions property and change event https://github.com/microsoft/vscode/issues/55718
+ //#region terminalDimensions: https://github.com/microsoft/vscode/issues/55718
/**
* An {@link Event} which fires when a {@link Terminal}'s dimensions change.
@@ -937,7 +925,7 @@ declare module 'vscode' {
//#endregion
- //#region Terminal location https://github.com/microsoft/vscode/issues/45407
+ //#region terminalLocation: https://github.com/microsoft/vscode/issues/45407
export interface TerminalOptions {
location?: TerminalLocation | TerminalEditorLocationOptions | TerminalSplitLocationOptions;
@@ -977,7 +965,7 @@ declare module 'vscode' {
//#endregion
- //#region Terminal name change event https://github.com/microsoft/vscode/issues/114898
+ //#region terminalNameChangeEvent: https://github.com/microsoft/vscode/issues/114898
export interface Pseudoterminal {
/**
@@ -1001,8 +989,7 @@ declare module 'vscode' {
//#endregion
- // eslint-disable-next-line vscode-dts-region-comments
- //#region @jrieken -> exclusive document filters
+ //#region exclusiveDocumentFilters: @jrieken
export interface DocumentFilter {
readonly exclusive?: boolean;
@@ -1010,13 +997,13 @@ declare module 'vscode' {
//#endregion
- //#region Tree View: https://github.com/microsoft/vscode/issues/61313 @alexr00
+ //#region treeViewReveal: https://github.com/microsoft/vscode/issues/61313 @alexr00
export interface TreeView<T> extends Disposable {
reveal(element: T | undefined, options?: { select?: boolean, focus?: boolean, expand?: boolean | number; }): Thenable<void>;
}
//#endregion
- //#region Custom Tree View Drag and Drop https://github.com/microsoft/vscode/issues/32592
+ //#region treeViewDragAndDrop: https://github.com/microsoft/vscode/issues/32592
/**
* A data provider that provides tree data
*/
@@ -1080,7 +1067,7 @@ declare module 'vscode' {
}
//#endregion
- //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265
+ //#region taskPresentationGroup: https://github.com/microsoft/vscode/issues/47265
export interface TaskPresentationOptions {
/**
* Controls whether the task is executed in a specific terminal group using split panes.
@@ -1094,7 +1081,7 @@ declare module 'vscode' {
}
//#endregion
- //#region Custom editor move https://github.com/microsoft/vscode/issues/86146
+ //#region customEditorMove: https://github.com/microsoft/vscode/issues/86146
// TODO: Also for custom editor
@@ -1118,7 +1105,7 @@ declare module 'vscode' {
//#endregion
- //#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904
+ //#region quickPickSortByLabel: https://github.com/microsoft/vscode/issues/73904
export interface QuickPick<T extends QuickPickItem> extends QuickInput {
/**
@@ -1129,19 +1116,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/132068
-
- export interface QuickPick<T extends QuickPickItem> extends QuickInput {
-
- /*
- * An optional flag to maintain the scroll position of the quick pick when the quick pick items are updated. Defaults to false.
- */
- keepScrollPosition?: boolean;
- }
-
- //#endregion
-
- //#region https://github.com/microsoft/vscode/issues/124970, Cell Execution State
+ //#region notebookCellExecutionState: https://github.com/microsoft/vscode/issues/124970
/**
* The execution state of a notebook cell.
@@ -1188,7 +1163,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, Notebook, deprecated & misc
+ //#region notebookDeprecated: https://github.com/microsoft/vscode/issues/106744
export interface NotebookCellOutput {
id: string;
@@ -1196,7 +1171,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, NotebookEditor
+ //#region notebookEditor: https://github.com/microsoft/vscode/issues/106744
/**
* Represents a notebook editor that is attached to a {@link NotebookDocument notebook}.
@@ -1361,7 +1336,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, NotebookEditorEdit
+ //#region notebookEditorEdit: https://github.com/microsoft/vscode/issues/106744
// todo@API add NotebookEdit-type which handles all these cases?
// export class NotebookEdit {
@@ -1409,7 +1384,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, NotebookEditorDecorationType
+ //#region notebookEditorDecorationType: https://github.com/microsoft/vscode/issues/106744
export interface NotebookEditor {
setDecorations(decorationType: NotebookEditorDecorationType, range: NotebookRange): void;
@@ -1432,7 +1407,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, NotebookConcatTextDocument
+ //#region notebookConcatTextDocument: https://github.com/microsoft/vscode/issues/106744
export namespace notebooks {
/**
@@ -1467,8 +1442,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, NotebookContentProvider
-
+ //#region notebookContentProvider: https://github.com/microsoft/vscode/issues/106744
interface NotebookDocumentBackup {
/**
@@ -1528,7 +1502,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/106744, LiveShare
+ //#region notebookLiveShare: https://github.com/microsoft/vscode/issues/106744
export interface NotebookRegistrationData {
displayName: string;
@@ -1545,7 +1519,7 @@ declare module 'vscode' {
//#endregion
- //#region @https://github.com/microsoft/vscode/issues/123601, notebook messaging
+ //#region notebookMessaging: https://github.com/microsoft/vscode/issues/123601
/**
* Represents a script that is loaded into the notebook renderer before rendering output. This allows
@@ -1612,7 +1586,7 @@ declare module 'vscode' {
//#endregion
- //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297
+ //#region timeline: https://github.com/microsoft/vscode/issues/84297
export class TimelineItem {
/**
@@ -1770,7 +1744,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/91555
+ //#region tokenInformation: https://github.com/microsoft/vscode/issues/91555
export enum StandardTokenType {
Other = 0,
@@ -1790,7 +1764,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/16221
+ //#region inlayHints: https://github.com/microsoft/vscode/issues/16221
// todo@API Split between Inlay- and OverlayHints (InlayHint are for a position, OverlayHints for a non-empty range)
// todo@API add "mini-markdown" for links and styles
@@ -1873,7 +1847,7 @@ declare module 'vscode' {
}
//#endregion
- //#region https://github.com/microsoft/vscode/issues/104436
+ //#region extensionRuntime: https://github.com/microsoft/vscode/issues/104436
export enum ExtensionRuntime {
/**
@@ -1892,7 +1866,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/102091
+ //#region textDocumentNotebook: https://github.com/microsoft/vscode/issues/102091
export interface TextDocument {
@@ -1904,6 +1878,8 @@ declare module 'vscode' {
}
//#endregion
+ // TODO: @connor4312 split this up
+ // eslint-disable-next-line vscode-dts-region-comments
//#region proposed test APIs https://github.com/microsoft/vscode/issues/107467
export namespace tests {
/**
@@ -2100,7 +2076,7 @@ declare module 'vscode' {
//#endregion
- //#region Opener service (https://github.com/microsoft/vscode/issues/109277)
+ //#region externalUriOpener: https://github.com/microsoft/vscode/issues/109277
/**
* Details if an `ExternalUriOpener` can open a uri.
@@ -2258,7 +2234,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/Microsoft/vscode/issues/15178
+ //#region tabs: https://github.com/Microsoft/vscode/issues/15178
/**
* Represents a tab within the window
@@ -2353,7 +2329,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/120173
+ //#region workspaceTrust: https://github.com/microsoft/vscode/issues/120173
/**
* The object describing the properties of the workspace trust request
*/
@@ -2377,7 +2353,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/115616 @alexr00
+ //#region portAttributesProvider: https://github.com/microsoft/vscode/issues/115616 @alexr00
export enum PortAutoForwardAction {
Notify = 1,
OpenBrowser = 2,
@@ -2432,19 +2408,7 @@ declare module 'vscode' {
}
//#endregion
- //#region https://github.com/microsoft/vscode/issues/119904 @eamodio
-
- export interface SourceControlInputBox {
-
- /**
- * Sets focus to the input.
- */
- focus(): void;
- }
-
- //#endregion
-
- //#region https://github.com/microsoft/vscode/issues/124024 @hediet @alexdima
+ //#region inlineCompletionProvider: https://github.com/microsoft/vscode/issues/124024 @hediet @alexdima
export namespace languages {
/**
@@ -2566,7 +2530,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/126280 @mjbvz
+ //#region notebookMime: https://github.com/microsoft/vscode/issues/126280 @mjbvz
export interface NotebookCellData {
/**
@@ -2594,7 +2558,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/123713 @connor4312
+ //#region testCoverage: https://github.com/microsoft/vscode/issues/123713 @connor4312
export interface TestRun {
/**
* Test coverage provider for this result. An extension can defer setting
@@ -2785,7 +2749,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/129037
+ //#region languageStatus: https://github.com/microsoft/vscode/issues/129037
enum LanguageStatusSeverity {
Information = 0,
@@ -2812,21 +2776,7 @@ declare module 'vscode' {
//#endregion
- //#region https://github.com/microsoft/vscode/issues/88716
- export interface QuickPickItem {
- buttons?: QuickInputButton[];
- }
- export interface QuickPick<T extends QuickPickItem> extends QuickInput {
- readonly onDidTriggerItemButton: Event<QuickPickItemButtonEvent<T>>;
- }
- export interface QuickPickItemButtonEvent<T extends QuickPickItem> {
- button: QuickInputButton;
- item: T;
- }
-
- //#endregion
-
- //#region @eamodio https://github.com/microsoft/vscode/issues/133935
+ //#region scmActionButton: https://github.com/microsoft/vscode/issues/133935
export interface SourceControl {
actionButton?: Command;
@@ -2834,14 +2784,4 @@ declare module 'vscode' {
//#endregion
- //#region @sandy081 https://github.com/microsoft/vscode/issues/132183
-
- export interface OutputChannel {
- /*
- * Replaces the existing contents of the channel with the given value.
- */
- replace(value: string): void;
- }
-
- //#endregion
}
diff --git a/test/automation/src/code.ts b/test/automation/src/code.ts
index aa67c834e0d..6f7a8a7e9ee 100644
--- a/test/automation/src/code.ts
+++ b/test/automation/src/code.ts
@@ -128,6 +128,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
const env = { ...process.env };
const codePath = options.codePath;
+ const logsPath = path.join(repoPath, '.build', 'logs', options.remote ? 'smoke-tests-remote' : 'smoke-tests');
const outPath = codePath ? getBuildOutPath(codePath) : getDevOutPath();
const args = [
@@ -142,7 +143,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
'--disable-workspace-trust',
`--extensions-dir=${options.extensionsPath}`,
`--user-data-dir=${options.userDataDir}`,
- `--logsPath=${path.join(repoPath, '.build', 'logs', 'smoke-tests')}`,
+ `--logsPath=${logsPath}`,
'--driver', handle
];
@@ -170,6 +171,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
}
env['TESTRESOLVER_DATA_FOLDER'] = remoteDataDir;
+ env['TESTRESOLVER_LOGS_FOLDER'] = path.join(logsPath, 'server');
}
const spawnOptions: cp.SpawnOptions = { env };
diff --git a/test/smoke/README.md b/test/smoke/README.md
index 93e35e4c1f7..84c2030a336 100644
--- a/test/smoke/README.md
+++ b/test/smoke/README.md
@@ -62,6 +62,7 @@ xattr -d com.apple.quarantine <path to server with web folder zip>
- `--verbose` logs all the low level driver calls made to Code;
- `-f PATTERN` (alias `-g PATTERN`) filters the tests to be run. You can also use pretty much any mocha argument;
- `--screenshots SCREENSHOT_DIR` captures screenshots when tests fail.
+- `--headless` will run playwright in headless mode when `--web` is used.
**Note**: you can enable verbose logging of playwright library by setting a `DEBUG` environment variable before running the tests (https://playwright.dev/docs/debug#verbose-api-logs)
diff --git a/test/smoke/src/areas/terminal/terminal-profiles.test.ts b/test/smoke/src/areas/terminal/terminal-profiles.test.ts
new file mode 100644
index 00000000000..17c5d3d3525
--- /dev/null
+++ b/test/smoke/src/areas/terminal/terminal-profiles.test.ts
@@ -0,0 +1,20 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { ParsedArgs } from 'minimist';
+import { Application } from '../../../../automation';
+import { afterSuite, beforeSuite } from '../../utils';
+
+export function setup(opts: ParsedArgs) {
+ describe.skip('Terminal Profiles', () => {
+ beforeSuite(opts);
+ afterSuite(opts);
+
+ it.skip('should launch the default profile', async () => {
+ const app = this.app as Application;
+ console.log(app);
+ });
+ });
+}
diff --git a/test/smoke/src/areas/terminal/terminal-reconnection.test.ts b/test/smoke/src/areas/terminal/terminal-reconnection.test.ts
new file mode 100644
index 00000000000..6a6db40a623
--- /dev/null
+++ b/test/smoke/src/areas/terminal/terminal-reconnection.test.ts
@@ -0,0 +1,20 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { ParsedArgs } from 'minimist';
+import { Application } from '../../../../automation';
+import { afterSuite, beforeSuite } from '../../utils';
+
+export function setup(opts: ParsedArgs) {
+ describe('Terminal Reconnection', () => {
+ beforeSuite(opts);
+ afterSuite(opts);
+
+ it.skip('should reconnect to a single terminal on reload', async () => {
+ const app = this.app as Application;
+ console.log(app);
+ });
+ });
+}
diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts
index b05d6742d01..bae2e43cc51 100644
--- a/test/smoke/src/main.ts
+++ b/test/smoke/src/main.ts
@@ -17,16 +17,17 @@ import { Quality, ApplicationOptions, MultiLogger, Logger, ConsoleLogger, FileLo
import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test';
import { setup as setupDataLossTests } from './areas/workbench/data-loss.test';
-import { setup as setupDataPreferencesTests } from './areas/preferences/preferences.test';
-import { setup as setupDataSearchTests } from './areas/search/search.test';
-import { setup as setupDataNotebookTests } from './areas/notebook/notebook.test';
-import { setup as setupDataLanguagesTests } from './areas/languages/languages.test';
-import { setup as setupDataEditorTests } from './areas/editor/editor.test';
-import { setup as setupDataStatusbarTests } from './areas/statusbar/statusbar.test';
-import { setup as setupDataExtensionTests } from './areas/extensions/extensions.test';
-import { setup as setupDataMultirootTests } from './areas/multiroot/multiroot.test';
-import { setup as setupDataLocalizationTests } from './areas/workbench/localization.test';
+import { setup as setupPreferencesTests } from './areas/preferences/preferences.test';
+import { setup as setupSearchTests } from './areas/search/search.test';
+import { setup as setupNotebookTests } from './areas/notebook/notebook.test';
+import { setup as setupLanguagesTests } from './areas/languages/languages.test';
+import { setup as setupEditorTests } from './areas/editor/editor.test';
+import { setup as setupStatusbarTests } from './areas/statusbar/statusbar.test';
+import { setup as setupExtensionTests } from './areas/extensions/extensions.test';
+import { setup as setupMultirootTests } from './areas/multiroot/multiroot.test';
+import { setup as setupLocalizationTests } from './areas/workbench/localization.test';
import { setup as setupLaunchTests } from './areas/workbench/launch.test';
+import { setup as setupTerminalProfileTests } from './areas/terminal/terminal-profiles.test';
const testDataPath = path.join(os.tmpdir(), 'vscsmoke');
if (fs.existsSync(testDataPath)) {
@@ -162,7 +163,11 @@ if (!opts.web) {
quality = Quality.Stable;
}
- console.log(`Running desktop smoke tests against ${electronPath}`);
+ if (opts.remote) {
+ console.log(`Running desktop remote smoke tests against ${electronPath}`);
+ } else {
+ console.log(`Running desktop smoke tests against ${electronPath}`);
+ }
}
//
@@ -342,14 +347,17 @@ if (!opts.web && opts['build'] && !opts['remote']) {
describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => {
if (!opts.web) { setupDataLossTests(opts); }
- if (!opts.web) { setupDataPreferencesTests(opts); }
- setupDataSearchTests(opts);
- setupDataNotebookTests(opts);
- setupDataLanguagesTests(opts);
- setupDataEditorTests(opts);
- setupDataStatusbarTests(opts);
- setupDataExtensionTests(opts);
- if (!opts.web) { setupDataMultirootTests(opts); }
- if (!opts.web) { setupDataLocalizationTests(opts); }
+ if (!opts.web) { setupPreferencesTests(opts); }
+ setupSearchTests(opts);
+ setupNotebookTests(opts);
+ setupLanguagesTests(opts);
+ setupEditorTests(opts);
+ setupStatusbarTests(opts);
+ setupExtensionTests(opts);
+ if (!opts.web) { setupMultirootTests(opts); }
+ if (!opts.web) { setupLocalizationTests(opts); }
if (!opts.web) { setupLaunchTests(); }
+
+ // TODO: Enable terminal tests for non-web
+ if (opts.web) { setupTerminalProfileTests(opts); }
});
diff --git a/yarn.lock b/yarn.lock
index 5218af6c280..06debad293e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -417,10 +417,10 @@
dependencies:
"@octokit/openapi-types" "^10.2.2"
-"@parcel/watcher@2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.0.tgz#ebe992a4838b35c3da9a568eb95a71cb26ddf551"
- integrity sha512-ByalKmRRXNNAhwZ0X1r0XeIhh1jG8zgdlvjgHk9ZV3YxiersEGNQkwew+RfqJbIL4gOJfvC2ey6lg5kaeRainw==
+"@parcel/watcher@2.0.1":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.1.tgz#ec4bb6c43d9588a1ffd3d2abe6df5b501463c62d"
+ integrity sha512-XegFF4L8sFn1RzU5KKOZxXUuzgOSwd6+X2ez3Cy6MVhYMbiLZ1moceMTqDhuT3N8DNbdumK3zP1wojsIsnX40w==
dependencies:
node-addon-api "^3.2.1"
node-gyp-build "^4.3.0"
@@ -10874,35 +10874,35 @@ xtend@~2.1.1:
dependencies:
object-keys "~0.4.0"
-xterm-addon-search@0.9.0-beta.5:
- version "0.9.0-beta.5"
- resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.5.tgz#e0e60a203d1c9d6c8af933648a46865dba299302"
- integrity sha512-ylfqim0ISBvuuX83LQwgu/06p5GC545QsAo9SssXw03TPpIrcd0zwaVMEnhOftSIzM9EKRRsyx3GbBjgUdiF5w==
-
-xterm-addon-serialize@0.7.0-beta.2:
- version "0.7.0-beta.2"
- resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.2.tgz#ced9f664c74ab88448e7b63850721bc272aa6806"
- integrity sha512-KuSwdx2AAliUv7SvjKYUKHrB7vscbHLv8QsmwSDI3pgL1BpjyLJ8LR99iFFfuNpPW9CG4TX6adKPIJXtqiN3Vg==
-
-xterm-addon-unicode11@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.3.0.tgz#e4435c3c91a5294a7eb8b79c380acbb28a659463"
- integrity sha512-x5fHDZT2j9tlTlHnzPHt++9uKZ2kJ/lYQOj3L6xJA22xoJsS8UQRw/5YIFg2FUHqEAbV77Z1fZij/9NycMSH/A==
-
-xterm-addon-webgl@0.12.0-beta.15:
- version "0.12.0-beta.15"
- resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.15.tgz#9ae82127f2a39b3cb7f5ae45a6af223810c933d4"
- integrity sha512-LWZ3iLspQOCc26OoT8qa+SuyuIcn2cAMRbBkinOuQCk4aW5kjovIrGovj9yVAcXNvOBnPm3sUqmnwGlN579kDA==
-
-xterm-headless@4.15.0-beta.10:
- version "4.15.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.15.0-beta.10.tgz#2dbcb40dfda7ecfdacc7b63889c80da965480ce7"
- integrity sha512-kDAzmaeFX8hAJvbPUJc4dW4SoVBSg4onCVOPyi8QTmxZz1o7I9mX4U7DX1v3PceyfrU27A9k6zXjuTuPjxCCSQ==
-
-xterm@4.15.0-beta.10:
- version "4.15.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.15.0-beta.10.tgz#8cda3d7885e8345f2fc6cf9275a43f3833d29acf"
- integrity sha512-valoh5ZcY/y7Pe+ffgcSAEFeuZfjzVeUUXcthdxTTsrGEiU1s4QR2EOg4U5jn5wye/Nc6mSfLW3s79R6Ac186w==
+xterm-addon-search@0.9.0-beta.6:
+ version "0.9.0-beta.6"
+ resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.9.0-beta.6.tgz#8b016baac5580dc0ba93bb52610bc4f5776d3b17"
+ integrity sha512-UAEzas4O+NrF7BSGf0C9N5ngAkmbtr/hSTFvLAM/Rw7EfLUatf8aLMqAWZTggRGMwDjuqR0GXJI4+e5QrJhQfw==
+
+xterm-addon-serialize@0.7.0-beta.3:
+ version "0.7.0-beta.3"
+ resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.7.0-beta.3.tgz#a8ce52a59685041bd3b6d6a2a77a3df8bc3daf29"
+ integrity sha512-fgB0h8JiSN1cOMh3slenysprnGfFwbDZ/D38WA0Pdjxf3YDy4j2SwoUajlvXpkFWR7sHjVHmgpw/nHggO731KA==
+
+xterm-addon-unicode11@0.4.0-beta.1:
+ version "0.4.0-beta.1"
+ resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.4.0-beta.1.tgz#aeefd26e87bad15d8dfd8a1e0b804fe408c9b882"
+ integrity sha512-pG8mpxnqpYDry0e20vuEFKhd4kKIcLLNwdNftNvfo+R/EjYRnTYnF+H8L+7eQHq6hqDH61xCEP4H4qR2CyT4pg==
+
+xterm-addon-webgl@0.12.0-beta.16:
+ version "0.12.0-beta.16"
+ resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0-beta.16.tgz#63a0f1f5be9e66286e035448e2011e3065769ad5"
+ integrity sha512-g6v3RegOhSsD9Zt8ArWBMNT30QyPUlIWEIvP/xLHAluUZ1S5sDjFyZDB0nJAyn9MwQozJpwb0ylYO1nznN/TzA==
+
+xterm-headless@4.16.0-beta.2:
+ version "4.16.0-beta.2"
+ resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-4.16.0-beta.2.tgz#62e66a655a30c814e3a311f3542d42c87446cecd"
+ integrity sha512-g92HDaIZcu1TQFlrjq2CHtt7A2qAwSD6s8RwncU/7u1kaq2e7rc9O3OKfu5v3QzgaRSKuugtquMr0OTKjkmLUg==
+
+xterm@4.16.0-beta.2:
+ version "4.16.0-beta.2"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.16.0-beta.2.tgz#251beef21a232143f272da74c7005bc4d832ca79"
+ integrity sha512-PD0agueJ7qvbn1/QhZriAQXf+ykaoPKgQN9qiIGf88VMxHs8T47MYHW/+qPsrXagTmbrENtncughTIzOzv8Q5Q==
y18n@^3.2.1:
version "3.2.2"