未验证 提交 78e9e08f 编写于 作者: M Manzur Khan Sarguru 提交者: GitHub

Merge pull request #1 from Microsoft/master

Latest
......@@ -31,6 +31,7 @@ addons:
- libsecret-1-dev
before_install:
- export GITHUB_TOKEN=$PUBLIC_GITHUB_TOKEN
- git submodule update --init --recursive
- git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm
- source ./.nvm/nvm.sh
......
......@@ -45,8 +45,8 @@ const nodeModules = ['electron', 'original-fs']
// Build
const builtInExtensions = [
{ name: 'ms-vscode.node-debug', version: '1.19.7' },
{ name: 'ms-vscode.node-debug2', version: '1.19.3' }
{ name: 'ms-vscode.node-debug', version: '1.20.0' },
{ name: 'ms-vscode.node-debug2', version: '1.19.4' }
];
const excludedExtensions = [
......
......@@ -318,7 +318,7 @@
"@emmetio/css-parser": "ramya-rao-a/css-parser#vscode",
"@emmetio/math-expression": "^0.1.1",
"vscode-emmet-helper": "^1.1.19",
"vscode-languageserver-types": "^3.0.3",
"vscode-languageserver-types": "^3.5.0",
"image-size": "^0.5.2",
"vscode-nls": "2.0.2"
}
......
......@@ -23,6 +23,12 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
const isSyntaxMapped = mappedLanguages[document.languageId] ? true : false;
let syntax = getEmmetMode((isSyntaxMapped ? mappedLanguages[document.languageId] : document.languageId), excludedLanguages);
if (!syntax
|| emmetConfig['showExpandedAbbreviation'] === 'never'
|| ((isSyntaxMapped || syntax === 'jsx') && emmetConfig['showExpandedAbbreviation'] !== 'always')) {
return;
}
const helper = getEmmetHelper();
const extractAbbreviationResults = helper.extractAbbreviation(document, position);
if (!extractAbbreviationResults) {
......@@ -46,12 +52,6 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
}
}
if (!syntax
|| ((isSyntaxMapped || syntax === 'jsx')
&& emmetConfig['showExpandedAbbreviation'] !== 'always')) {
return;
}
let noiseCheckPromise: Thenable<any> = Promise.resolve();
// Fix for https://github.com/Microsoft/vscode/issues/32647
......
......@@ -2059,6 +2059,10 @@ vscode-languageserver-types@^3.0.3:
version "3.3.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.3.0.tgz#8964dc7c2247536fbefd2d6836bf3febac80dd00"
vscode-languageserver-types@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
vscode-nls@2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
......
......@@ -519,6 +519,7 @@ export class Repository implements Disposable {
this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)");
this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] };
this._sourceControl.quickDiffProvider = this;
this._sourceControl.inputBox.lineWarningLength = 72;
this.disposables.push(this._sourceControl);
this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes"));
......
......@@ -11,8 +11,8 @@
],
"main": "./out/javascriptMain",
"dependencies": {
"jsonc-parser": "^0.3.1",
"request-light": "^0.2.0",
"jsonc-parser": "^1.0.0",
"request-light": "^0.2.1",
"vscode-nls": "^2.0.2"
},
"scripts": {
......
......@@ -36,19 +36,17 @@ https-proxy-agent@^0.3.5:
debug "2"
extend "3"
jsonc-parser@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-0.3.1.tgz#6ebf5c75224368d4b07ef4c26f9434e657472e95"
dependencies:
vscode-nls "^2.0.2"
jsonc-parser@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272"
ms@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
request-light@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.0.tgz#922497791c2e68528124dfb82354cf37e4bb2cfc"
request-light@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.1.tgz#986f5a82893e9d1ca6a896ebe6f46c51c6b4557f"
dependencies:
http-proxy-agent "^0.2.6"
https-proxy-agent "^0.3.5"
......
......@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
'use strict';
(function () {
......@@ -29,6 +29,13 @@
};
}
function postMessage(command, args) {
window.parent.postMessage({
command: 'did-click-link',
data: `command:${command}?${encodeURIComponent(JSON.stringify(args))}`
}, 'file://');
}
/**
* Find the html elements that map to a specific target line in the editor.
*
......@@ -196,14 +203,34 @@
const offset = event.pageY;
const line = getEditorLineNumberForPageOffset(offset);
if (!isNaN(line)) {
const args = [settings.source, line];
window.parent.postMessage({
command: "did-click-link",
data: `command:_markdown.didClick?${encodeURIComponent(JSON.stringify(args))}`
}, "file://");
postMessage('_markdown.didClick', [settings.source, line]);
}
});
document.addEventListener('click', event => {
if (!event) {
return;
}
const baseElement = document.getElementsByTagName('base')[0];
/** @type {any} */
let node = event.target;
while (node) {
if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {
if (node.href.startsWith('file://')) {
const [path, fragment] = node.href.replace(/^file:\/\//i, '').split('#');
postMessage('_markdown.openDocumentLink', { path, fragment });
event.preventDefault();
event.stopPropagation();
break;
}
break;
}
node = node.parentNode;
}
}, true);
if (settings.scrollEditorWithPreview) {
window.addEventListener('scroll', throttle(() => {
if (scrollDisabled) {
......@@ -211,11 +238,7 @@
} else {
const line = getEditorLineNumberForPageOffset(window.scrollY);
if (!isNaN(line)) {
const args = [settings.source, line];
window.parent.postMessage({
command: 'did-click-link',
data: `command:_markdown.revealLine?${encodeURIComponent(JSON.stringify(args))}`
}, 'file://');
postMessage('_markdown.revealLine', [settings.source, line]);
}
}
}, 50));
......
......@@ -311,8 +311,8 @@
"highlight.js": "9.5.0",
"markdown-it": "^8.4.0",
"markdown-it-named-headers": "0.0.4",
"vscode-extension-telemetry": "0.0.8",
"vscode-nls": "2.0.2"
"vscode-extension-telemetry": "^0.0.8",
"vscode-nls": "^2.0.2"
},
"devDependencies": {
"@types/highlight.js": "9.1.10",
......
......@@ -264,6 +264,16 @@ export class OpenDocumentLinkCommand implements Command {
new vscode.Range(line, 0, line, 0),
vscode.TextEditorRevealType.AtTop);
}
const lineNumberFragment = args.fragment.match(/^L(\d+)$/);
if (lineNumberFragment) {
const line = +lineNumberFragment[1] - 1;
if (!isNaN(line)) {
return editor.revealRange(
new vscode.Range(line, 0, line, 0),
vscode.TextEditorRevealType.AtTop);
}
}
}
};
......
......@@ -137,8 +137,9 @@ export class MarkdownEngine {
md.normalizeLink = (link: string) => {
try {
let uri = vscode.Uri.parse(link);
if (!uri.scheme && uri.path && !uri.fragment) {
if (!uri.scheme && uri.path) {
// Assume it must be a file
const fragment = uri.fragment;
if (uri.path[0] === '/') {
const root = vscode.workspace.getWorkspaceFolder(this.currentDocument);
if (root) {
......@@ -147,6 +148,10 @@ export class MarkdownEngine {
} else {
uri = vscode.Uri.file(path.join(path.dirname(this.currentDocument.path), uri.path));
}
if (fragment) {
uri = uri.with({ fragment });
}
return normalizeLink(uri.toString(true));
}
} catch (e) {
......
......@@ -155,14 +155,14 @@ util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
vscode-extension-telemetry@0.0.8:
vscode-extension-telemetry@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0"
dependencies:
applicationinsights "0.18.0"
winreg "1.2.3"
vscode-nls@2.0.2:
vscode-nls@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
......
{
"name": "node-debug",
"version": "1.19.2",
"version": "1.19.7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -42,21 +42,21 @@
}
},
"@types/mocha": {
"version": "2.2.42",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.42.tgz",
"integrity": "sha512-b6gVDoxEbAQGwbV7gSzeFw/hy3/eEAokztktdzl4bHvGgb9K5zW4mVQDlVYch2w31m8t/J7L2iqhQvz3r5edCQ==",
"version": "2.2.44",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz",
"integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==",
"dev": true
},
"@types/node": {
"version": "6.0.52",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.52.tgz",
"integrity": "sha1-GsOpm0IyD55GNILyWvTCNZRzqqY=",
"version": "7.0.43",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.43.tgz",
"integrity": "sha512-7scYwwfHNppXvH/9JzakbVxk0o0QUILVk1Lv64GRaxwPuGpnF1QBiwdvhDpLcymb8BpomQL3KYoWKq3wUdDMhQ==",
"dev": true
},
"@types/source-map": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.1.tgz",
"integrity": "sha512-/GVAjL1Y8puvZab63n8tsuBiYwZt1bApMdx58/msQ9ID5T05ov+wm/ZV1DvYC/DKKEygpTJViqQvkh5Rhrl4CA==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.2.tgz",
"integrity": "sha512-++w4WmMbk3dS3UeHGzAG+xJOSz5Xqtjys/TBkqG3qp3SeWE7Wwezqe5eB7B51cxUyh4PW7bwVotpsLdBK0D8cw==",
"dev": true
},
"abbrev": {
......@@ -4755,9 +4755,9 @@
}
},
"mime": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.5.0.tgz",
"integrity": "sha512-v/jMDoK/qKptnTuC3YUNbIj8uUYvTCIHzVu9BHldKSWja48wusAtfjlcBlqnFrqClu3yf69ScDxBPrIyFnF51g==",
"dev": true
},
"mime-db": {
......@@ -5149,13 +5149,30 @@
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true
},
"parse-semver": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
"integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
"dev": true,
"requires": {
"semver": "5.4.1"
},
"dependencies": {
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
}
}
},
"parse5": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
"integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
"dev": true,
"requires": {
"@types/node": "6.0.52"
"@types/node": "7.0.43"
}
},
"path-dirname": {
......@@ -6671,9 +6688,9 @@
}
},
"vsce": {
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.32.0.tgz",
"integrity": "sha1-EN+pIyGCwg6r5r8xJdMzpLIG/j0=",
"version": "1.33.2",
"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.33.2.tgz",
"integrity": "sha1-NkX2mq+YTiL3TqSdNfON0Y1m/18=",
"dev": true,
"requires": {
"cheerio": "1.0.0-rc.2",
......@@ -6682,9 +6699,10 @@
"glob": "7.1.2",
"lodash": "4.17.4",
"markdown-it": "8.4.0",
"mime": "1.4.1",
"mime": "1.5.0",
"minimatch": "3.0.4",
"osenv": "0.1.4",
"parse-semver": "1.1.1",
"read": "1.0.7",
"semver": "5.4.1",
"tmp": "0.0.29",
......@@ -6709,9 +6727,9 @@
}
},
"vscode": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.6.tgz",
"integrity": "sha1-Ru0a+iwbnWifY5TI8WvR1xkPdfs=",
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.8.tgz",
"integrity": "sha512-kT6sIA1AEKR5M+us2fXk5dxwV9SR/IEdLHNmVW4/dl1wNBHoEvgIo1qMQwHNxPVTQmw70KTGZ9UVeVb8FbpNFA==",
"dev": true,
"requires": {
"glob": "7.1.2",
......@@ -6739,34 +6757,26 @@
}
},
"vscode-debugadapter": {
"version": "1.25.0-pre.0",
"resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0-pre.0.tgz",
"integrity": "sha1-0pDsVH5h5Pvss2P/9ojSAyMZQmQ=",
"version": "1.25.0",
"resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0.tgz",
"integrity": "sha512-tsOtNNKKTbnQanARdkFfUxI8qKVKba+QHOKWC1reDDeeyvzoNKkLMGkL/xsiKn5vQDeaP3zFBcLY8Ysak9GrvQ==",
"requires": {
"vscode-debugprotocol": "1.25.0-pre.0"
},
"dependencies": {
"vscode-debugprotocol": {
"version": "1.25.0-pre.0",
"resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0-pre.0.tgz",
"integrity": "sha1-rYPnvZWxmseV31D6Di/pA0YqcrY="
}
"vscode-debugprotocol": "1.25.0"
}
},
"vscode-debugadapter-testsupport": {
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.24.0.tgz",
"integrity": "sha1-rDZ1scU/wW+1JMvSt+znEhtiXng=",
"version": "1.25.0",
"resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.25.0.tgz",
"integrity": "sha512-6E2N7CoH7B0KEDvI9mFVFt4H+dRFDhtj3PmLVjNojfZ1VZZS2yfhE0XO0E5Axdhef3zTpUU6WZoeOOMVFGZGIg==",
"dev": true,
"requires": {
"vscode-debugprotocol": "1.24.0"
"vscode-debugprotocol": "1.25.0"
}
},
"vscode-debugprotocol": {
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz",
"integrity": "sha1-28EOjX2VsQJyehmvPw/O9+JSsI4=",
"dev": true
"version": "1.25.0",
"resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz",
"integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA=="
},
"vscode-nls": {
"version": "2.0.2",
......@@ -6774,9 +6784,9 @@
"integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto="
},
"vscode-nls-dev": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.5.tgz",
"integrity": "sha1-GfqjsYp/MCIBA5pMlnu9IvoShE0=",
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/vscode-nls-dev/-/vscode-nls-dev-2.1.6.tgz",
"integrity": "sha512-1IylC/ekENYqz1vEItfrzrMXS8LW9aZQnNTU6BfdwT0Jddzed+l+nvU8amgVKFFmC1/GoiMFk5wtC20zWBbEbw==",
"dev": true,
"requires": {
"clone": "1.0.3",
......
......@@ -13,8 +13,8 @@
},
"dependencies": {
"semver": "4.3.6",
"vscode-extension-telemetry": "0.0.8",
"vscode-nls": "2.0.1"
"vscode-extension-telemetry": "^0.0.8",
"vscode-nls": "^2.0.2"
},
"devDependencies": {
"@types/node": "8.0.33",
......
......@@ -399,8 +399,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
}
private snippetForFunctionCall(detail: CompletionEntryDetails): SnippetString {
const suggestionArgumentNames: string[] = [];
let hasOptionalParemeters = false;
let hasOptionalParameters = false;
let hasAddedParameters = false;
const snippet = new SnippetString();
snippet.appendText(detail.name);
snippet.appendText('(');
let parenCount = 0;
let i = 0;
for (; i < detail.displayParts.length; ++i) {
......@@ -411,9 +416,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
// Skip optional parameters
const nameIsFollowedByOptionalIndicator = next && next.text === '?';
if (!nameIsFollowedByOptionalIndicator) {
suggestionArgumentNames.push(`\${${i + 1}:${part.text}}`);
if (hasAddedParameters) {
snippet.appendText(', ');
}
hasAddedParameters = true;
snippet.appendPlaceholder(part.text);
}
hasOptionalParemeters = hasOptionalParemeters || nameIsFollowedByOptionalIndicator;
hasOptionalParameters = hasOptionalParameters || nameIsFollowedByOptionalIndicator;
} else if (part.kind === 'punctuation') {
if (part.text === '(') {
++parenCount;
......@@ -421,13 +430,17 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
--parenCount;
} else if (part.text === '...' && parenCount === 1) {
// Found rest parmeter. Do not fill in any further arguments
hasOptionalParemeters = true;
hasOptionalParameters = true;
break;
}
}
}
const codeSnippet = `${detail.name}(${suggestionArgumentNames.join(', ')}${hasOptionalParemeters ? '${' + i + '}' : ''})$0`;
return new SnippetString(codeSnippet);
if (hasOptionalParameters) {
snippet.appendTabstop();
}
snippet.appendText(')');
snippet.appendTabstop(0);
return snippet;
}
private getConfiguration(resource: Uri): Configuration {
......
......@@ -27,6 +27,7 @@ import { TypeScriptServiceConfiguration, TsServerLogLevel } from './utils/config
import { TypeScriptVersionProvider, TypeScriptVersion } from './utils/versionProvider';
import { TypeScriptVersionPicker } from './utils/versionPicker';
import * as fileSchemes from './utils/fileSchemes';
import { inferredProjectConfig } from './utils/tsconfig';
const localize = nls.loadMessageBundle();
......@@ -330,11 +331,9 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
this.error('Starting TSServer failed with error.', err);
window.showErrorMessage(localize('serverCouldNotBeStarted', 'TypeScript language server couldn\'t be started. Error message is: {0}', err.message || err));
/* __GDPR__
"error" : {
"message": { "classification": "CustomerContent", "purpose": "PerformanceAndHealth" }
}
"error" : {}
*/
this.logTelemetry('error', { message: err.message });
this.logTelemetry('error');
this.resetClientVersion();
return;
}
......@@ -476,20 +475,12 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
}
private getCompilerOptionsForInferredProjects(configuration: TypeScriptServiceConfiguration): Proto.ExternalProjectCompilerOptions {
const compilerOptions: Proto.ExternalProjectCompilerOptions = {
module: 'CommonJS' as Proto.ModuleKind,
target: 'ES6' as Proto.ScriptTarget,
return {
...inferredProjectConfig(configuration),
allowJs: true,
allowSyntheticDefaultImports: true,
allowNonTsExtensions: true,
allowJs: true,
jsx: 'Preserve' as Proto.JsxEmit
};
if (this.apiVersion.has230Features()) {
compilerOptions.checkJs = configuration.checkJs;
compilerOptions.experimentalDecorators = configuration.experimentalDecorators;
}
return compilerOptions;
}
private serviceExited(restart: boolean): void {
......
......@@ -5,27 +5,39 @@
import * as vscode from 'vscode';
import * as path from 'path';
import * as Proto from '../protocol';
import { TypeScriptServiceConfiguration } from './configuration';
export function isImplicitProjectConfigFile(configFileName: string) {
return configFileName.indexOf('/dev/null/') === 0;
}
function getEmptyConfig(
isTypeScriptProject: boolean,
export function inferredProjectConfig(
config: TypeScriptServiceConfiguration
) {
const compilerOptions = [
'"target": "ES6"',
'"module": "commonjs"',
'"jsx": "preserve"',
];
if (!isTypeScriptProject && config.checkJs) {
compilerOptions.push('"checkJs": true');
): Proto.ExternalProjectCompilerOptions {
const base: Proto.ExternalProjectCompilerOptions = {
module: 'commonjs' as Proto.ModuleKind,
target: 'es2016' as Proto.ScriptTarget,
jsx: 'preserve' as Proto.JsxEmit
};
if (config.checkJs) {
base.checkJs = true;
}
if (!isTypeScriptProject && config.experimentalDecorators) {
compilerOptions.push('"experimentalDecorators": true');
if (config.experimentalDecorators) {
base.experimentalDecorators = true;
}
return base;
}
function inferredProjectConfigSnippet(
config: TypeScriptServiceConfiguration
) {
const baseConfig = inferredProjectConfig(config);
const compilerOptions = Object.keys(baseConfig).map(key => `"${key}": ${JSON.stringify(baseConfig[key])}`);
return new vscode.SnippetString(`{
"compilerOptions": {
${compilerOptions.join(',\n\t\t')}$0
......@@ -51,7 +63,7 @@ export async function openOrCreateConfigFile(
const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' }));
const editor = await vscode.window.showTextDocument(doc, col);
if (editor.document.getText().length === 0) {
await editor.insertSnippet(getEmptyConfig(isTypeScriptProject, config));
await editor.insertSnippet(inferredProjectConfigSnippet(config));
}
return editor;
}
......
......@@ -18,16 +18,16 @@ semver@4.3.6:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
vscode-extension-telemetry@0.0.8:
vscode-extension-telemetry@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0"
dependencies:
applicationinsights "0.18.0"
winreg "1.2.3"
vscode-nls@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.1.tgz#7853866e33f9c50ca415e51b9640d081800e36c6"
vscode-nls@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
winreg@1.2.3:
version "1.2.3"
......
......@@ -10,14 +10,21 @@ set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5%
:: Tests in the extension host
call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR%
if %errorlevel% neq 0 exit /b %errorlevel%
call .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR%
if %errorlevel% neq 0 exit /b %errorlevel%
call .\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR%
if %errorlevel% neq 0 exit /b %errorlevel%
:: Integration & performance tests in AMD
call .\scripts\test.bat --runGlob **\*.integrationTest.js %*
if %errorlevel% neq 0 exit /b %errorlevel%
:: Tests in commonJS (language servers tests...)
call .\scripts\node-electron.bat .\node_modules\mocha\bin\_mocha .\extensions\html\server\out\test\
if %errorlevel% neq 0 exit /b %errorlevel%
rmdir /s /q %VSCODEUSERDATADIR%
......
......@@ -124,7 +124,7 @@ function formatEnvironment(info: IMainProcessInfo): string {
const output: string[] = [];
output.push(`Version: ${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`);
output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()})`);
output.push(`OS Version: ${os.type()} ${os.arch()} ${os.release()}`);
const cpus = os.cpus();
if (cpus && cpus.length > 0) {
output.push(`CPUs: ${cpus[0].model} (${cpus.length} x ${cpus[0].speed})`);
......
......@@ -472,8 +472,8 @@ export class View extends ViewEventHandler {
return this.outgoingEvents;
}
public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): OverviewRuler {
return new OverviewRuler(this._context, cssClassName, minimumHeight, maximumHeight);
public createOverviewRuler(cssClassName: string): OverviewRuler {
return new OverviewRuler(this._context, cssClassName);
}
public change(callback: (changeAccessor: editorBrowser.IViewZoneChangeAccessor) => any): boolean {
......
......@@ -11,38 +11,23 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions';
import { OverviewRulerZone, OverviewZoneManager, ColorZone } from 'vs/editor/common/view/overviewZoneManager';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { Color } from 'vs/base/common/color';
import { LIGHT } from 'vs/platform/theme/common/themeService';
import { OverviewRulerLane } from 'vs/editor/common/editorCommon';
export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
private _context: ViewContext;
private _canvasLeftOffset: number;
private _domNode: FastDomNode<HTMLCanvasElement>;
private _lanesCount: number;
private _zoneManager: OverviewZoneManager;
private _background: Color;
constructor(context: ViewContext, cssClassName: string, minimumHeight: number, maximumHeight: number) {
constructor(context: ViewContext, cssClassName: string) {
super();
this._context = context;
this._canvasLeftOffset = 0;
this._domNode = createFastDomNode(document.createElement('canvas'));
this._domNode.setClassName(cssClassName);
this._domNode.setPosition('absolute');
this._domNode.setLayerHinting(true);
this._lanesCount = 3;
this._background = null;
this._zoneManager = new OverviewZoneManager((lineNumber: number) => this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber));
this._zoneManager.setMinimumHeight(minimumHeight);
this._zoneManager.setMaximumHeight(maximumHeight);
this._zoneManager.setThemeType(LIGHT);
this._zoneManager.setDOMWidth(0);
this._zoneManager.setDOMHeight(0);
this._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight());
......@@ -64,7 +49,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
if (e.lineHeight) {
this._zoneManager.setLineHeight(this._context.configuration.editor.lineHeight);
this.render(true);
this._render();
}
if (e.pixelRatio) {
......@@ -73,23 +58,24 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
this._domNode.setHeight(this._zoneManager.getDOMHeight());
this._domNode.domNode.width = this._zoneManager.getCanvasWidth();
this._domNode.domNode.height = this._zoneManager.getCanvasHeight();
this.render(true);
this._render();
}
return true;
}
public onFlushed(e: viewEvents.ViewFlushedEvent): boolean {
this._render();
return true;
}
public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {
this._zoneManager.setOuterHeight(e.scrollHeight);
this.render(true);
return super.onScrollChanged(e) || e.scrollHeightChanged;
if (e.scrollHeightChanged) {
this._zoneManager.setOuterHeight(e.scrollHeight);
this._render();
}
return true;
}
public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {
this._render();
return true;
}
......@@ -113,16 +99,16 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
this._domNode.domNode.width = this._zoneManager.getCanvasWidth();
this._domNode.domNode.height = this._zoneManager.getCanvasHeight();
this.render(true);
this._render();
}
}
public setZones(zones: OverviewRulerZone[]): void {
this._zoneManager.setZones(zones);
this.render(false);
this._render();
}
public render(forceRender: boolean): boolean {
private _render(): boolean {
if (this._zoneManager.getOuterHeight() === 0) {
return false;
}
......@@ -134,79 +120,29 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
let id2Color = this._zoneManager.getId2Color();
let ctx = this._domNode.domNode.getContext('2d');
if (this._background === null) {
ctx.clearRect(0, 0, width, height);
} else {
ctx.fillStyle = Color.Format.CSS.formatHex(this._background);
ctx.fillRect(0, 0, width, height);
}
ctx.clearRect(0, 0, width, height);
if (colorZones.length > 0) {
let remainingWidth = width - this._canvasLeftOffset;
if (this._lanesCount >= 3) {
this._renderThreeLanes(ctx, colorZones, id2Color, remainingWidth);
} else if (this._lanesCount === 2) {
this._renderTwoLanes(ctx, colorZones, id2Color, remainingWidth);
} else if (this._lanesCount === 1) {
this._renderOneLane(ctx, colorZones, id2Color, remainingWidth);
}
this._renderOneLane(ctx, colorZones, id2Color, width);
}
return true;
}
private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void {
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center | OverviewRulerLane.Right, this._canvasLeftOffset, w);
}
private _renderTwoLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void {
let leftWidth = Math.floor(w / 2);
let rightWidth = w - leftWidth;
let leftOffset = this._canvasLeftOffset;
let rightOffset = this._canvasLeftOffset + leftWidth;
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left | OverviewRulerLane.Center, leftOffset, leftWidth);
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth);
}
private _renderThreeLanes(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], w: number): void {
let leftWidth = Math.floor(w / 3);
let rightWidth = Math.floor(w / 3);
let centerWidth = w - leftWidth - rightWidth;
let leftOffset = this._canvasLeftOffset;
let centerOffset = this._canvasLeftOffset + leftWidth;
let rightOffset = this._canvasLeftOffset + leftWidth + centerWidth;
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Left, leftOffset, leftWidth);
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Center, centerOffset, centerWidth);
this._renderVerticalPatch(ctx, colorZones, id2Color, OverviewRulerLane.Right, rightOffset, rightWidth);
}
private _renderVerticalPatch(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], laneMask: number, xpos: number, width: number): void {
private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], width: number): void {
let currentColorId = 0;
let currentFrom = 0;
let currentTo = 0;
for (let i = 0, len = colorZones.length; i < len; i++) {
let zone = colorZones[i];
if (!(zone.position & laneMask)) {
continue;
}
const zone = colorZones[i];
let zoneColorId = zone.colorId;
let zoneFrom = zone.from;
let zoneTo = zone.to;
const zoneColorId = zone.colorId;
const zoneFrom = zone.from;
const zoneTo = zone.to;
if (zoneColorId !== currentColorId) {
ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom);
ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);
currentColorId = zoneColorId;
ctx.fillStyle = id2Color[currentColorId];
......@@ -216,14 +152,14 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
if (currentTo >= zoneFrom) {
currentTo = Math.max(currentTo, zoneTo);
} else {
ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom);
ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);
currentFrom = zoneFrom;
currentTo = zoneTo;
}
}
}
ctx.fillRect(xpos, currentFrom, width, currentTo - currentFrom);
ctx.fillRect(0, currentFrom, width, currentTo - currentFrom);
}
}
......@@ -157,8 +157,8 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
super.dispose();
}
public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): editorBrowser.IOverviewRuler {
return this._view.createOverviewRuler(cssClassName, minimumHeight, maximumHeight);
public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler {
return this._view.createOverviewRuler(cssClassName);
}
public getDomNode(): HTMLElement {
......
......@@ -361,14 +361,14 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode());
this._originalOverviewRuler.dispose();
}
this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler', 4, Number.MAX_VALUE);
this._originalOverviewRuler = this.originalEditor.createOverviewRuler('original diffOverviewRuler');
this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode());
if (this._modifiedOverviewRuler) {
this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode());
this._modifiedOverviewRuler.dispose();
}
this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler', 4, Number.MAX_VALUE);
this._modifiedOverviewRuler = this.modifiedEditor.createOverviewRuler('modified diffOverviewRuler');
this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode());
this._layoutOverviewRulers();
......@@ -1594,6 +1594,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
}
_getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._removeColor.toString();
let result: IEditorDiffDecorations = {
decorations: [],
......@@ -1614,16 +1615,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, DECORATIONS.charDeleteWholeLine));
}
let color = this._removeColor.toString();
result.overviewZones.push(new OverviewRulerZone(
lineChange.originalStartLineNumber,
lineChange.originalEndLineNumber,
editorCommon.OverviewRulerLane.Full,
0,
color,
color,
color
overviewZoneColor
));
if (lineChange.charChanges) {
......@@ -1659,6 +1654,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
}
_getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._insertColor.toString();
let result: IEditorDiffDecorations = {
decorations: [],
......@@ -1679,15 +1675,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) {
result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine));
}
let color = this._insertColor.toString();
result.overviewZones.push(new OverviewRulerZone(
lineChange.modifiedStartLineNumber,
lineChange.modifiedEndLineNumber,
editorCommon.OverviewRulerLane.Full,
0,
color,
color,
color
overviewZoneColor
));
if (lineChange.charChanges) {
......@@ -1783,6 +1774,8 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
}
_getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._removeColor.toString();
let result: IEditorDiffDecorations = {
decorations: [],
overviewZones: []
......@@ -1798,15 +1791,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
options: DECORATIONS.lineDeleteMargin
});
let color = this._removeColor.toString();
result.overviewZones.push(new OverviewRulerZone(
lineChange.originalStartLineNumber,
lineChange.originalEndLineNumber,
editorCommon.OverviewRulerLane.Full,
0,
color,
color,
color
overviewZoneColor
));
}
}
......@@ -1815,6 +1803,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
}
_getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._insertColor.toString();
let result: IEditorDiffDecorations = {
decorations: [],
......@@ -1833,15 +1822,10 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert)
});
let color = this._insertColor.toString();
result.overviewZones.push(new OverviewRulerZone(
lineChange.modifiedStartLineNumber,
lineChange.modifiedEndLineNumber,
editorCommon.OverviewRulerLane.Full,
0,
color,
color,
color
overviewZoneColor
));
if (lineChange.charChanges) {
......
......@@ -4,22 +4,31 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { OverviewRulerLane } from 'vs/editor/common/editorCommon';
import { ThemeType, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
const enum Constants {
MINIMUM_HEIGHT = 4
}
export class ColorZone {
_colorZoneBrand: void;
from: number;
to: number;
colorId: number;
position: OverviewRulerLane;
public readonly from: number;
public readonly to: number;
public readonly colorId: number;
constructor(from: number, to: number, colorId: number, position: OverviewRulerLane) {
constructor(from: number, to: number, colorId: number) {
this.from = from | 0;
this.to = to | 0;
this.colorId = colorId | 0;
this.position = position | 0;
}
public static compare(a: ColorZone, b: ColorZone): number {
if (a.colorId === b.colorId) {
if (a.from === b.from) {
return a.to - b.to;
}
return a.from - b.from;
}
return a.colorId - b.colorId;
}
}
......@@ -29,74 +38,39 @@ export class ColorZone {
export class OverviewRulerZone {
_overviewRulerZoneBrand: void;
startLineNumber: number;
endLineNumber: number;
position: OverviewRulerLane;
forceHeight: number;
private _color: string;
private _darkColor: string;
private _hcColor: string;
public readonly startLineNumber: number;
public readonly endLineNumber: number;
public readonly color: string;
private _colorZones: ColorZone[];
private _colorZone: ColorZone;
constructor(
startLineNumber: number, endLineNumber: number,
position: OverviewRulerLane,
forceHeight: number,
color: string, darkColor: string, hcColor: string
startLineNumber: number,
endLineNumber: number,
color: string
) {
this.startLineNumber = startLineNumber;
this.endLineNumber = endLineNumber;
this.position = position;
this.forceHeight = forceHeight;
this._color = color;
this._darkColor = darkColor;
this._hcColor = hcColor;
this._colorZones = null;
}
public getColor(themeType: ThemeType): string {
switch (themeType) {
case HIGH_CONTRAST:
return this._hcColor;
case DARK:
return this._darkColor;
}
return this._color;
this.color = color;
this._colorZone = null;
}
public compareTo(other: OverviewRulerZone): number {
if (this.startLineNumber === other.startLineNumber) {
if (this.endLineNumber === other.endLineNumber) {
if (this.forceHeight === other.forceHeight) {
if (this.position === other.position) {
if (this._darkColor === other._darkColor) {
if (this._color === other._color) {
if (this._hcColor === other._hcColor) {
return 0;
}
return this._hcColor < other._hcColor ? -1 : 1;
}
return this._color < other._color ? -1 : 1;
}
return this._darkColor < other._darkColor ? -1 : 1;
}
return this.position - other.position;
}
return this.forceHeight - other.forceHeight;
public static compare(a: OverviewRulerZone, b: OverviewRulerZone): number {
if (a.color === b.color) {
if (a.startLineNumber === b.startLineNumber) {
return a.endLineNumber - b.endLineNumber;
}
return this.endLineNumber - other.endLineNumber;
return a.startLineNumber - b.startLineNumber;
}
return this.startLineNumber - other.startLineNumber;
return a.color < b.color ? -1 : 1;
}
public setColorZones(colorZones: ColorZone[]): void {
this._colorZones = colorZones;
public setColorZone(colorZone: ColorZone): void {
this._colorZone = colorZone;
}
public getColorZones(): ColorZone[] {
return this._colorZones;
public getColorZones(): ColorZone {
return this._colorZone;
}
}
......@@ -109,9 +83,6 @@ export class OverviewZoneManager {
private _domWidth: number;
private _domHeight: number;
private _outerHeight: number;
private _maximumHeight: number;
private _minimumHeight: number;
private _themeType: ThemeType;
private _pixelRatio: number;
private _lastAssignedId: number;
......@@ -126,9 +97,6 @@ export class OverviewZoneManager {
this._domWidth = 0;
this._domHeight = 0;
this._outerHeight = 0;
this._maximumHeight = 0;
this._minimumHeight = 0;
this._themeType = LIGHT;
this._pixelRatio = 1;
this._lastAssignedId = 0;
......@@ -141,39 +109,8 @@ export class OverviewZoneManager {
}
public setZones(newZones: OverviewRulerZone[]): void {
newZones.sort((a, b) => a.compareTo(b));
let oldZones = this._zones;
let oldIndex = 0;
let oldLength = this._zones.length;
let newIndex = 0;
let newLength = newZones.length;
let result: OverviewRulerZone[] = [];
while (newIndex < newLength) {
let newZone = newZones[newIndex];
if (oldIndex >= oldLength) {
result.push(newZone);
newIndex++;
} else {
let oldZone = oldZones[oldIndex];
let cmp = oldZone.compareTo(newZone);
if (cmp < 0) {
oldIndex++;
} else if (cmp > 0) {
result.push(newZone);
newIndex++;
} else {
// cmp === 0
result.push(oldZone);
oldIndex++;
newIndex++;
}
}
}
this._zones = result;
this._zones = newZones;
this._zones.sort(OverviewRulerZone.compare);
}
public setLineHeight(lineHeight: number): boolean {
......@@ -237,146 +174,58 @@ export class OverviewZoneManager {
return true;
}
public setMaximumHeight(maximumHeight: number): boolean {
if (this._maximumHeight === maximumHeight) {
return false;
}
this._maximumHeight = maximumHeight;
this._colorZonesInvalid = true;
return true;
}
public setMinimumHeight(minimumHeight: number): boolean {
if (this._minimumHeight === minimumHeight) {
return false;
}
this._minimumHeight = minimumHeight;
this._colorZonesInvalid = true;
return true;
}
public setThemeType(themeType: ThemeType): boolean {
if (this._themeType === themeType) {
return false;
}
this._themeType = themeType;
this._colorZonesInvalid = true;
return true;
}
public resolveColorZones(): ColorZone[] {
const colorZonesInvalid = this._colorZonesInvalid;
const lineHeight = Math.floor(this._lineHeight); // @perf
const totalHeight = Math.floor(this.getCanvasHeight()); // @perf
const maximumHeight = Math.floor(this._maximumHeight * this._pixelRatio); // @perf
const minimumHeight = Math.floor(this._minimumHeight * this._pixelRatio); // @perf
const themeType = this._themeType; // @perf
const outerHeight = Math.floor(this._outerHeight); // @perf
const heightRatio = totalHeight / outerHeight;
let allColorZones: ColorZone[] = [];
for (let i = 0, len = this._zones.length; i < len; i++) {
let zone = this._zones[i];
const zone = this._zones[i];
if (!colorZonesInvalid) {
let colorZones = zone.getColorZones();
if (colorZones) {
for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) {
allColorZones.push(colorZones[j]);
}
const colorZone = zone.getColorZones();
if (colorZone) {
allColorZones.push(colorZone);
continue;
}
}
let colorZones: ColorZone[] = [];
if (zone.forceHeight) {
let forcedHeight = Math.floor(zone.forceHeight * this._pixelRatio);
let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber));
y1 = Math.floor(y1 * heightRatio);
let y2 = y1 + forcedHeight;
colorZones.push(this.createZone(totalHeight, y1, y2, forcedHeight, forcedHeight, zone.getColor(themeType), zone.position));
} else {
let y1 = Math.floor(this._getVerticalOffsetForLine(zone.startLineNumber));
let y2 = Math.floor(this._getVerticalOffsetForLine(zone.endLineNumber)) + lineHeight;
y1 = Math.floor(y1 * heightRatio);
y2 = Math.floor(y2 * heightRatio);
const y1 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.startLineNumber)));
const y2 = Math.floor(heightRatio * (this._getVerticalOffsetForLine(zone.endLineNumber) + lineHeight));
// Figure out if we can render this in one continuous zone
let zoneLineNumbers = zone.endLineNumber - zone.startLineNumber + 1;
let zoneMaximumHeight = zoneLineNumbers * maximumHeight;
let ycenter = Math.floor((y1 + y2) / 2);
let halfHeight = (y2 - ycenter);
if (y2 - y1 > zoneMaximumHeight) {
// We need to draw one zone per line
for (let lineNumber = zone.startLineNumber; lineNumber <= zone.endLineNumber; lineNumber++) {
y1 = Math.floor(this._getVerticalOffsetForLine(lineNumber));
y2 = y1 + lineHeight;
y1 = Math.floor(y1 * heightRatio);
y2 = Math.floor(y2 * heightRatio);
colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, maximumHeight, zone.getColor(themeType), zone.position));
}
} else {
colorZones.push(this.createZone(totalHeight, y1, y2, minimumHeight, zoneMaximumHeight, zone.getColor(themeType), zone.position));
}
if (halfHeight < Constants.MINIMUM_HEIGHT / 2) {
halfHeight = Constants.MINIMUM_HEIGHT / 2;
}
zone.setColorZones(colorZones);
for (let j = 0, lenJ = colorZones.length; j < lenJ; j++) {
allColorZones.push(colorZones[j]);
if (ycenter - halfHeight < 0) {
ycenter = halfHeight;
}
}
this._colorZonesInvalid = false;
let sortFunc = (a: ColorZone, b: ColorZone) => {
if (a.colorId === b.colorId) {
if (a.from === b.from) {
return a.to - b.to;
}
return a.from - b.from;
if (ycenter + halfHeight > totalHeight) {
ycenter = totalHeight - halfHeight;
}
return a.colorId - b.colorId;
};
allColorZones.sort(sortFunc);
return allColorZones;
}
public createZone(totalHeight: number, y1: number, y2: number, minimumHeight: number, maximumHeight: number, color: string, position: OverviewRulerLane): ColorZone {
totalHeight = Math.floor(totalHeight); // @perf
y1 = Math.floor(y1); // @perf
y2 = Math.floor(y2); // @perf
minimumHeight = Math.floor(minimumHeight); // @perf
maximumHeight = Math.floor(maximumHeight); // @perf
let ycenter = Math.floor((y1 + y2) / 2);
let halfHeight = (y2 - ycenter);
const color = zone.color;
let colorId = this._color2Id[color];
if (!colorId) {
colorId = (++this._lastAssignedId);
this._color2Id[color] = colorId;
this._id2Color[colorId] = color;
}
const colorZone = new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId);
if (halfHeight > maximumHeight / 2) {
halfHeight = maximumHeight / 2;
}
if (halfHeight < minimumHeight / 2) {
halfHeight = minimumHeight / 2;
zone.setColorZone(colorZone);
allColorZones.push(colorZone);
}
if (ycenter - halfHeight < 0) {
ycenter = halfHeight;
}
if (ycenter + halfHeight > totalHeight) {
ycenter = totalHeight - halfHeight;
}
this._colorZonesInvalid = false;
let colorId = this._color2Id[color];
if (!colorId) {
colorId = (++this._lastAssignedId);
this._color2Id[color] = colorId;
this._id2Color[colorId] = color;
}
return new ColorZone(ycenter - halfHeight, ycenter + halfHeight, colorId, position);
allColorZones.sort(ColorZone.compare);
return allColorZones;
}
}
......@@ -5,9 +5,7 @@
'use strict';
import * as assert from 'assert';
import { OverviewRulerLane } from 'vs/editor/common/editorCommon';
import { OverviewZoneManager, ColorZone, OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
import { LIGHT } from 'vs/platform/theme/common/themeService';
suite('Editor View - OverviewZoneManager', () => {
......@@ -15,9 +13,6 @@ suite('Editor View - OverviewZoneManager', () => {
const LINE_COUNT = 50;
const LINE_HEIGHT = 20;
let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber);
manager.setMinimumHeight(6);
manager.setMaximumHeight(6);
manager.setThemeType(LIGHT);
manager.setDOMWidth(30);
manager.setDOMHeight(600);
manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT);
......@@ -25,19 +20,18 @@ suite('Editor View - OverviewZoneManager', () => {
manager.setPixelRatio(1);
manager.setZones([
new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'),
new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'),
new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'),
new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'),
new OverviewRulerZone(1, 1, '1'),
new OverviewRulerZone(10, 10, '2'),
new OverviewRulerZone(30, 31, '3'),
new OverviewRulerZone(50, 50, '4'),
]);
// one line = 12, but cap is at 6
assert.deepEqual(manager.resolveColorZones(), [
new ColorZone(12, 22, 1, OverviewRulerLane.Full), // forced height of 10
new ColorZone(123, 129, 2, OverviewRulerLane.Full), // 120 -> 132
new ColorZone(363, 369, 3, OverviewRulerLane.Full), // 360 -> 372 [360 -> 384]
new ColorZone(375, 381, 3, OverviewRulerLane.Full), // 372 -> 384 [360 -> 384]
new ColorZone(594, 600, 4, OverviewRulerLane.Full), // 588 -> 600
new ColorZone(12, 24, 1), //
new ColorZone(120, 132, 2), // 120 -> 132
new ColorZone(360, 384, 3), // 360 -> 372 [360 -> 384]
new ColorZone(588, 600, 4), // 588 -> 600
]);
});
......@@ -45,9 +39,6 @@ suite('Editor View - OverviewZoneManager', () => {
const LINE_COUNT = 50;
const LINE_HEIGHT = 20;
let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber);
manager.setMinimumHeight(6);
manager.setMaximumHeight(6);
manager.setThemeType(LIGHT);
manager.setDOMWidth(30);
manager.setDOMHeight(300);
manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT);
......@@ -55,18 +46,18 @@ suite('Editor View - OverviewZoneManager', () => {
manager.setPixelRatio(1);
manager.setZones([
new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'),
new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'),
new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'),
new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'),
new OverviewRulerZone(1, 1, '1'),
new OverviewRulerZone(10, 10, '2'),
new OverviewRulerZone(30, 31, '3'),
new OverviewRulerZone(50, 50, '4'),
]);
// one line = 6, cap is at 6
assert.deepEqual(manager.resolveColorZones(), [
new ColorZone(6, 16, 1, OverviewRulerLane.Full), // forced height of 10
new ColorZone(60, 66, 2, OverviewRulerLane.Full), // 60 -> 66
new ColorZone(180, 192, 3, OverviewRulerLane.Full), // 180 -> 192
new ColorZone(294, 300, 4, OverviewRulerLane.Full), // 294 -> 300
new ColorZone(6, 12, 1), //
new ColorZone(60, 66, 2), // 60 -> 66
new ColorZone(180, 192, 3), // 180 -> 192
new ColorZone(294, 300, 4), // 294 -> 300
]);
});
......@@ -74,9 +65,6 @@ suite('Editor View - OverviewZoneManager', () => {
const LINE_COUNT = 50;
const LINE_HEIGHT = 20;
let manager = new OverviewZoneManager((lineNumber) => LINE_HEIGHT * lineNumber);
manager.setMinimumHeight(6);
manager.setMaximumHeight(6);
manager.setThemeType(LIGHT);
manager.setDOMWidth(30);
manager.setDOMHeight(300);
manager.setOuterHeight(LINE_COUNT * LINE_HEIGHT);
......@@ -84,18 +72,18 @@ suite('Editor View - OverviewZoneManager', () => {
manager.setPixelRatio(2);
manager.setZones([
new OverviewRulerZone(1, 1, OverviewRulerLane.Full, 10, '1', '1', '1'),
new OverviewRulerZone(10, 10, OverviewRulerLane.Full, 0, '2', '2', '2'),
new OverviewRulerZone(30, 31, OverviewRulerLane.Full, 0, '3', '3', '3'),
new OverviewRulerZone(50, 50, OverviewRulerLane.Full, 0, '4', '4', '4'),
new OverviewRulerZone(1, 1, '1'),
new OverviewRulerZone(10, 10, '2'),
new OverviewRulerZone(30, 31, '3'),
new OverviewRulerZone(50, 50, '4'),
]);
// one line = 6, cap is at 12
assert.deepEqual(manager.resolveColorZones(), [
new ColorZone(12, 32, 1, OverviewRulerLane.Full), // forced height of 10 => forced height of 20
new ColorZone(120, 132, 2, OverviewRulerLane.Full), // 120 -> 132
new ColorZone(360, 384, 3, OverviewRulerLane.Full), // 360 -> 384
new ColorZone(588, 600, 4, OverviewRulerLane.Full), // 588 -> 600
new ColorZone(12, 24, 1), //
new ColorZone(120, 132, 2), // 120 -> 132
new ColorZone(360, 384, 3), // 360 -> 384
new ColorZone(588, 600, 4), // 588 -> 600
]);
});
});
......@@ -5782,6 +5782,11 @@ declare module 'vscode' {
* A string to show as place holder in the input box to guide the user.
*/
placeholder: string;
/**
* The warning threshold for lines in the input box.
*/
lineWarningLength: number | undefined;
}
interface QuickDiffProvider {
......
......@@ -391,4 +391,14 @@ export class MainThreadSCM implements MainThreadSCMShape {
repository.input.placeholder = placeholder;
}
$setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void {
const repository = this._repositories[sourceControlHandle];
if (!repository) {
return;
}
repository.input.lineWarningLength = lineWarningLength;
}
}
......@@ -410,6 +410,7 @@ export interface MainThreadSCMShape extends IDisposable {
$setInputBoxValue(sourceControlHandle: number, value: string): void;
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
$setLineWarningLength(sourceControlHandle: number, lineWarningLength: number): void;
}
export type DebugSessionUUID = string;
......
......@@ -110,7 +110,7 @@ function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.S
return result;
}
export class ExtHostSCMInputBox {
export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
private _value: string = '';
......@@ -140,6 +140,17 @@ export class ExtHostSCMInputBox {
this._placeholder = placeholder;
}
private _lineWarningLength: number | undefined;
get lineWarningLength(): number | undefined {
return this._lineWarningLength;
}
set lineWarningLength(lineWarningLength: number) {
this._proxy.$setLineWarningLength(this._sourceControlHandle, lineWarningLength);
this._lineWarningLength = lineWarningLength;
}
constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) {
// noop
}
......
......@@ -580,16 +580,22 @@ export class ViewsViewlet extends PanelViewlet {
if (this.length > 1) {
return false;
}
// Check in cache so that view do not jump. See #29609
if (ViewLocation.getContributedViewLocation(this.location.id) && !this.areExtensionsReady) {
if (ViewLocation.getContributedViewLocation(this.location.id)) {
let visibleViewsCount = 0;
this.viewsStates.forEach((viewState, id) => {
if (!viewState.isHidden) {
visibleViewsCount++;
}
});
if (this.areExtensionsReady) {
visibleViewsCount = this.getViewDescriptorsFromRegistry().reduce((visibleViewsCount, v) => visibleViewsCount + (this.canBeVisible(v) ? 1 : 0), 0);
} else {
// Check in cache so that view do not jump. See #29609
this.viewsStates.forEach((viewState, id) => {
if (!viewState.isHidden) {
visibleViewsCount++;
}
});
}
return visibleViewsCount === 1;
}
return super.isSingleView();
}
......
......@@ -46,11 +46,12 @@
if (!event || !event.view || !event.view.document) {
return;
}
var baseElement = event.view.document.getElementsByTagName('base')[0];
/** @type {any} */
var node = event.target;
while (node) {
if (node.tagName && node.tagName.toLowerCase() === 'a' && node.href) {
var baseElement = event.view.document.getElementsByTagName('base')[0];
if (node.getAttribute('href') === '#') {
event.view.scrollTo(0, 0);
} else if (node.hash && (node.getAttribute('href') === node.hash || (baseElement && node.href.indexOf(baseElement.href) >= 0))) {
......
......@@ -196,6 +196,10 @@ export default class Webview {
this._onDidClickLink.dispose();
this._disposables = dispose(this._disposables);
if (this._contextKey) {
this._contextKey.reset();
}
if (this._webview.parentElement) {
this._webview.parentElement.removeChild(this._webview);
const findWidgetDomNode = this._webviewFindWidget.getDomNode();
......
......@@ -74,5 +74,11 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
default: 'all',
description: localize('diffDecorations', "Controls diff decorations in the editor.")
},
'scm.inputCounter': {
type: 'string',
enum: ['always', 'warn', 'off'],
default: 'warn',
description: localize('inputCounter', "Controls when to display the input counter.")
}
}
});
\ No newline at end of file
......@@ -8,7 +8,7 @@
import 'vs/css!./media/scmViewlet';
import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import Event, { Emitter, chain, mapEvent } from 'vs/base/common/event';
import Event, { Emitter, chain, mapEvent, anyEvent } from 'vs/base/common/event';
import { domEvent, stop } from 'vs/base/browser/event';
import { basename } from 'vs/base/common/paths';
import { onUnexpectedError } from 'vs/base/common/errors';
......@@ -45,7 +45,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { IMessage, InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { Command } from 'vs/editor/common/modes';
......@@ -56,6 +56,7 @@ import { format } from 'vs/base/common/strings';
import { ISpliceable, ISequence, ISplice } from 'vs/base/common/sequence';
import { firstIndex } from 'vs/base/common/arrays';
import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
// TODO@Joao
// Need to subclass MenuItemActionItem in order to respect
......@@ -695,7 +696,8 @@ export class RepositoryPanel extends ViewletPanel {
@IWorkbenchEditorService protected editorService: IWorkbenchEditorService,
@IEditorGroupService protected editorGroupService: IEditorGroupService,
@IContextKeyService protected contextKeyService: IContextKeyService,
@IInstantiationService protected instantiationService: IInstantiationService
@IInstantiationService protected instantiationService: IInstantiationService,
@IConfigurationService protected configurationService: IConfigurationService
) {
super(repository.provider.label, {}, keybindingService, contextMenuService);
this.menus = instantiationService.createInstance(SCMMenus, repository.provider);
......@@ -753,10 +755,63 @@ export class RepositoryPanel extends ViewletPanel {
this.inputBox.setPlaceHolder(placeholder);
};
this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { flexibleHeight: true });
const validation = (text: string): IMessage => {
const setting = this.configurationService.getValue<'always' | 'warn' | 'off'>('scm.inputCounter');
if (setting === 'off') {
return null;
}
let position = this.inputBox.inputElement.selectionStart;
let start = 0, end;
let match: RegExpExecArray;
const regex = /\r?\n/g;
while ((match = regex.exec(text)) && position > match.index) {
start = match.index + match[0].length;
}
end = match ? match.index : text.length;
const line = text.substring(start, end);
const lineWarningLength = this.repository.input.lineWarningLength;
if (lineWarningLength === undefined) {
return {
content: localize('commitMessageInfo', "{0} characters in current line", text.length),
type: MessageType.INFO
};
}
if (line.length <= lineWarningLength) {
if (setting !== 'always') {
return null;
}
return {
content: localize('commitMessageCountdown', "{0} characters left in current line", lineWarningLength - line.length),
type: MessageType.INFO
};
} else {
return {
content: localize('commitMessageWarning', "{0} characters over {1} in current line", line.length - lineWarningLength, lineWarningLength),
type: MessageType.WARNING
};
}
};
this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, {
flexibleHeight: true,
validationOptions: { validation: validation }
});
this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService));
this.disposables.push(this.inputBox);
const onKeyUp = domEvent(this.inputBox.inputElement, 'keyup');
const onMouseUp = domEvent(this.inputBox.inputElement, 'mouseup');
anyEvent<any>(onKeyUp, onMouseUp)(() => this.inputBox.validate(), null, this.disposables);
this.inputBox.value = this.repository.input.value;
this.inputBox.onDidChange(value => this.repository.input.value = value, null, this.disposables);
this.repository.input.onDidChange(value => this.inputBox.value = value, null, this.disposables);
......
......@@ -35,14 +35,13 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history';
import pkg from 'vs/platform/node/package';
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry';
import { PANEL_BACKGROUND } from 'vs/workbench/common/theme';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
/** The amount of time to consider terminal errors to be related to the launch */
const LAUNCHING_DURATION = 500;
// Enable search functionality in xterm.js instance
XTermTerminal.loadAddon('search');
// Enable the winpty compatibility addon which will simulate wraparound mode
XTermTerminal.loadAddon('winptyCompat');
let Terminal: typeof XTermTerminal;
enum ProcessState {
// The process has not been initialized yet.
......@@ -97,6 +96,7 @@ export class TerminalInstance implements ITerminalInstance {
private _initialCwd: string;
private _windowsShellHelper: WindowsShellHelper;
private _onLineDataListeners: ((lineData: string) => void)[];
private _xtermReadyPromise: TPromise<void>;
private _widgetManager: TerminalWidgetManager;
private _linkHandler: TerminalLinkHandler;
......@@ -123,7 +123,9 @@ export class TerminalInstance implements ITerminalInstance {
@IInstantiationService private _instantiationService: IInstantiationService,
@IClipboardService private _clipboardService: IClipboardService,
@IHistoryService private _historyService: IHistoryService,
@IThemeService private _themeService: IThemeService
@IThemeService private _themeService: IThemeService,
@IConfigurationResolverService private _configurationResolverService: IConfigurationResolverService,
@IWorkspaceContextService private _workspaceContextService: IWorkspaceContextService
) {
this._instanceDisposables = [];
this._processDisposables = [];
......@@ -150,7 +152,6 @@ export class TerminalInstance implements ITerminalInstance {
this._initDimensions();
this._createProcess();
this._createXterm();
if (platform.isWindows) {
this._processReady.then(() => {
......@@ -160,10 +161,13 @@ export class TerminalInstance implements ITerminalInstance {
});
}
// Only attach xterm.js to the DOM if the terminal panel has been opened before.
if (_container) {
this.attachToElement(_container);
}
this._xtermReadyPromise = this._createXterm();
this._xtermReadyPromise.then(() => {
// Only attach xterm.js to the DOM if the terminal panel has been opened before.
if (_container) {
this.attachToElement(_container);
}
});
}
public addDisposable(disposable: lifecycle.IDisposable): void {
......@@ -248,9 +252,16 @@ export class TerminalInstance implements ITerminalInstance {
/**
* Create xterm.js instance and attach data listeners.
*/
protected _createXterm(): void {
protected async _createXterm(): TPromise<void> {
if (!Terminal) {
Terminal = (await import('xterm')).Terminal;
// Enable search functionality in xterm.js instance
Terminal.loadAddon('search');
// Enable the winpty compatibility addon which will simulate wraparound mode
Terminal.loadAddon('winptyCompat');
}
const font = this._configHelper.getFont(true);
this._xterm = new XTermTerminal({
this._xterm = new Terminal({
scrollback: this._configHelper.config.scrollback,
theme: this._getXtermTheme(),
fontFamily: font.fontFamily,
......@@ -284,100 +295,102 @@ export class TerminalInstance implements ITerminalInstance {
}
public attachToElement(container: HTMLElement): void {
if (this._wrapperElement) {
throw new Error('The terminal instance has already been attached to a container');
}
this._container = container;
this._wrapperElement = document.createElement('div');
dom.addClass(this._wrapperElement, 'terminal-wrapper');
this._xtermElement = document.createElement('div');
// Attach the xterm object to the DOM, exposing it to the smoke tests
(<any>this._wrapperElement).xterm = this._xterm;
this._xterm.open(this._xtermElement);
this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => {
// Disable all input if the terminal is exiting
if (this._isExiting) {
return false;
this._xtermReadyPromise.then(() => {
if (this._wrapperElement) {
throw new Error('The terminal instance has already been attached to a container');
}
// Skip processing by xterm.js of keyboard events that resolve to commands described
// within commandsToSkipShell
const standardKeyboardEvent = new StandardKeyboardEvent(event);
const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target);
if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
event.preventDefault();
return false;
}
this._container = container;
this._wrapperElement = document.createElement('div');
dom.addClass(this._wrapperElement, 'terminal-wrapper');
this._xtermElement = document.createElement('div');
// If tab focus mode is on, tab is not passed to the terminal
if (TabFocus.getTabFocusMode() && event.keyCode === 9) {
return false;
}
// Attach the xterm object to the DOM, exposing it to the smoke tests
(<any>this._wrapperElement).xterm = this._xterm;
return undefined;
});
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => {
// Wait until mouseup has propagated through the DOM before
// evaluating the new selection state.
setTimeout(() => this._refreshSelectionContextKey(), 0);
}));
// xterm.js currently drops selection on keyup as we need to handle this case.
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => {
// Wait until keyup has propagated through the DOM before evaluating
// the new selection state.
setTimeout(() => this._refreshSelectionContextKey(), 0);
}));
const xtermHelper: HTMLElement = <HTMLElement>this._xterm.element.querySelector('.xterm-helpers');
const focusTrap: HTMLElement = document.createElement('div');
focusTrap.setAttribute('tabindex', '0');
dom.addClass(focusTrap, 'focus-trap');
this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => {
let currentElement = focusTrap;
while (!dom.hasClass(currentElement, 'part')) {
currentElement = currentElement.parentElement;
}
const hidePanelElement = <HTMLElement>currentElement.querySelector('.hide-panel-action');
hidePanelElement.focus();
}));
xtermHelper.insertBefore(focusTrap, this._xterm.textarea);
this._xterm.open(this._xtermElement);
this._xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => {
// Disable all input if the terminal is exiting
if (this._isExiting) {
return false;
}
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => {
this._terminalFocusContextKey.set(true);
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => {
this._terminalFocusContextKey.reset();
this._refreshSelectionContextKey();
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => {
this._terminalFocusContextKey.set(true);
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => {
this._terminalFocusContextKey.reset();
this._refreshSelectionContextKey();
}));
// Skip processing by xterm.js of keyboard events that resolve to commands described
// within commandsToSkipShell
const standardKeyboardEvent = new StandardKeyboardEvent(event);
const resolveResult = this._keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target);
if (resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) {
event.preventDefault();
return false;
}
this._wrapperElement.appendChild(this._xtermElement);
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
this._linkHandler.setWidgetManager(this._widgetManager);
this._container.appendChild(this._wrapperElement);
// If tab focus mode is on, tab is not passed to the terminal
if (TabFocus.getTabFocusMode() && event.keyCode === 9) {
return false;
}
const computedStyle = window.getComputedStyle(this._container);
const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10);
const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10);
this.layout(new Dimension(width, height));
this.setVisible(this._isVisible);
this.updateConfig();
// If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal
// panel was initialized.
if (this._xterm.getOption('disableStdin')) {
this._attachPressAnyKeyToCloseListener();
}
return undefined;
});
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'mouseup', (event: KeyboardEvent) => {
// Wait until mouseup has propagated through the DOM before
// evaluating the new selection state.
setTimeout(() => this._refreshSelectionContextKey(), 0);
}));
// xterm.js currently drops selection on keyup as we need to handle this case.
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', (event: KeyboardEvent) => {
// Wait until keyup has propagated through the DOM before evaluating
// the new selection state.
setTimeout(() => this._refreshSelectionContextKey(), 0);
}));
const xtermHelper: HTMLElement = <HTMLElement>this._xterm.element.querySelector('.xterm-helpers');
const focusTrap: HTMLElement = document.createElement('div');
focusTrap.setAttribute('tabindex', '0');
dom.addClass(focusTrap, 'focus-trap');
this._instanceDisposables.push(dom.addDisposableListener(focusTrap, 'focus', (event: FocusEvent) => {
let currentElement = focusTrap;
while (!dom.hasClass(currentElement, 'part')) {
currentElement = currentElement.parentElement;
}
const hidePanelElement = <HTMLElement>currentElement.querySelector('.hide-panel-action');
hidePanelElement.focus();
}));
xtermHelper.insertBefore(focusTrap, this._xterm.textarea);
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', (event: KeyboardEvent) => {
this._terminalFocusContextKey.set(true);
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', (event: KeyboardEvent) => {
this._terminalFocusContextKey.reset();
this._refreshSelectionContextKey();
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'focus', (event: KeyboardEvent) => {
this._terminalFocusContextKey.set(true);
}));
this._instanceDisposables.push(dom.addDisposableListener(this._xterm.element, 'blur', (event: KeyboardEvent) => {
this._terminalFocusContextKey.reset();
this._refreshSelectionContextKey();
}));
this._wrapperElement.appendChild(this._xtermElement);
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
this._linkHandler.setWidgetManager(this._widgetManager);
this._container.appendChild(this._wrapperElement);
const computedStyle = window.getComputedStyle(this._container);
const width = parseInt(computedStyle.getPropertyValue('width').replace('px', ''), 10);
const height = parseInt(computedStyle.getPropertyValue('height').replace('px', ''), 10);
this.layout(new Dimension(width, height));
this.setVisible(this._isVisible);
this.updateConfig();
// If IShellLaunchConfig.waitOnExit was true and the process finished before the terminal
// panel was initialized.
if (this._xterm.getOption('disableStdin')) {
this._attachPressAnyKeyToCloseListener();
}
});
}
public registerLinkMatcher(regex: RegExp, handler: (url: string) => void, matchIndex?: number, validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void): number {
......@@ -585,16 +598,24 @@ export class TerminalInstance implements ITerminalInstance {
if (!this._shellLaunchConfig.executable) {
this._configHelper.mergeDefaultShellPathAndArgs(this._shellLaunchConfig);
}
this._initialCwd = this._getCwd(this._shellLaunchConfig, this._historyService.getLastActiveWorkspaceRoot('file'));
const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file');
this._initialCwd = this._getCwd(this._shellLaunchConfig, lastActiveWorkspaceRootUri);
// Resolve env vars from config and shell
const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
const envFromConfig = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot);
const envFromShell = TerminalInstance.resolveConfigurationVariables(this._configurationResolverService, { ...this._shellLaunchConfig.env }, lastActiveWorkspaceRoot);
this._shellLaunchConfig.env = envFromShell;
// Merge process env with the env from config
const envFromConfig = { ...process.env };
const envSettingKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
TerminalInstance.mergeEnvironments(envFromConfig, this._configHelper.config.env[envSettingKey]);
const parentEnv = { ...process.env };
TerminalInstance.mergeEnvironments(parentEnv, envFromConfig);
// Continue env initialization, merging in the env from the launch
// config and adding keys that are needed to create the process
const env = TerminalInstance.createTerminalEnv(envFromConfig, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows);
const env = TerminalInstance.createTerminalEnv(parentEnv, this._shellLaunchConfig, this._initialCwd, locale, this._cols, this._rows);
this._process = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], {
env,
cwd: Uri.parse(path.dirname(require.toUrl('../node/terminalProcess'))).fsPath
......@@ -636,6 +657,16 @@ export class TerminalInstance implements ITerminalInstance {
}, LAUNCHING_DURATION);
}
// TODO: Should be protected
private static resolveConfigurationVariables(configurationResolverService: IConfigurationResolverService, env: IStringDictionary<string>, lastActiveWorkspaceRoot: IWorkspaceFolder): IStringDictionary<string> {
Object.keys(env).forEach((key) => {
if (typeof env[key] === 'string') {
env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, env[key]);
}
});
return env;
}
private _sendPtyDataToXterm(message: { type: string, content: string }): void {
if (message.type === 'data') {
if (this._widgetManager) {
......
......@@ -20,6 +20,7 @@ import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybin
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { TPromise } from 'vs/base/common/winjs.base';
class TestTerminalInstance extends TerminalInstance {
public _getCwd(shell: IShellLaunchConfig, root: Uri): string {
......@@ -27,7 +28,7 @@ class TestTerminalInstance extends TerminalInstance {
}
protected _createProcess(): void { }
protected _createXterm(): void { }
protected _createXterm(): TPromise<void> { return TPromise.as(void 0); }
}
suite('Workbench - TerminalInstance', () => {
......
......@@ -10,7 +10,6 @@ import fs = require('fs');
import os = require('os');
import crypto = require('crypto');
import assert = require('assert');
import sudoPrompt = require('sudo-prompt');
import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData } from 'vs/platform/files/common/files';
import { MAX_FILE_SIZE } from 'vs/platform/files/node/files';
......@@ -598,14 +597,16 @@ export class FileService implements IFileService {
return this.updateContent(uri.file(tmpPath), value, writeOptions).then(() => {
// 3.) invoke our CLI as super user
return new TPromise<void>((c, e) => {
const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath };
sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => {
if (error || stderr) {
e(error || stderr);
} else {
c(void 0);
}
return (import('sudo-prompt')).then(sudoPrompt => {
return new TPromise<void>((c, e) => {
const promptOptions = { name: this.options.elevationSupport.promptTitle.replace('-', ''), icns: this.options.elevationSupport.promptIcnsPath };
sudoPrompt.exec(`"${this.options.elevationSupport.cliPath}" --write-elevated-helper "${tmpPath}" "${absolutePath}"`, promptOptions, (error: string, stdout: string, stderr: string) => {
if (error || stderr) {
e(error || stderr);
} else {
c(void 0);
}
});
});
}).then(() => {
......
......@@ -74,6 +74,8 @@ export interface ISCMInput {
placeholder: string;
readonly onDidChangePlaceholder: Event<string>;
lineWarningLength: number | undefined;
}
export interface ISCMRepository extends IDisposable {
......
......@@ -39,6 +39,8 @@ class SCMInput implements ISCMInput {
private _onDidChangePlaceholder = new Emitter<string>();
get onDidChangePlaceholder(): Event<string> { return this._onDidChangePlaceholder.event; }
public lineWarningLength: number | undefined = undefined;
}
class SCMRepository implements ISCMRepository {
......@@ -106,4 +108,4 @@ export class SCMService implements ISCMService {
return repository;
}
}
\ No newline at end of file
}
......@@ -306,5 +306,10 @@ suite('Search-integration', function () {
});
function makeExpression(...patterns: string[]): glob.IExpression {
return patterns.reduce((glob, cur) => { glob[cur] = true; return glob; }, Object.create(null));
}
\ No newline at end of file
return patterns.reduce((glob, pattern) => {
// glob.ts needs forward slashes
pattern = pattern.replace(/\\/g, '/');
glob[pattern] = true;
return glob;
}, Object.create(null));
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册