Merge branch 'main' into joh/vscode-dts

This commit is contained in:
Johannes Rieken 2021-11-10 08:40:26 +01:00
commit d90dd1355b
No known key found for this signature in database
GPG key ID: 96634B5AF12F8798
124 changed files with 1733 additions and 1368 deletions

View file

@ -1,4 +1,4 @@
disturl "https://electronjs.org/headers"
target "13.5.1"
target "13.5.2"
runtime "electron"
build_from_source "true"

View file

@ -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'))

View file

@ -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'))

View file

@ -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'))

View file

@ -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',

View file

@ -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',

View file

@ -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",

View file

@ -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

View file

@ -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')
};
}

View file

@ -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}`);

View file

@ -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;

View file

@ -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);
}

View file

@ -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 {

View file

@ -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}`);

View file

@ -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"
},

View file

@ -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"
},

View file

@ -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"
}
}

View file

@ -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-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.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-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.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-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.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@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==

View file

@ -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-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.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-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.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-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.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-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.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-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.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@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"

View file

@ -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 $?

View file

@ -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 $?

View file

@ -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"

View file

@ -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" ]

View file

@ -2,5 +2,5 @@
setlocal
set VSCODE_DEV=
set ELECTRON_RUN_AS_NODE=1
"%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" %*
endlocal
"%~dp0..\@@NAME@@.exe" "%~dp0..\resources\app\out\cli.js" --ms-enable-electron-run-as-node %*
endlocal

View file

@ -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 $?

View file

@ -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

View file

@ -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 "$@"

View file

@ -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

View file

@ -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%
exit /b %errorlevel%

View file

@ -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

View file

@ -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^

View file

@ -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 \

View file

@ -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;

View file

@ -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;
}

View file

@ -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));
this.columnLayoutDisposable = Event.any(...headers.map(h => h.onDidLayout))
(([index, size]) => renderer.layoutColumn(index, size));
Event.any(...headers.map(h => h.onDidLayout))
(([index, size]) => renderer.layoutColumn(index, size), null, this.disposables);
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();
}
}

View file

@ -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;

View file

@ -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};
}
`);
}
});

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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.") },

View file

@ -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'];

View file

@ -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);

View file

@ -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',

View file

@ -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;

View file

@ -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}`);

View file

@ -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();

View file

@ -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);
}

View file

@ -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) {

View file

@ -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 {

View file

@ -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,

View file

@ -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);

View file

@ -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;
}

View file

@ -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,

View file

@ -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());
}
};
}

View file

@ -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
};
}),
}))
});
}

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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;
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
const inputMatches = editorPane.input?.matches(editor);
// 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 (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 {

View file

@ -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) {

View file

@ -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));
}
}

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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,
});
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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)
)
});

View file

@ -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
}

View file

@ -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'

View file

@ -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');
}

View file

@ -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;
}

View file

@ -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
}
});

View file

@ -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;
}

View file

@ -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());

View file

@ -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[] {

View file

@ -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);

View file

@ -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;
}

View file

@ -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 |

View file

@ -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) {

View file

@ -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;

View file

@ -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();

View file

@ -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,

View file

@ -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,
};
}

View file

@ -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 });
});
});

View file

@ -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 ||

View file

@ -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;
}

View file

@ -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;

View file

@ -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..."),
};
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -40,9 +40,9 @@
*/
.xterm {
font-feature-settings: "liga" 0;
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}

View file

@ -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`);
}

View file

@ -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;

View file

@ -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;
// 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;
}
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;
}
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');
private async _removeScrollbar(): Promise<void> {
if (!this._container || !this._wrapperElement || !this._horizontalScrollbar) {
return;
}
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);
}
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();

Some files were not shown because too many files have changed in this diff Show more