diff --git a/.github/insiders.yml b/.github/insiders.yml index 28192b556e5..5ad2cb40a96 100644 --- a/.github/insiders.yml +++ b/.github/insiders.yml @@ -1,4 +1,4 @@ { insidersLabel: 'insiders', - perform: true + perform: false } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 37898b81577..1c3f45063cf 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -81,12 +81,26 @@ { "type": "extensionHost", "request": "launch", - "name": "VS Code API Tests", + "name": "VS Code API Tests (single folder)", "runtimeExecutable": "${execPath}", "args": [ "${workspaceFolder}/extensions/vscode-api-tests/testWorkspace", "--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests", - "--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out" + "--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/singlefolder-tests" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ] + }, + { + "type": "extensionHost", + "request": "launch", + "name": "VS Code API Tests (workspace)", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceFolder}/extensions/vscode-api-tests/testWorkspace.code-workspace", + "--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests", + "--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out/workspace-tests" ], "outFiles": [ "${workspaceFolder}/out/**/*.js" @@ -129,6 +143,9 @@ "runtimeArgs": [ "--inspect=5875" ], + "skipFiles": [ + "**/winjs*.js" + ], "webRoot": "${workspaceFolder}" }, { diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json new file mode 100644 index 00000000000..8e4aded2a28 --- /dev/null +++ b/build/builtInExtensions.json @@ -0,0 +1,12 @@ +[ + { + "name": "ms-vscode.node-debug", + "version": "1.20.6", + "repo": "https://github.com/Microsoft/vscode-node-debug" + }, + { + "name": "ms-vscode.node-debug2", + "version": "1.20.2", + "repo": "https://github.com/Microsoft/vscode-node-debug2" + } +] \ No newline at end of file diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 42f1d92e2ce..385b024609b 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -20,6 +20,7 @@ const sourcemaps = require('gulp-sourcemaps'); const nlsDev = require('vscode-nls-dev'); const root = path.dirname(__dirname); const commit = util.getVersion(root); +const i18n = require('./lib/i18n'); const extensionsPath = path.join(path.dirname(__dirname), 'extensions'); @@ -29,7 +30,8 @@ const compilations = glob.sync('**/tsconfig.json', { }); const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${commit}/${out}`; -const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita']; + +const languages = i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages: []); const tasks = compilations.map(function (tsconfigFile) { const absolutePath = path.join(extensionsPath, tsconfigFile); @@ -55,9 +57,19 @@ const tasks = compilations.map(function (tsconfigFile) { const srcBase = path.join(root, 'src'); const src = path.join(srcBase, '**'); const out = path.join(root, 'out'); - const i18n = path.join(__dirname, '..', 'i18n'); + const i18nPath = path.join(__dirname, '..', 'i18n'); const baseUrl = getBaseUrl(out); + let headerId, headerOut; + let index = relativeDirname.indexOf('/'); + if (index < 0) { + headerId = relativeDirname; + headerOut = 'out'; + } else { + headerId = relativeDirname.substr(0, index); + headerOut = relativeDirname.substr(index + 1) + '/out'; + } + function createPipeline(build, emitError) { const reporter = createReporter(); @@ -82,7 +94,9 @@ const tasks = compilations.map(function (tsconfigFile) { sourceRoot: '../src' })) .pipe(tsFilter.restore) - .pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18n, out) : es.through()) + .pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18nPath, out) : es.through()) + .pipe(build ? nlsDev.bundleMetaDataFiles(headerId, headerOut) : es.through()) + .pipe(build ? nlsDev.bundleLanguageFiles() : es.through()) .pipe(reporter.end(emitError)); return es.duplex(input, output); diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index f766cfaca0f..d6402600d27 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -77,7 +77,8 @@ const indentationFilter = [ '!extensions/**/syntaxes/**', '!extensions/**/themes/**', '!extensions/**/colorize-fixtures/**', - '!extensions/vscode-api-tests/testWorkspace/**' + '!extensions/vscode-api-tests/testWorkspace/**', + '!extensions/vscode-api-tests/testWorkspace2/**' ]; const copyrightFilter = [ @@ -95,6 +96,7 @@ const copyrightFilter = [ '!**/*.xpm', '!**/*.opts', '!**/*.disabled', + '!**/*.code-workspace', '!build/**/*.init', '!resources/linux/snap/snapcraft.yaml', '!resources/win32/bin/code.js', @@ -124,6 +126,7 @@ const tslintFilter = [ '!**/node_modules/**', '!extensions/typescript/test/colorize-fixtures/**', '!extensions/vscode-api-tests/testWorkspace/**', + '!extensions/vscode-api-tests/testWorkspace2/**', '!extensions/**/*.test.ts', '!extensions/html/server/lib/jquery.d.ts' ]; diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 78a09a2db01..5747660d216 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -44,14 +44,13 @@ const nodeModules = ['electron', 'original-fs'] // Build -const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.20.2' }, - { name: 'ms-vscode.node-debug2', version: '1.20.0' } -]; +const builtInExtensions = require('./builtInExtensions'); const excludedExtensions = [ 'vscode-api-tests', - 'vscode-colorize-tests' + 'vscode-colorize-tests', + 'ms-vscode.node-debug', + 'ms-vscode.node-debug2', ]; const vscodeEntryPoints = _.flatten([ @@ -83,6 +82,7 @@ const vscodeResources = [ 'out-build/vs/workbench/services/files/**/*.exe', 'out-build/vs/workbench/services/files/**/*.md', 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js', + 'out-build/vs/code/electron-browser/issue/issueReporter.js', '!**/test/**' ]; @@ -92,10 +92,7 @@ const BUNDLED_FILE_HEADER = [ ' *--------------------------------------------------------*/' ].join('\n'); -var languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita']; -if (process.env.VSCODE_QUALITY !== 'stable') { - languages = languages.concat(['ptb', 'hun', 'trk']); // Add languages requested by the community to non-stable builds -} +const languages = i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages: []); gulp.task('clean-optimized-vscode', util.rimraf('out-vscode')); gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compile-extensions-build'], common.optimizeTask({ @@ -105,7 +102,7 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil loaderConfig: common.loaderConfig(nodeModules), header: BUNDLED_FILE_HEADER, out: 'out-vscode', - languages: languages + languages: languages, })); @@ -382,25 +379,21 @@ gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], p gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true })); // Transifex Localizations -const vscodeLanguages = [ - 'zh-hans', - 'zh-hant', - 'ja', - 'ko', - 'de', - 'fr', - 'es', - 'ru', - 'it', - 'pt-br', - 'hu', - 'tr' -]; -const setupDefaultLanguages = [ - 'zh-hans', - 'zh-hant', - 'ko' -]; + +const innoSetupConfig = { + 'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } }, + 'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } }, + 'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } }, + 'ja': { codePage: 'CP932' }, + 'de': { codePage: 'CP1252' }, + 'fr': { codePage: 'CP1252' }, + 'es': { codePage: 'CP1252' }, + 'ru': { codePage: 'CP1251' }, + 'it': { codePage: 'CP1252' }, + 'pt-br': { codePage: 'CP1252' }, + 'hu': { codePage: 'CP1250' }, + 'tr': { codePage: 'CP1254' } +}; const apiHostname = process.env.TRANSIFEX_API_URL; const apiName = process.env.TRANSIFEX_API_NAME; @@ -408,27 +401,48 @@ const apiToken = process.env.TRANSIFEX_API_TOKEN; gulp.task('vscode-translations-push', ['optimize-vscode'], function () { const pathToMetadata = './out-vscode/nls.metadata.json'; - const pathToExtensions = './extensions/**/*.nls.json'; + const pathToExtensions = './extensions/*'; const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; return es.merge( - gulp.src(pathToMetadata).pipe(i18n.prepareXlfFiles()), - gulp.src(pathToSetup).pipe(i18n.prepareXlfFiles()), - gulp.src(pathToExtensions).pipe(i18n.prepareXlfFiles('vscode-extensions')) + gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), + gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), + gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) + ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken) ).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken)); }); -gulp.task('vscode-translations-pull', function () { +gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () { + const pathToMetadata = './out-vscode/nls.metadata.json'; + const pathToExtensions = './extensions/*'; + const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}'; + return es.merge( - i18n.pullXlfFiles('vscode-editor', apiHostname, apiName, apiToken, vscodeLanguages), - i18n.pullXlfFiles('vscode-workbench', apiHostname, apiName, apiToken, vscodeLanguages), - i18n.pullXlfFiles('vscode-extensions', apiHostname, apiName, apiToken, vscodeLanguages), - i18n.pullXlfFiles('vscode-setup', apiHostname, apiName, apiToken, setupDefaultLanguages) - ).pipe(vfs.dest('../vscode-localization')); + gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()), + gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()), + gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions()) + ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken) + ).pipe(vfs.dest('../vscode-transifex-input')); +}); + +gulp.task('vscode-translations-pull', function () { + [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => { + i18n.pullCoreAndExtensionsXlfFiles(apiHostname, apiName, apiToken, language).pipe(vfs.dest(`../vscode-localization/${language.id}/build`)); + + let includeDefault = !!innoSetupConfig[language.id].defaultInfo; + i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-localization/${language.id}/setup`)); + }); }); gulp.task('vscode-translations-import', function () { - return gulp.src('../vscode-localization/**/*.xlf').pipe(i18n.prepareJsonFiles()).pipe(vfs.dest('./i18n')); + [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => { + gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`) + .pipe(i18n.prepareI18nFiles(language)) + .pipe(vfs.dest(`./i18n/${language.folderName}`)); + gulp.src(`../vscode-localization/${language.id}/setup/*/*.xlf`) + .pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id])) + .pipe(vfs.dest(`./build/win32/i18n`)); + }); }); // Sourcemaps @@ -583,3 +597,17 @@ gulp.task('generate-vscode-configuration', () => { console.error(e.toString()); }); }); + +//#region Built-In Extensions +gulp.task('clean-builtin-extensions', util.rimraf('.build/builtInExtensions')); +gulp.task('download-builtin-extensions', ['clean-builtin-extensions'], function () { + const marketplaceExtensions = es.merge(...builtInExtensions.map(extension => { + return ext.fromMarketplace(extension.name, extension.version) + .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`)); + })); + + return marketplaceExtensions + .pipe(util.setExecutableBit(['**/*.sh'])) + .pipe(vfs.dest('.build/builtInExtensions')); +}); +//#endregion diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index ee92561849e..89fb9d95264 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -110,8 +110,7 @@ function buildDebPackage(arch) { return shell.task([ 'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm ' + product.applicationName + '-' + debArch + '/DEBIAN/postrm', 'mkdir -p deb', - 'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb', - 'dpkg-scanpackages deb /dev/null > Packages' + 'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb' ], { cwd: '.build/linux/deb/' + debArch }); } diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js index 8630284bc1f..15459f7dae8 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.js @@ -13,6 +13,7 @@ const _7z = require('7zip')['7z']; const util = require('./lib/util'); const pkg = require('../package.json'); const product = require('../product.json'); +const vfs = require('vinyl-fs'); const repoPath = path.dirname(__dirname); const buildPath = arch => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`); @@ -77,7 +78,7 @@ gulp.task('vscode-win32-x64-setup', ['clean-vscode-win32-x64-setup'], buildWin32 function archiveWin32Setup(arch) { return cb => { - const args = ['a', '-tzip', zipPath(arch), '.', '-r']; + const args = ['a', '-tzip', zipPath(arch), '.', '-r', '-x!inno_updater.exe']; cp.spawn(_7z, args, { stdio: 'inherit', cwd: buildPath(arch) }) .on('error', cb) @@ -90,3 +91,13 @@ gulp.task('vscode-win32-ia32-archive', ['clean-vscode-win32-ia32-archive'], arch gulp.task('clean-vscode-win32-x64-archive', util.rimraf(zipDir('x64'))); gulp.task('vscode-win32-x64-archive', ['clean-vscode-win32-x64-archive'], archiveWin32Setup('x64')); + +function copyInnoUpdater(arch) { + return () => { + return gulp.src('build/win32/inno_updater.exe', { base: 'build/win32' }) + .pipe(vfs.dest(buildPath(arch))); + }; +} + +gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32')); +gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64')); \ No newline at end of file diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js new file mode 100644 index 00000000000..0a78f4ccffd --- /dev/null +++ b/build/lib/builtInExtensions.js @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const root = path.dirname(path.dirname(__dirname)); + +function isUpToDate(extension) { + const packagePath = path.join(root, '.build', 'builtInExtensions', extension.name, 'package.json'); + if (!fs.existsSync(packagePath)) { + return false; + } + const packageContents = fs.readFileSync(packagePath); + try { + const diskVersion = JSON.parse(packageContents).version; + return (diskVersion === extension.version); + } catch(err) { + return false; + } +} + +const builtInExtensions = require('../builtInExtensions'); +builtInExtensions.forEach((extension) => { + if (!isUpToDate(extension)) { + process.exit(1); + } +}); +process.exit(0); diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 1be9709523f..1a4fad8bdfd 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -12,8 +12,10 @@ var Is = require("is"); var xml2js = require("xml2js"); var glob = require("glob"); var https = require("https"); +var gulp = require("gulp"); var util = require('gulp-util'); var iconv = require('iconv-lite'); +var NUMBER_OF_CONCURRENT_DOWNLOADS = 4; function log(message) { var rest = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -21,6 +23,32 @@ function log(message) { } util.log.apply(util, [util.colors.green('[i18n]'), message].concat(rest)); } +exports.defaultLanguages = [ + { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' }, + { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' }, + { id: 'ja', folderName: 'jpn' }, + { id: 'ko', folderName: 'kor' }, + { id: 'de', folderName: 'deu' }, + { id: 'fr', folderName: 'fra' }, + { id: 'es', folderName: 'esn' }, + { id: 'ru', folderName: 'rus' }, + { id: 'it', folderName: 'ita' } +]; +// languages requested by the community to non-stable builds +exports.extraLanguages = [ + { id: 'pt-br', folderName: 'ptb' }, + { id: 'hu', folderName: 'hun' }, + { id: 'tr', folderName: 'trk' } +]; +exports.pseudoLanguage = { id: 'pseudo', folderName: 'pseudo', transifexId: 'pseudo' }; +// non built-in extensions also that are transifex and need to be part of the language packs +var externalExtensionsWithTranslations = [ + "azure-account", + "vscode-chrome-debug", + "vscode-chrome-debug-core", + "vscode-node-debug", + "vscode-node-debug2" +]; var LocalizeInfo; (function (LocalizeInfo) { function is(value) { @@ -116,27 +144,31 @@ var XLF = /** @class */ (function () { return this.buffer.join('\r\n'); }; XLF.prototype.addFile = function (original, keys, messages) { + if (keys.length !== messages.length) { + throw new Error("Unmatching keys(" + keys.length + ") and messages(" + messages.length + ")."); + } this.files[original] = []; - var existingKeys = []; - for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { - var key = keys_1[_i]; - // Ignore duplicate keys because Transifex does not populate those with translated values. - if (existingKeys.indexOf(key) !== -1) { + var existingKeys = new Set(); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var realKey = void 0; + var comment = void 0; + if (Is.string(key)) { + realKey = key; + comment = undefined; + } + else if (LocalizeInfo.is(key)) { + realKey = key.key; + if (key.comment && key.comment.length > 0) { + comment = key.comment.map(function (comment) { return encodeEntities(comment); }).join('\r\n'); + } + } + if (!realKey || existingKeys.has(realKey)) { continue; } - existingKeys.push(key); - var message = encodeEntities(messages[keys.indexOf(key)]); - var comment = undefined; - // Check if the message contains description (if so, it becomes an object type in JSON) - if (Is.string(key)) { - this.files[original].push({ id: key, message: message, comment: comment }); - } - else { - if (key['comment'] && key['comment'].length > 0) { - comment = key['comment'].map(function (comment) { return encodeEntities(comment); }).join('\r\n'); - } - this.files[original].push({ id: key['key'], message: message, comment: comment }); - } + existingKeys.add(realKey); + var message = encodeEntities(messages[i]); + this.files[original].push({ id: realKey, message: message, comment: comment }); } }; XLF.prototype.addStringItem = function (item) { @@ -168,20 +200,20 @@ var XLF = /** @class */ (function () { var files = []; parser.parseString(xlfString, function (err, result) { if (err) { - reject("Failed to parse XLIFF string. " + err); + reject(new Error("XLF parsing error: Failed to parse XLIFF string. " + err)); } var fileNodes = result['xliff']['file']; if (!fileNodes) { - reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.'); + reject(new Error("XLF parsing error: XLIFF file does not contain \"xliff\" or \"file\" node(s) required for parsing.")); } fileNodes.forEach(function (file) { var originalFilePath = file.$.original; if (!originalFilePath) { - reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.'); + reject(new Error("XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.")); } - var language = file.$['target-language'].toLowerCase(); + var language = file.$['target-language']; if (!language) { - reject('XLIFF file node does not contain target-language attribute to determine translated language.'); + reject(new Error("XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.")); } var messages = {}; var transUnits = file.body[0]['trans-unit']; @@ -195,10 +227,10 @@ var XLF = /** @class */ (function () { messages[key] = decodeEntities(val); } else { - reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.'); + reject(new Error("XLF parsing error: XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.")); } }); - files.push({ messages: messages, originalFilePath: originalFilePath, language: language }); + files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() }); }); resolve(files); }); @@ -207,67 +239,39 @@ var XLF = /** @class */ (function () { return XLF; }()); exports.XLF = XLF; -var iso639_3_to_2 = { - 'chs': 'zh-cn', - 'cht': 'zh-tw', - 'csy': 'cs-cz', - 'deu': 'de', - 'enu': 'en', - 'esn': 'es', - 'fra': 'fr', - 'hun': 'hu', - 'ita': 'it', - 'jpn': 'ja', - 'kor': 'ko', - 'nld': 'nl', - 'plk': 'pl', - 'ptb': 'pt-br', - 'ptg': 'pt', - 'rus': 'ru', - 'sve': 'sv-se', - 'trk': 'tr' -}; -/** - * Used to map Transifex to VS Code language code representation. - */ -var iso639_2_to_3 = { - 'zh-hans': 'chs', - 'zh-hant': 'cht', - 'cs-cz': 'csy', - 'de': 'deu', - 'en': 'enu', - 'es': 'esn', - 'fr': 'fra', - 'hu': 'hun', - 'it': 'ita', - 'ja': 'jpn', - 'ko': 'kor', - 'nl': 'nld', - 'pl': 'plk', - 'pt-br': 'ptb', - 'pt': 'ptg', - 'ru': 'rus', - 'sv-se': 'sve', - 'tr': 'trk' -}; -function sortLanguages(directoryNames) { - return directoryNames.map(function (dirName) { - var lower = dirName.toLowerCase(); - return { - name: lower, - iso639_2: iso639_3_to_2[lower] - }; - }).sort(function (a, b) { - if (!a.iso639_2 && !b.iso639_2) { - return 0; +var Limiter = /** @class */ (function () { + function Limiter(maxDegreeOfParalellism) { + this.maxDegreeOfParalellism = maxDegreeOfParalellism; + this.outstandingPromises = []; + this.runningPromises = 0; + } + Limiter.prototype.queue = function (factory) { + var _this = this; + return new Promise(function (c, e) { + _this.outstandingPromises.push({ factory: factory, c: c, e: e }); + _this.consume(); + }); + }; + Limiter.prototype.consume = function () { + var _this = this; + while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { + var iLimitedTask = this.outstandingPromises.shift(); + this.runningPromises++; + var promise = iLimitedTask.factory(); + promise.then(iLimitedTask.c).catch(iLimitedTask.e); + promise.then(function () { return _this.consumed(); }).catch(function () { return _this.consumed(); }); } - if (!a.iso639_2) { - return -1; - } - if (!b.iso639_2) { - return 1; - } - return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0); + }; + Limiter.prototype.consumed = function () { + this.runningPromises--; + this.consume(); + }; + return Limiter; +}()); +exports.Limiter = Limiter; +function sortLanguages(languages) { + return languages.sort(function (a, b) { + return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0); }); } function stripComments(content) { @@ -355,7 +359,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { defaultMessages[module] = messageMap; keys.map(function (key, i) { total++; - if (Is.string(key)) { + if (typeof key === 'string') { messageMap[key] = messages[i]; } else { @@ -364,23 +368,15 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { }); }); var languageDirectory = path.join(__dirname, '..', '..', 'i18n'); - var languageDirs; - if (languages) { - languageDirs = sortLanguages(languages); - } - else { - languageDirs = sortLanguages(fs.readdirSync(languageDirectory).filter(function (item) { return fs.statSync(path.join(languageDirectory, item)).isDirectory(); })); - } - languageDirs.forEach(function (language) { - if (!language.iso639_2) { - return; - } + var sortedLanguages = sortLanguages(languages); + sortedLanguages.forEach(function (language) { if (process.env['VSCODE_BUILD_VERBOSE']) { - log("Generating nls bundles for: " + language.iso639_2); + log("Generating nls bundles for: " + language.id); } - statistics[language.iso639_2] = 0; + statistics[language.id] = 0; var localizedModules = Object.create(null); - var cwd = path.join(languageDirectory, language.name, 'src'); + var languageFolderName = language.folderName || language.id; + var cwd = path.join(languageDirectory, languageFolderName, 'src'); modules.forEach(function (module) { var order = keysSection[module]; var i18nFile = path.join(cwd, module) + '.i18n.json'; @@ -394,12 +390,12 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { log("No localized messages found for module " + module + ". Using default messages."); } messages = defaultMessages[module]; - statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length; + statistics[language.id] = statistics[language.id] + Object.keys(messages).length; } var localizedMessages = []; order.forEach(function (keyInfo) { var key = null; - if (Is.string(keyInfo)) { + if (typeof keyInfo === 'string') { key = keyInfo; } else { @@ -411,7 +407,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { log("No localized message found for key " + key + " in module " + module + ". Using default message."); } message = defaultMessages[module][key]; - statistics[language.iso639_2] = statistics[language.iso639_2] + 1; + statistics[language.id] = statistics[language.id] + 1; } localizedMessages.push(message); }); @@ -421,7 +417,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { var modules = bundleSection[bundle]; var contents = [ fileHeader, - "define(\"" + bundle + ".nls." + language.iso639_2 + "\", {" + "define(\"" + bundle + ".nls." + language.id + "\", {" ]; modules.forEach(function (module, index) { contents.push("\t\"" + module + "\": ["); @@ -436,24 +432,17 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { contents.push(index < modules.length - 1 ? '\t],' : '\t]'); }); contents.push('});'); - emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') })); + emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') })); }); }); Object.keys(statistics).forEach(function (key) { var value = statistics[key]; log(key + " has " + value + " untranslated strings."); }); - languageDirs.forEach(function (dir) { - var language = dir.name; - var iso639_2 = iso639_3_to_2[language]; - if (!iso639_2) { - log("\tCouldn't find iso639 2 mapping for language " + language + ". Using default language instead."); - } - else { - var stats = statistics[iso639_2]; - if (Is.undef(stats)) { - log("\tNo translations found for language " + language + ". Using default language instead."); - } + sortedLanguages.forEach(function (language) { + var stats = statistics[language.id]; + if (Is.undef(stats)) { + log("\tNo translations found for language " + language.id + ". Using default language instead."); } }); } @@ -467,39 +456,16 @@ function processNlsFiles(opts) { } else { this.emit('error', "Failed to read component file: " + file.relative); + return; } if (BundledFormat.is(json)) { processCoreBundleFormat(opts.fileHeader, opts.languages, json, this); } } - this.emit('data', file); + this.queue(file); }); } exports.processNlsFiles = processNlsFiles; -function prepareXlfFiles(projectName, extensionName) { - return event_stream_1.through(function (file) { - if (!file.isBuffer()) { - throw new Error("Failed to read component file: " + file.relative); - } - var extension = path.extname(file.path); - if (extension === '.json') { - var json = JSON.parse(file.contents.toString('utf8')); - if (BundledFormat.is(json)) { - importBundleJson(file, json, this); - } - else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) { - importModuleOrPackageJson(file, json, projectName, this, extensionName); - } - else { - throw new Error("JSON format cannot be deduced for " + file.relative + "."); - } - } - else if (extension === '.isl') { - importIsl(file, this); - } - }); -} -exports.prepareXlfFiles = prepareXlfFiles; var editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup'; function getResource(sourceFile) { var resource; @@ -532,113 +498,186 @@ function getResource(sourceFile) { throw new Error("Could not identify the XLF bundle for " + sourceFile); } exports.getResource = getResource; -function importBundleJson(file, json, stream) { - var bundleXlfs = Object.create(null); - for (var source in json.keys) { - var projectResource = getResource(source); - var resource = projectResource.name; - var project = projectResource.project; - var keys = json.keys[source]; - var messages = json.messages[source]; - if (keys.length !== messages.length) { - throw new Error("There is a mismatch between keys and messages in " + file.relative); - } - var xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project); - xlf.addFile('src/' + source, keys, messages); - } - for (var resource in bundleXlfs) { - var newFilePath = bundleXlfs[resource].project + "/" + resource.replace(/\//g, '_') + ".xlf"; - var xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') }); - stream.emit('data', xlfFile); - } -} -// Keeps existing XLF instances and a state of how many files were already processed for faster file emission -var extensions = Object.create(null); -function importModuleOrPackageJson(file, json, projectName, stream, extensionName) { - if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) { - throw new Error("There is a mismatch between keys and messages in " + file.relative); - } - // Prepare the source path for attribute in XLF & extract messages from JSON - var formattedSourcePath = file.relative.replace(/\\/g, '/'); - var messages = Object.keys(json).map(function (key) { return json[key].toString(); }); - // Stores the amount of localization files to be transformed to XLF before the emission - var localizationFilesCount, originalFilePath; - // If preparing XLF for external extension, then use different glob pattern and source path - if (extensionName) { - localizationFilesCount = glob.sync('**/*.nls.json').length; - originalFilePath = "" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length); - } - else { - // Used for vscode/extensions folder - extensionName = formattedSourcePath.split('/')[0]; - localizationFilesCount = glob.sync("./extensions/" + extensionName + "/**/*.nls.json").length; - originalFilePath = "extensions/" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length); - } - var extension = extensions[extensionName] ? - extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 }; - // .nls.json can come with empty array of keys and messages, check for it - if (ModuleJsonFormat.is(json) && json.keys.length !== 0) { - extension.xlf.addFile(originalFilePath, json.keys, json.messages); - } - else if (PackageJsonFormat.is(json) && Object.keys(json).length !== 0) { - extension.xlf.addFile(originalFilePath, Object.keys(json), messages); - } - // Check if XLF is populated with file nodes to emit it - if (++extensions[extensionName].processed === localizationFilesCount) { - var newFilePath = path.join(projectName, extensionName + '.xlf'); - var xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') }); - stream.emit('data', xlfFile); - } -} -function importIsl(file, stream) { - var projectName, resourceFile; - if (path.basename(file.path) === 'Default.isl') { - projectName = setupProject; - resourceFile = 'setup_default.xlf'; - } - else { - projectName = workbenchProject; - resourceFile = 'setup_messages.xlf'; - } - var xlf = new XLF(projectName), keys = [], messages = []; - var model = new TextModel(file.contents.toString()); - var inMessageSection = false; - model.lines.forEach(function (line) { - if (line.length === 0) { - return; - } - var firstChar = line.charAt(0); - switch (firstChar) { - case ';': - // Comment line; +function createXlfFilesForCoreBundle() { + return event_stream_1.through(function (file) { + var basename = path.basename(file.path); + if (basename === 'nls.metadata.json') { + if (file.isBuffer()) { + var xlfs = Object.create(null); + var json = JSON.parse(file.contents.toString('utf8')); + for (var coreModule in json.keys) { + var projectResource = getResource(coreModule); + var resource = projectResource.name; + var project = projectResource.project; + var keys = json.keys[coreModule]; + var messages = json.messages[coreModule]; + if (keys.length !== messages.length) { + this.emit('error', "There is a mismatch between keys and messages in " + file.relative + " for module " + coreModule); + return; + } + else { + var xlf = xlfs[resource]; + if (!xlf) { + xlf = new XLF(project); + xlfs[resource] = xlf; + } + xlf.addFile("src/" + coreModule, keys, messages); + } + } + for (var resource in xlfs) { + var xlf = xlfs[resource]; + var filePath = xlf.project + "/" + resource.replace(/\//g, '_') + ".xlf"; + var xlfFile = new File({ + path: filePath, + contents: new Buffer(xlf.toString(), 'utf8') + }); + this.queue(xlfFile); + } + } + else { + this.emit('error', new Error("File " + file.relative + " is not using a buffer content")); return; - case '[': - inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; - return; - } - if (!inMessageSection) { - return; - } - var sections = line.split('='); - if (sections.length !== 2) { - throw new Error("Badly formatted message found: " + line); - } - else { - var key = sections[0]; - var value = sections[1]; - if (key.length > 0 && value.length > 0) { - keys.push(key); - messages.push(value); } } + else { + this.emit('error', new Error("File " + file.relative + " is not a core meta data file.")); + return; + } }); - var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/'); - xlf.addFile(originalPath, keys, messages); - // Emit only upon all ISL files combined into single XLF instance - var newFilePath = path.join(projectName, resourceFile); - var xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') }); - stream.emit('data', xlfFile); } +exports.createXlfFilesForCoreBundle = createXlfFilesForCoreBundle; +function createXlfFilesForExtensions() { + var counter = 0; + var folderStreamEnded = false; + var folderStreamEndEmitted = false; + return event_stream_1.through(function (extensionFolder) { + var folderStream = this; + var stat = fs.statSync(extensionFolder.path); + if (!stat.isDirectory()) { + return; + } + var extensionName = path.basename(extensionFolder.path); + if (extensionName === 'node_modules') { + return; + } + counter++; + var _xlf; + function getXlf() { + if (!_xlf) { + _xlf = new XLF(extensionsProject); + } + return _xlf; + } + gulp.src(["./extensions/" + extensionName + "/package.nls.json", "./extensions/" + extensionName + "/**/nls.metadata.json"]).pipe(event_stream_1.through(function (file) { + if (file.isBuffer()) { + var buffer = file.contents; + var basename = path.basename(file.path); + if (basename === 'package.nls.json') { + var json_1 = JSON.parse(buffer.toString('utf8')); + var keys = Object.keys(json_1); + var messages = keys.map(function (key) { + var value = json_1[key]; + if (Is.string(value)) { + return value; + } + else if (value) { + return value.message; + } + else { + return "Unknown message for key: " + key; + } + }); + getXlf().addFile("extensions/" + extensionName + "/package", keys, messages); + } + else if (basename === 'nls.metadata.json') { + var json = JSON.parse(buffer.toString('utf8')); + var relPath = path.relative("./extensions/" + extensionName, path.dirname(file.path)); + for (var file_1 in json) { + var fileContent = json[file_1]; + getXlf().addFile("extensions/" + extensionName + "/" + relPath + "/" + file_1, fileContent.keys, fileContent.messages); + } + } + else { + this.emit('error', new Error(file.path + " is not a valid extension nls file")); + return; + } + } + }, function () { + if (_xlf) { + var xlfFile = new File({ + path: path.join(extensionsProject, extensionName + '.xlf'), + contents: new Buffer(_xlf.toString(), 'utf8') + }); + folderStream.queue(xlfFile); + } + this.queue(null); + counter--; + if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) { + folderStreamEndEmitted = true; + folderStream.queue(null); + } + })); + }, function () { + folderStreamEnded = true; + if (counter === 0) { + folderStreamEndEmitted = true; + this.queue(null); + } + }); +} +exports.createXlfFilesForExtensions = createXlfFilesForExtensions; +function createXlfFilesForIsl() { + return event_stream_1.through(function (file) { + var projectName, resourceFile; + if (path.basename(file.path) === 'Default.isl') { + projectName = setupProject; + resourceFile = 'setup_default.xlf'; + } + else { + projectName = workbenchProject; + resourceFile = 'setup_messages.xlf'; + } + var xlf = new XLF(projectName), keys = [], messages = []; + var model = new TextModel(file.contents.toString()); + var inMessageSection = false; + model.lines.forEach(function (line) { + if (line.length === 0) { + return; + } + var firstChar = line.charAt(0); + switch (firstChar) { + case ';': + // Comment line; + return; + case '[': + inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; + return; + } + if (!inMessageSection) { + return; + } + var sections = line.split('='); + if (sections.length !== 2) { + throw new Error("Badly formatted message found: " + line); + } + else { + var key = sections[0]; + var value = sections[1]; + if (key.length > 0 && value.length > 0) { + keys.push(key); + messages.push(value); + } + } + }); + var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/'); + xlf.addFile(originalPath, keys, messages); + // Emit only upon all ISL files combined into single XLF instance + var newFilePath = path.join(projectName, resourceFile); + var xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') }); + this.queue(xlfFile); + }); +} +exports.createXlfFilesForIsl = createXlfFilesForIsl; function pushXlfFiles(apiHostname, username, password) { var tryGetPromises = []; var updateCreatePromises = []; @@ -664,12 +703,78 @@ function pushXlfFiles(apiHostname, username, password) { // End the pipe only after all the communication with Transifex API happened Promise.all(tryGetPromises).then(function () { Promise.all(updateCreatePromises).then(function () { - _this.emit('end'); + _this.queue(null); }).catch(function (reason) { throw new Error(reason); }); }).catch(function (reason) { throw new Error(reason); }); }); } exports.pushXlfFiles = pushXlfFiles; +function getAllResources(project, apiHostname, username, password) { + return new Promise(function (resolve, reject) { + var credentials = username + ":" + password; + var options = { + hostname: apiHostname, + path: "/api/2/project/" + project + "/resources", + auth: credentials, + method: 'GET' + }; + var request = https.request(options, function (res) { + var buffer = []; + res.on('data', function (chunk) { return buffer.push(chunk); }); + res.on('end', function () { + if (res.statusCode === 200) { + var json = JSON.parse(Buffer.concat(buffer).toString()); + if (Array.isArray(json)) { + resolve(json.map(function (o) { return o.slug; })); + return; + } + reject("Unexpected data format. Response code: " + res.statusCode + "."); + } + else { + reject("No resources in " + project + " returned no data. Response code: " + res.statusCode + "."); + } + }); + }); + request.on('error', function (err) { + reject("Failed to query resources in " + project + " with the following error: " + err + ". " + options.path); + }); + request.end(); + }); +} +function findObsoleteResources(apiHostname, username, password) { + var resourcesByProject = Object.create(null); + resourcesByProject[extensionsProject] = [].concat(externalExtensionsWithTranslations); // clone + return event_stream_1.through(function (file) { + var project = path.dirname(file.relative); + var fileName = path.basename(file.path); + var slug = fileName.substr(0, fileName.length - '.xlf'.length); + var slugs = resourcesByProject[project]; + if (!slugs) { + resourcesByProject[project] = slugs = []; + } + slugs.push(slug); + this.push(file); + }, function () { + var _this = this; + var promises = []; + var _loop_1 = function (project) { + promises.push(getAllResources(project, apiHostname, username, password).then(function (resources) { + var expectedResources = resourcesByProject[project]; + var unusedResources = resources.filter(function (resource) { return resource && expectedResources.indexOf(resource) === -1; }); + if (unusedResources.length) { + console.log("[transifex] Obsolete resources in project '" + project + "': " + unusedResources.join(', ')); + } + })); + }; + for (var project in resourcesByProject) { + _loop_1(project); + } + return Promise.all(promises).then(function (_) { + _this.push(null); + }).catch(function (reason) { throw new Error(reason); }); + }); +} +exports.findObsoleteResources = findObsoleteResources; function tryGetResource(project, slug, apiHostname, credentials) { return new Promise(function (resolve, reject) { var options = { @@ -769,40 +874,41 @@ function updateResource(project, slug, xlfFile, apiHostname, credentials) { request.end(); }); } -function obtainProjectResources(projectName) { - var resources = []; - if (projectName === editorProject) { - var json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'); - resources = JSON.parse(json).editor; - } - else if (projectName === workbenchProject) { - var json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'); - resources = JSON.parse(json).workbench; - } - else if (projectName === extensionsProject) { - var extensionsToLocalize = glob.sync('./extensions/**/*.nls.json').map(function (extension) { return extension.split('/')[2]; }); - var resourcesToPull_1 = []; - extensionsToLocalize.forEach(function (extension) { - if (resourcesToPull_1.indexOf(extension) === -1) { - resourcesToPull_1.push(extension); - resources.push({ name: extension, project: projectName }); - } +// cache resources +var _coreAndExtensionResources; +function pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language) { + if (!_coreAndExtensionResources) { + _coreAndExtensionResources = []; + // editor and workbench + var json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8')); + _coreAndExtensionResources.push.apply(_coreAndExtensionResources, json.editor); + _coreAndExtensionResources.push.apply(_coreAndExtensionResources, json.workbench); + // extensions + var extensionsToLocalize_1 = Object.create(null); + glob.sync('./extensions/**/*.nls.json').forEach(function (extension) { return extensionsToLocalize_1[extension.split('/')[2]] = true; }); + glob.sync('./extensions/*/node_modules/vscode-nls').forEach(function (extension) { return extensionsToLocalize_1[extension.split('/')[2]] = true; }); + for (var _i = 0, externalExtensionsWithTranslations_1 = externalExtensionsWithTranslations; _i < externalExtensionsWithTranslations_1.length; _i++) { + var extension = externalExtensionsWithTranslations_1[_i]; + extensionsToLocalize_1[extension] = true; + } + Object.keys(extensionsToLocalize_1).forEach(function (extension) { + _coreAndExtensionResources.push({ name: extension, project: extensionsProject }); }); } - else if (projectName === setupProject) { - resources.push({ name: 'setup_default', project: setupProject }); - } - return resources; + return pullXlfFiles(apiHostname, username, password, language, _coreAndExtensionResources); } -function pullXlfFiles(projectName, apiHostname, username, password, languages, resources) { - if (!resources) { - resources = obtainProjectResources(projectName); - } - if (!resources) { - throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.'); +exports.pullCoreAndExtensionsXlfFiles = pullCoreAndExtensionsXlfFiles; +function pullSetupXlfFiles(apiHostname, username, password, language, includeDefault) { + var setupResources = [{ name: 'setup_messages', project: workbenchProject }]; + if (includeDefault) { + setupResources.push({ name: 'setup_default', project: setupProject }); } + return pullXlfFiles(apiHostname, username, password, language, setupResources); +} +exports.pullSetupXlfFiles = pullSetupXlfFiles; +function pullXlfFiles(apiHostname, username, password, language, resources) { var credentials = username + ":" + password; - var expectedTranslationsCount = languages.length * resources.length; + var expectedTranslationsCount = resources.length; var translationsRetrieved = 0, called = false; return event_stream_1.readable(function (count, callback) { // Mark end of stream when all resources were retrieved @@ -812,48 +918,55 @@ function pullXlfFiles(projectName, apiHostname, username, password, languages, r if (!called) { called = true; var stream_1 = this; - // Retrieve XLF files from main projects - languages.map(function (language) { - resources.map(function (resource) { - retrieveResource(language, resource, apiHostname, credentials).then(function (file) { + resources.map(function (resource) { + retrieveResource(language, resource, apiHostname, credentials).then(function (file) { + if (file) { stream_1.emit('data', file); - translationsRetrieved++; - }).catch(function (error) { throw new Error(error); }); - }); + } + translationsRetrieved++; + }).catch(function (error) { throw new Error(error); }); }); } callback(); }); } -exports.pullXlfFiles = pullXlfFiles; +var limiter = new Limiter(NUMBER_OF_CONCURRENT_DOWNLOADS); function retrieveResource(language, resource, apiHostname, credentials) { - return new Promise(function (resolve, reject) { + return limiter.queue(function () { return new Promise(function (resolve, reject) { var slug = resource.name.replace(/\//g, '_'); var project = resource.project; - var iso639 = language.toLowerCase(); + var transifexLanguageId = language.transifexId || language.id; var options = { hostname: apiHostname, - path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + iso639 + "?file&mode=onlyreviewed", + path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + transifexLanguageId + "?file&mode=onlyreviewed", auth: credentials, + port: 443, method: 'GET' }; + console.log('Fetching ' + options.path); var request = https.request(options, function (res) { var xlfBuffer = []; res.on('data', function (chunk) { return xlfBuffer.push(chunk); }); res.on('end', function () { if (res.statusCode === 200) { - resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + iso639_2_to_3[language] + "/" + slug + ".xlf" })); + resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + slug + ".xlf" })); + } + else if (res.statusCode === 404) { + console.log(slug + " in " + project + " returned no data."); + resolve(null); + } + else { + reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + "."); } - reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + "."); }); }); request.on('error', function (err) { - reject("Failed to query resource " + slug + " with the following error: " + err); + reject("Failed to query resource " + slug + " with the following error: " + err + ". " + options.path); }); request.end(); - }); + }); }); } -function prepareJsonFiles() { +function prepareI18nFiles() { var parsePromises = []; return event_stream_1.through(function (xlf) { var stream = this; @@ -861,69 +974,117 @@ function prepareJsonFiles() { parsePromises.push(parsePromise); parsePromise.then(function (resolvedFiles) { resolvedFiles.forEach(function (file) { - var messages = file.messages, translatedFile; - // ISL file path always starts with 'build/' - if (/^build\//.test(file.originalFilePath)) { - var defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true }; - if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) { - return; - } - translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]); - } - else { - translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages); - } - stream.emit('data', translatedFile); + var translatedFile = createI18nFile(file.originalFilePath, file.messages); + stream.queue(translatedFile); }); - }, function (rejectReason) { - throw new Error("XLF parsing error: " + rejectReason); }); }, function () { var _this = this; Promise.all(parsePromises) - .then(function () { _this.emit('end'); }) + .then(function () { _this.queue(null); }) .catch(function (reason) { throw new Error(reason); }); }); } -exports.prepareJsonFiles = prepareJsonFiles; -function createI18nFile(base, originalFilePath, messages) { - var content = [ - '/*---------------------------------------------------------------------------------------------', - ' * Copyright (c) Microsoft Corporation. All rights reserved.', - ' * Licensed under the MIT License. See License.txt in the project root for license information.', - ' *--------------------------------------------------------------------------------------------*/', - '// Do not edit this file. It is machine generated.' - ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n'); +exports.prepareI18nFiles = prepareI18nFiles; +function createI18nFile(originalFilePath, messages) { + var result = Object.create(null); + result[''] = [ + '--------------------------------------------------------------------------------------------', + 'Copyright (c) Microsoft Corporation. All rights reserved.', + 'Licensed under the MIT License. See License.txt in the project root for license information.', + '--------------------------------------------------------------------------------------------', + 'Do not edit this file. It is machine generated.' + ]; + for (var _i = 0, _a = Object.keys(messages); _i < _a.length; _i++) { + var key = _a[_i]; + result[key] = messages[key]; + } + var content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n'); return new File({ - path: path.join(base, originalFilePath + '.i18n.json'), + path: path.join(originalFilePath + '.i18n.json'), contents: new Buffer(content, 'utf8') }); } -var languageNames = { - 'chs': 'Simplified Chinese', - 'cht': 'Traditional Chinese', - 'kor': 'Korean' -}; -var languageIds = { - 'chs': '$0804', - 'cht': '$0404', - 'kor': '$0412' -}; -var encodings = { - 'chs': 'CP936', - 'cht': 'CP950', - 'jpn': 'CP932', - 'kor': 'CP949', - 'deu': 'CP1252', - 'fra': 'CP1252', - 'esn': 'CP1252', - 'rus': 'CP1251', - 'ita': 'CP1252', - 'ptb': 'CP1252', - 'hun': 'CP1250', - 'trk': 'CP1254' -}; -function createIslFile(base, originalFilePath, messages, language) { +var i18nPackVersion = "1.0.0"; +function pullI18nPackFiles(apiHostname, username, password, language) { + return pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language).pipe(prepareI18nPackFiles()); +} +exports.pullI18nPackFiles = pullI18nPackFiles; +function prepareI18nPackFiles() { + var parsePromises = []; + var mainPack = { version: i18nPackVersion, contents: {} }; + var extensionsPacks = {}; + return event_stream_1.through(function (xlf) { + var stream = this; + var parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then(function (resolvedFiles) { + resolvedFiles.forEach(function (file) { + var path = file.originalFilePath; + var firstSlash = path.indexOf('/'); + var firstSegment = path.substr(0, firstSlash); + if (firstSegment === 'src') { + mainPack.contents[path.substr(firstSlash + 1)] = file.messages; + } + else if (firstSegment === 'extensions') { + var secondSlash = path.indexOf('/', firstSlash + 1); + var secondSegment = path.substring(firstSlash + 1, secondSlash); + if (secondSegment) { + var extPack = extensionsPacks[secondSegment]; + if (!extPack) { + extPack = extensionsPacks[secondSegment] = { version: i18nPackVersion, contents: {} }; + } + extPack.contents[path.substr(secondSlash + 1)] = file.messages; + } + else { + console.log('Unknown second segment ' + path); + } + } + else { + console.log('Unknown first segment ' + path); + } + }); + }); + }, function () { + var _this = this; + Promise.all(parsePromises) + .then(function () { + var translatedMainFile = createI18nFile('./main', mainPack); + _this.queue(translatedMainFile); + for (var extension in extensionsPacks) { + var translatedExtFile = createI18nFile("./extensions/" + extension, extensionsPacks[extension]); + _this.queue(translatedExtFile); + } + _this.queue(null); + }) + .catch(function (reason) { throw new Error(reason); }); + }); +} +exports.prepareI18nPackFiles = prepareI18nPackFiles; +function prepareIslFiles(language, innoSetupConfig) { + var parsePromises = []; + return event_stream_1.through(function (xlf) { + var stream = this; + var parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then(function (resolvedFiles) { + resolvedFiles.forEach(function (file) { + if (path.basename(file.originalFilePath) === 'Default' && !innoSetupConfig.defaultInfo) { + return; + } + var translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig); + stream.queue(translatedFile); + }); + }); + }, function () { + var _this = this; + Promise.all(parsePromises) + .then(function () { _this.queue(null); }) + .catch(function (reason) { throw new Error(reason); }); + }); +} +exports.prepareIslFiles = prepareIslFiles; +function createIslFile(originalFilePath, messages, language, innoSetup) { var content = []; var originalContent; if (path.basename(originalFilePath) === 'Default') { @@ -937,7 +1098,7 @@ function createIslFile(base, originalFilePath, messages, language) { var firstChar = line.charAt(0); if (firstChar === '[' || firstChar === ';') { if (line === '; *** Inno Setup version 5.5.3+ English messages ***') { - content.push("; *** Inno Setup version 5.5.3+ " + languageNames[language] + " messages ***"); + content.push("; *** Inno Setup version 5.5.3+ " + innoSetup.defaultInfo.name + " messages ***"); } else { content.push(line); @@ -949,13 +1110,13 @@ function createIslFile(base, originalFilePath, messages, language) { var translated = line; if (key) { if (key === 'LanguageName') { - translated = key + "=" + languageNames[language]; + translated = key + "=" + innoSetup.defaultInfo.name; } else if (key === 'LanguageID') { - translated = key + "=" + languageIds[language]; + translated = key + "=" + innoSetup.defaultInfo.id; } else if (key === 'LanguageCodePage') { - translated = key + "=" + encodings[language].substr(2); + translated = key + "=" + innoSetup.codePage.substr(2); } else { var translatedMessage = messages[key]; @@ -968,12 +1129,11 @@ function createIslFile(base, originalFilePath, messages, language) { } } }); - var tag = iso639_3_to_2[language]; var basename = path.basename(originalFilePath); - var filePath = path.join(base, path.dirname(originalFilePath), basename) + "." + tag + ".isl"; + var filePath = basename + "." + language.id + ".isl"; return new File({ path: filePath, - contents: iconv.encode(new Buffer(content.join('\r\n'), 'utf8'), encodings[language]) + contents: iconv.encode(new Buffer(content.join('\r\n'), 'utf8'), innoSetup.codePage) }); } function encodeEntities(value) { diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 93cf72c39c9..909ab84d057 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -46,10 +46,6 @@ "name": "vs/workbench/parts/execution", "project": "vscode-workbench" }, - { - "name": "vs/workbench/parts/explorers", - "project": "vscode-workbench" - }, { "name": "vs/workbench/parts/extensions", "project": "vscode-workbench" @@ -74,10 +70,6 @@ "name": "vs/workbench/parts/logs", "project": "vscode-workbench" }, - { - "name": "vs/workbench/parts/nps", - "project": "vscode-workbench" - }, { "name": "vs/workbench/parts/output", "project": "vscode-workbench" @@ -197,10 +189,6 @@ { "name": "vs/workbench/services/decorations", "project": "vscode-workbench" - }, - { - "name": "setup_messages", - "project": "vscode-workbench" } ] } \ No newline at end of file diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index db67ffc3812..a4d35c79dcb 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -6,21 +6,67 @@ import * as path from 'path'; import * as fs from 'fs'; -import { through, readable } from 'event-stream'; -import { ThroughStream } from 'through'; +import { through, readable, ThroughStream } from 'event-stream'; import File = require('vinyl'); import * as Is from 'is'; import * as xml2js from 'xml2js'; import * as glob from 'glob'; import * as https from 'https'; +import * as gulp from 'gulp'; var util = require('gulp-util'); var iconv = require('iconv-lite'); +const NUMBER_OF_CONCURRENT_DOWNLOADS = 4; + function log(message: any, ...rest: any[]): void { util.log(util.colors.green('[i18n]'), message, ...rest); } +export interface Language { + id: string; // laguage id, e.g. zh-tw, de + transifexId?: string; // language id used in transifex, e.g zh-hant, de (optional, if not set, the id is used) + folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used) +} + +export interface InnoSetup { + codePage: string; //code page for encoding (http://www.jrsoftware.org/ishelp/index.php?topic=langoptionssection) + defaultInfo?: { + name: string; // inno setup language name + id: string; // locale identifier (https://msdn.microsoft.com/en-us/library/dd318693.aspx) + }; +} + +export const defaultLanguages: Language[] = [ + { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' }, + { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' }, + { id: 'ja', folderName: 'jpn' }, + { id: 'ko', folderName: 'kor' }, + { id: 'de', folderName: 'deu' }, + { id: 'fr', folderName: 'fra' }, + { id: 'es', folderName: 'esn' }, + { id: 'ru', folderName: 'rus' }, + { id: 'it', folderName: 'ita' } +]; + +// languages requested by the community to non-stable builds +export const extraLanguages: Language[] = [ + { id: 'pt-br', folderName: 'ptb' }, + { id: 'hu', folderName: 'hun' }, + { id: 'tr', folderName: 'trk' } +]; + +export const pseudoLanguage: Language = { id: 'pseudo', folderName: 'pseudo', transifexId: 'pseudo' }; + +// non built-in extensions also that are transifex and need to be part of the language packs +const externalExtensionsWithTranslations = [ + "azure-account", + "vscode-chrome-debug", + "vscode-chrome-debug-core", + "vscode-node-debug", + "vscode-node-debug2" +]; + interface Map { [key: string]: V; } @@ -108,6 +154,20 @@ module ModuleJsonFormat { } } +interface BundledExtensionHeaderFormat { + id: string; + type: string; + hash: string; + outDir: string; +} + +interface BundledExtensionFormat { + [key: string]: { + messages: string[]; + keys: (string | LocalizeInfo)[]; + }; +} + export class Line { private buffer: string[] = []; @@ -163,30 +223,31 @@ export class XLF { return this.buffer.join('\r\n'); } - public addFile(original: string, keys: any[], messages: string[]) { + public addFile(original: string, keys: (string | LocalizeInfo)[], messages: string[]) { + if (keys.length !== messages.length) { + throw new Error(`Unmatching keys(${keys.length}) and messages(${messages.length}).`); + } this.files[original] = []; - let existingKeys = []; - - for (let key of keys) { - // Ignore duplicate keys because Transifex does not populate those with translated values. - if (existingKeys.indexOf(key) !== -1) { + let existingKeys = new Set(); + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + let realKey: string; + let comment: string; + if (Is.string(key)) { + realKey = key; + comment = undefined; + } else if (LocalizeInfo.is(key)) { + realKey = key.key; + if (key.comment && key.comment.length > 0) { + comment = key.comment.map(comment => encodeEntities(comment)).join('\r\n'); + } + } + if (!realKey || existingKeys.has(realKey)) { continue; } - existingKeys.push(key); - - let message: string = encodeEntities(messages[keys.indexOf(key)]); - let comment: string = undefined; - - // Check if the message contains description (if so, it becomes an object type in JSON) - if (Is.string(key)) { - this.files[original].push({ id: key, message: message, comment: comment }); - } else { - if (key['comment'] && key['comment'].length > 0) { - comment = key['comment'].map(comment => encodeEntities(comment)).join('\r\n'); - } - - this.files[original].push({ id: key['key'], message: message, comment: comment }); - } + existingKeys.add(realKey); + let message: string = encodeEntities(messages[i]); + this.files[original].push({ id: realKey, message: message, comment: comment }); } } @@ -228,22 +289,22 @@ export class XLF { parser.parseString(xlfString, function (err, result) { if (err) { - reject(`Failed to parse XLIFF string. ${err}`); + reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`)); } const fileNodes: any[] = result['xliff']['file']; if (!fileNodes) { - reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.'); + reject(new Error(`XLF parsing error: XLIFF file does not contain "xliff" or "file" node(s) required for parsing.`)); } fileNodes.forEach((file) => { const originalFilePath = file.$.original; if (!originalFilePath) { - reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.'); + reject(new Error(`XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.`)); } - const language = file.$['target-language'].toLowerCase(); + const language = file.$['target-language']; if (!language) { - reject('XLIFF file node does not contain target-language attribute to determine translated language.'); + reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`)); } let messages: Map = {}; @@ -259,11 +320,11 @@ export class XLF { if (key && val) { messages[key] = decodeEntities(val); } else { - reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.'); + reject(new Error(`XLF parsing error: XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.`)); } }); - files.push({ messages: messages, originalFilePath: originalFilePath, language: language }); + files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() }); }); resolve(files); @@ -272,74 +333,52 @@ export class XLF { }; } -const iso639_3_to_2: Map = { - 'chs': 'zh-cn', - 'cht': 'zh-tw', - 'csy': 'cs-cz', - 'deu': 'de', - 'enu': 'en', - 'esn': 'es', - 'fra': 'fr', - 'hun': 'hu', - 'ita': 'it', - 'jpn': 'ja', - 'kor': 'ko', - 'nld': 'nl', - 'plk': 'pl', - 'ptb': 'pt-br', - 'ptg': 'pt', - 'rus': 'ru', - 'sve': 'sv-se', - 'trk': 'tr' -}; - -/** - * Used to map Transifex to VS Code language code representation. - */ -const iso639_2_to_3: Map = { - 'zh-hans': 'chs', - 'zh-hant': 'cht', - 'cs-cz': 'csy', - 'de': 'deu', - 'en': 'enu', - 'es': 'esn', - 'fr': 'fra', - 'hu': 'hun', - 'it': 'ita', - 'ja': 'jpn', - 'ko': 'kor', - 'nl': 'nld', - 'pl': 'plk', - 'pt-br': 'ptb', - 'pt': 'ptg', - 'ru': 'rus', - 'sv-se': 'sve', - 'tr': 'trk' -}; - -interface IDirectoryInfo { - name: string; - iso639_2: string; +export interface ITask { + (): T; } -function sortLanguages(directoryNames: string[]): IDirectoryInfo[] { - return directoryNames.map((dirName) => { - var lower = dirName.toLowerCase(); - return { - name: lower, - iso639_2: iso639_3_to_2[lower] - }; - }).sort((a: IDirectoryInfo, b: IDirectoryInfo): number => { - if (!a.iso639_2 && !b.iso639_2) { - return 0; +interface ILimitedTaskFactory { + factory: ITask>; + c: (value?: T | Thenable) => void; + e: (error?: any) => void; +} + +export class Limiter { + private runningPromises: number; + private outstandingPromises: ILimitedTaskFactory[]; + + constructor(private maxDegreeOfParalellism: number) { + this.outstandingPromises = []; + this.runningPromises = 0; + } + + queue(factory: ITask>): Promise { + return new Promise((c, e) => { + this.outstandingPromises.push({ factory, c, e }); + this.consume(); + }); + } + + private consume(): void { + while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { + const iLimitedTask = this.outstandingPromises.shift(); + this.runningPromises++; + + const promise = iLimitedTask.factory(); + promise.then(iLimitedTask.c).catch(iLimitedTask.e); + promise.then(() => this.consumed()).catch(() => this.consumed()); } - if (!a.iso639_2) { - return -1; - } - if (!b.iso639_2) { - return 1; - } - return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0); + } + + private consumed(): void { + this.runningPromises--; + this.consume(); + } +} + +function sortLanguages(languages: Language[]): Language[] { + return languages.sort((a: Language, b: Language): number => { + return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0); }); } @@ -408,7 +447,7 @@ function escapeCharacters(value: string): string { return result.join(''); } -function processCoreBundleFormat(fileHeader: string, languages: string[], json: BundledFormat, emitter: any) { +function processCoreBundleFormat(fileHeader: string, languages: Language[], json: BundledFormat, emitter: ThroughStream) { let keysSection = json.keys; let messageSection = json.messages; let bundleSection = json.bundles; @@ -429,7 +468,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: defaultMessages[module] = messageMap; keys.map((key, i) => { total++; - if (Is.string(key)) { + if (typeof key === 'string') { messageMap[key] = messages[i]; } else { messageMap[key.key] = messages[i]; @@ -438,24 +477,16 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: }); let languageDirectory = path.join(__dirname, '..', '..', 'i18n'); - let languageDirs; - if (languages) { - languageDirs = sortLanguages(languages); - } else { - languageDirs = sortLanguages(fs.readdirSync(languageDirectory).filter((item) => fs.statSync(path.join(languageDirectory, item)).isDirectory())); - } - languageDirs.forEach((language) => { - if (!language.iso639_2) { - return; - } - + let sortedLanguages = sortLanguages(languages); + sortedLanguages.forEach((language) => { if (process.env['VSCODE_BUILD_VERBOSE']) { - log(`Generating nls bundles for: ${language.iso639_2}`); + log(`Generating nls bundles for: ${language.id}`); } - statistics[language.iso639_2] = 0; + statistics[language.id] = 0; let localizedModules: Map = Object.create(null); - let cwd = path.join(languageDirectory, language.name, 'src'); + let languageFolderName = language.folderName || language.id; + let cwd = path.join(languageDirectory, languageFolderName, 'src'); modules.forEach((module) => { let order = keysSection[module]; let i18nFile = path.join(cwd, module) + '.i18n.json'; @@ -468,12 +499,12 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: log(`No localized messages found for module ${module}. Using default messages.`); } messages = defaultMessages[module]; - statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length; + statistics[language.id] = statistics[language.id] + Object.keys(messages).length; } let localizedMessages: string[] = []; order.forEach((keyInfo) => { let key: string = null; - if (Is.string(keyInfo)) { + if (typeof keyInfo === 'string') { key = keyInfo; } else { key = keyInfo.key; @@ -484,7 +515,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: log(`No localized message found for key ${key} in module ${module}. Using default message.`); } message = defaultMessages[module][key]; - statistics[language.iso639_2] = statistics[language.iso639_2] + 1; + statistics[language.id] = statistics[language.id] + 1; } localizedMessages.push(message); }); @@ -494,7 +525,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: let modules = bundleSection[bundle]; let contents: string[] = [ fileHeader, - `define("${bundle}.nls.${language.iso639_2}", {` + `define("${bundle}.nls.${language.id}", {` ]; modules.forEach((module, index) => { contents.push(`\t"${module}": [`); @@ -509,29 +540,23 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json: contents.push(index < modules.length - 1 ? '\t],' : '\t]'); }); contents.push('});'); - emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') })); + emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') })); }); }); Object.keys(statistics).forEach(key => { let value = statistics[key]; log(`${key} has ${value} untranslated strings.`); }); - languageDirs.forEach(dir => { - const language = dir.name; - let iso639_2 = iso639_3_to_2[language]; - if (!iso639_2) { - log(`\tCouldn't find iso639 2 mapping for language ${language}. Using default language instead.`); - } else { - let stats = statistics[iso639_2]; - if (Is.undef(stats)) { - log(`\tNo translations found for language ${language}. Using default language instead.`); - } + sortedLanguages.forEach(language => { + let stats = statistics[language.id]; + if (Is.undef(stats)) { + log(`\tNo translations found for language ${language.id}. Using default language instead.`); } }); } -export function processNlsFiles(opts: { fileHeader: string; languages: string[] }): ThroughStream { - return through(function (file: File) { +export function processNlsFiles(opts: { fileHeader: string; languages: Language[] }): ThroughStream { + return through(function (this: ThroughStream, file: File) { let fileName = path.basename(file.path); if (fileName === 'nls.metadata.json') { let json = null; @@ -539,40 +564,16 @@ export function processNlsFiles(opts: { fileHeader: string; languages: string[] json = JSON.parse((file.contents).toString('utf8')); } else { this.emit('error', `Failed to read component file: ${file.relative}`); + return; } if (BundledFormat.is(json)) { processCoreBundleFormat(opts.fileHeader, opts.languages, json, this); } } - this.emit('data', file); + this.queue(file); }); } -export function prepareXlfFiles(projectName?: string, extensionName?: string): ThroughStream { - return through( - function (file: File) { - if (!file.isBuffer()) { - throw new Error(`Failed to read component file: ${file.relative}`); - } - - const extension = path.extname(file.path); - if (extension === '.json') { - const json = JSON.parse((file.contents).toString('utf8')); - - if (BundledFormat.is(json)) { - importBundleJson(file, json, this); - } else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) { - importModuleOrPackageJson(file, json, projectName, this, extensionName); - } else { - throw new Error(`JSON format cannot be deduced for ${file.relative}.`); - } - } else if (extension === '.isl') { - importIsl(file, this); - } - } - ); -} - const editorProject: string = 'vscode-editor', workbenchProject: string = 'vscode-workbench', extensionsProject: string = 'vscode-extensions', @@ -605,134 +606,190 @@ export function getResource(sourceFile: string): Resource { } -function importBundleJson(file: File, json: BundledFormat, stream: ThroughStream): void { - let bundleXlfs: Map = Object.create(null); +export function createXlfFilesForCoreBundle(): ThroughStream { + return through(function (this: ThroughStream, file: File) { + const basename = path.basename(file.path); + if (basename === 'nls.metadata.json') { + if (file.isBuffer()) { + const xlfs: Map = Object.create(null); + const json: BundledFormat = JSON.parse((file.contents as Buffer).toString('utf8')); + for (let coreModule in json.keys) { + const projectResource = getResource(coreModule); + const resource = projectResource.name; + const project = projectResource.project; - for (let source in json.keys) { - const projectResource = getResource(source); - const resource = projectResource.name; - const project = projectResource.project; - - const keys = json.keys[source]; - const messages = json.messages[source]; - if (keys.length !== messages.length) { - throw new Error(`There is a mismatch between keys and messages in ${file.relative}`); - } - - let xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project); - xlf.addFile('src/' + source, keys, messages); - } - - for (let resource in bundleXlfs) { - const newFilePath = `${bundleXlfs[resource].project}/${resource.replace(/\//g, '_')}.xlf`; - const xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') }); - stream.emit('data', xlfFile); - } -} - -// Keeps existing XLF instances and a state of how many files were already processed for faster file emission -var extensions: Map<{ xlf: XLF, processed: number }> = Object.create(null); -function importModuleOrPackageJson(file: File, json: ModuleJsonFormat | PackageJsonFormat, projectName: string, stream: ThroughStream, extensionName?: string): void { - if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) { - throw new Error(`There is a mismatch between keys and messages in ${file.relative}`); - } - - // Prepare the source path for attribute in XLF & extract messages from JSON - const formattedSourcePath = file.relative.replace(/\\/g, '/'); - const messages = Object.keys(json).map((key) => json[key].toString()); - - // Stores the amount of localization files to be transformed to XLF before the emission - let localizationFilesCount, - originalFilePath; - // If preparing XLF for external extension, then use different glob pattern and source path - if (extensionName) { - localizationFilesCount = glob.sync('**/*.nls.json').length; - originalFilePath = `${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; - } else { - // Used for vscode/extensions folder - extensionName = formattedSourcePath.split('/')[0]; - localizationFilesCount = glob.sync(`./extensions/${extensionName}/**/*.nls.json`).length; - originalFilePath = `extensions/${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`; - } - - let extension = extensions[extensionName] ? - extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 }; - - // .nls.json can come with empty array of keys and messages, check for it - if (ModuleJsonFormat.is(json) && json.keys.length !== 0) { - extension.xlf.addFile(originalFilePath, json.keys, json.messages); - } else if (PackageJsonFormat.is(json) && Object.keys(json).length !== 0) { - extension.xlf.addFile(originalFilePath, Object.keys(json), messages); - } - - // Check if XLF is populated with file nodes to emit it - if (++extensions[extensionName].processed === localizationFilesCount) { - const newFilePath = path.join(projectName, extensionName + '.xlf'); - const xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') }); - stream.emit('data', xlfFile); - } -} - -function importIsl(file: File, stream: ThroughStream) { - let projectName: string, - resourceFile: string; - if (path.basename(file.path) === 'Default.isl') { - projectName = setupProject; - resourceFile = 'setup_default.xlf'; - } else { - projectName = workbenchProject; - resourceFile = 'setup_messages.xlf'; - } - - let xlf = new XLF(projectName), - keys: string[] = [], - messages: string[] = []; - - let model = new TextModel(file.contents.toString()); - let inMessageSection = false; - model.lines.forEach(line => { - if (line.length === 0) { - return; - } - let firstChar = line.charAt(0); - switch (firstChar) { - case ';': - // Comment line; + const keys = json.keys[coreModule]; + const messages = json.messages[coreModule]; + if (keys.length !== messages.length) { + this.emit('error', `There is a mismatch between keys and messages in ${file.relative} for module ${coreModule}`); + return; + } else { + let xlf = xlfs[resource]; + if (!xlf) { + xlf = new XLF(project); + xlfs[resource] = xlf; + } + xlf.addFile(`src/${coreModule}`, keys, messages); + } + } + for (let resource in xlfs) { + const xlf = xlfs[resource]; + const filePath = `${xlf.project}/${resource.replace(/\//g, '_')}.xlf`; + const xlfFile = new File({ + path: filePath, + contents: new Buffer(xlf.toString(), 'utf8') + }); + this.queue(xlfFile); + } + } else { + this.emit('error', new Error(`File ${file.relative} is not using a buffer content`)); return; - case '[': - inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; - return; - } - if (!inMessageSection) { - return; - } - let sections: string[] = line.split('='); - if (sections.length !== 2) { - throw new Error(`Badly formatted message found: ${line}`); - } else { - let key = sections[0]; - let value = sections[1]; - if (key.length > 0 && value.length > 0) { - keys.push(key); - messages.push(value); } + } else { + this.emit('error', new Error(`File ${file.relative} is not a core meta data file.`)); + return; } }); +} - const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/'); - xlf.addFile(originalPath, keys, messages); +export function createXlfFilesForExtensions(): ThroughStream { + let counter: number = 0; + let folderStreamEnded: boolean = false; + let folderStreamEndEmitted: boolean = false; + return through(function (this: ThroughStream, extensionFolder: File) { + const folderStream = this; + const stat = fs.statSync(extensionFolder.path); + if (!stat.isDirectory()) { + return; + } + let extensionName = path.basename(extensionFolder.path); + if (extensionName === 'node_modules') { + return; + } + counter++; + let _xlf: XLF; + function getXlf() { + if (!_xlf) { + _xlf = new XLF(extensionsProject); + } + return _xlf; + } + gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`]).pipe(through(function (file: File) { + if (file.isBuffer()) { + const buffer: Buffer = file.contents as Buffer; + const basename = path.basename(file.path); + if (basename === 'package.nls.json') { + const json: PackageJsonFormat = JSON.parse(buffer.toString('utf8')); + const keys = Object.keys(json); + const messages = keys.map((key) => { + const value = json[key]; + if (Is.string(value)) { + return value; + } else if (value) { + return value.message; + } else { + return `Unknown message for key: ${key}`; + } + }); + getXlf().addFile(`extensions/${extensionName}/package`, keys, messages); + } else if (basename === 'nls.metadata.json') { + const json: BundledExtensionFormat = JSON.parse(buffer.toString('utf8')); + const relPath = path.relative(`./extensions/${extensionName}`, path.dirname(file.path)); + for (let file in json) { + const fileContent = json[file]; + getXlf().addFile(`extensions/${extensionName}/${relPath}/${file}`, fileContent.keys, fileContent.messages); + } + } else { + this.emit('error', new Error(`${file.path} is not a valid extension nls file`)); + return; + } + } + }, function () { + if (_xlf) { + let xlfFile = new File({ + path: path.join(extensionsProject, extensionName + '.xlf'), + contents: new Buffer(_xlf.toString(), 'utf8') + }); + folderStream.queue(xlfFile); + } + this.queue(null); + counter--; + if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) { + folderStreamEndEmitted = true; + folderStream.queue(null); + } + })); + }, function () { + folderStreamEnded = true; + if (counter === 0) { + folderStreamEndEmitted = true; + this.queue(null); + } + }); +} - // Emit only upon all ISL files combined into single XLF instance - const newFilePath = path.join(projectName, resourceFile); - const xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') }); - stream.emit('data', xlfFile); +export function createXlfFilesForIsl(): ThroughStream { + return through(function (this: ThroughStream, file: File) { + let projectName: string, + resourceFile: string; + if (path.basename(file.path) === 'Default.isl') { + projectName = setupProject; + resourceFile = 'setup_default.xlf'; + } else { + projectName = workbenchProject; + resourceFile = 'setup_messages.xlf'; + } + + let xlf = new XLF(projectName), + keys: string[] = [], + messages: string[] = []; + + let model = new TextModel(file.contents.toString()); + let inMessageSection = false; + model.lines.forEach(line => { + if (line.length === 0) { + return; + } + let firstChar = line.charAt(0); + switch (firstChar) { + case ';': + // Comment line; + return; + case '[': + inMessageSection = '[Messages]' === line || '[CustomMessages]' === line; + return; + } + if (!inMessageSection) { + return; + } + let sections: string[] = line.split('='); + if (sections.length !== 2) { + throw new Error(`Badly formatted message found: ${line}`); + } else { + let key = sections[0]; + let value = sections[1]; + if (key.length > 0 && value.length > 0) { + keys.push(key); + messages.push(value); + } + } + }); + + const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/'); + xlf.addFile(originalPath, keys, messages); + + // Emit only upon all ISL files combined into single XLF instance + const newFilePath = path.join(projectName, resourceFile); + const xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') }); + this.queue(xlfFile); + }); } export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream { let tryGetPromises = []; let updateCreatePromises = []; - return through(function (file: File) { + return through(function (this: ThroughStream, file: File) { const project = path.dirname(file.relative); const fileName = path.basename(file.path); const slug = fileName.substr(0, fileName.length - '.xlf'.length); @@ -754,12 +811,79 @@ export function pushXlfFiles(apiHostname: string, username: string, password: st // End the pipe only after all the communication with Transifex API happened Promise.all(tryGetPromises).then(() => { Promise.all(updateCreatePromises).then(() => { - this.emit('end'); + this.queue(null); }).catch((reason) => { throw new Error(reason); }); }).catch((reason) => { throw new Error(reason); }); }); } +function getAllResources(project: string, apiHostname: string, username: string, password: string): Promise { + return new Promise((resolve, reject) => { + const credentials = `${username}:${password}`; + const options = { + hostname: apiHostname, + path: `/api/2/project/${project}/resources`, + auth: credentials, + method: 'GET' + }; + + const request = https.request(options, (res) => { + let buffer: Buffer[] = []; + res.on('data', (chunk: Buffer) => buffer.push(chunk)); + res.on('end', () => { + if (res.statusCode === 200) { + let json = JSON.parse(Buffer.concat(buffer).toString()); + if (Array.isArray(json)) { + resolve(json.map(o => o.slug)); + return; + } + reject(`Unexpected data format. Response code: ${res.statusCode}.`); + } else { + reject(`No resources in ${project} returned no data. Response code: ${res.statusCode}.`); + } + }); + }); + request.on('error', (err) => { + reject(`Failed to query resources in ${project} with the following error: ${err}. ${options.path}`); + }); + request.end(); + }); +} + +export function findObsoleteResources(apiHostname: string, username: string, password: string): ThroughStream { + let resourcesByProject: Map = Object.create(null); + resourcesByProject[extensionsProject] = [].concat(externalExtensionsWithTranslations); // clone + + return through(function (this: ThroughStream, file: File) { + const project = path.dirname(file.relative); + const fileName = path.basename(file.path); + const slug = fileName.substr(0, fileName.length - '.xlf'.length); + + let slugs = resourcesByProject[project]; + if (!slugs) { + resourcesByProject[project] = slugs = []; + } + slugs.push(slug); + this.push(file); + }, function () { + let promises = []; + for (let project in resourcesByProject) { + promises.push( + getAllResources(project, apiHostname, username, password).then(resources => { + let expectedResources = resourcesByProject[project]; + let unusedResources = resources.filter(resource => resource && expectedResources.indexOf(resource) === -1); + if (unusedResources.length) { + console.log(`[transifex] Obsolete resources in project '${project}': ${unusedResources.join(', ')}`); + } + }) + ); + } + return Promise.all(promises).then(_ => { + this.push(null); + }).catch((reason) => { throw new Error(reason); }); + }); +} + function tryGetResource(project: string, slug: string, apiHostname: string, credentials: string): Promise { return new Promise((resolve, reject) => { const options = { @@ -865,42 +989,44 @@ function updateResource(project: string, slug: string, xlfFile: File, apiHostnam }); } -function obtainProjectResources(projectName: string): Resource[] { - let resources: Resource[] = []; +// cache resources +let _coreAndExtensionResources: Resource[]; - if (projectName === editorProject) { - const json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'); - resources = JSON.parse(json).editor; - } else if (projectName === workbenchProject) { - const json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'); - resources = JSON.parse(json).workbench; - } else if (projectName === extensionsProject) { - let extensionsToLocalize: string[] = glob.sync('./extensions/**/*.nls.json').map(extension => extension.split('/')[2]); - let resourcesToPull: string[] = []; +export function pullCoreAndExtensionsXlfFiles(apiHostname: string, username: string, password: string, language: Language): NodeJS.ReadableStream { + if (!_coreAndExtensionResources) { + _coreAndExtensionResources = []; + // editor and workbench + const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8')); + _coreAndExtensionResources.push(...json.editor); + _coreAndExtensionResources.push(...json.workbench); - extensionsToLocalize.forEach(extension => { - if (resourcesToPull.indexOf(extension) === -1) { // remove duplicate elements returned by glob - resourcesToPull.push(extension); - resources.push({ name: extension, project: projectName }); - } + // extensions + let extensionsToLocalize = Object.create(null); + glob.sync('./extensions/**/*.nls.json', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); + glob.sync('./extensions/*/node_modules/vscode-nls', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true); + + for (let extension of externalExtensionsWithTranslations) { + extensionsToLocalize[extension] = true; + } + + Object.keys(extensionsToLocalize).forEach(extension => { + _coreAndExtensionResources.push({ name: extension, project: extensionsProject }); }); - } else if (projectName === setupProject) { - resources.push({ name: 'setup_default', project: setupProject }); } - - return resources; + return pullXlfFiles(apiHostname, username, password, language, _coreAndExtensionResources); } -export function pullXlfFiles(projectName: string, apiHostname: string, username: string, password: string, languages: string[], resources?: Resource[]): NodeJS.ReadableStream { - if (!resources) { - resources = obtainProjectResources(projectName); - } - if (!resources) { - throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.'); +export function pullSetupXlfFiles(apiHostname: string, username: string, password: string, language: Language, includeDefault: boolean): NodeJS.ReadableStream { + let setupResources = [{ name: 'setup_messages', project: workbenchProject }]; + if (includeDefault) { + setupResources.push({ name: 'setup_default', project: setupProject }); } + return pullXlfFiles(apiHostname, username, password, language, setupResources); +} +function pullXlfFiles(apiHostname: string, username: string, password: string, language: Language, resources: Resource[]): NodeJS.ReadableStream { const credentials = `${username}:${password}`; - let expectedTranslationsCount = languages.length * resources.length; + let expectedTranslationsCount = resources.length; let translationsRetrieved = 0, called = false; return readable(function (count, callback) { @@ -912,133 +1038,186 @@ export function pullXlfFiles(projectName: string, apiHostname: string, username: if (!called) { called = true; const stream = this; - - // Retrieve XLF files from main projects - languages.map(function (language) { - resources.map(function (resource) { - retrieveResource(language, resource, apiHostname, credentials).then((file: File) => { + resources.map(function (resource) { + retrieveResource(language, resource, apiHostname, credentials).then((file: File) => { + if (file) { stream.emit('data', file); - translationsRetrieved++; - }).catch(error => { throw new Error(error); }); - }); + } + translationsRetrieved++; + }).catch(error => { throw new Error(error); }); }); } callback(); }); } +const limiter = new Limiter(NUMBER_OF_CONCURRENT_DOWNLOADS); -function retrieveResource(language: string, resource: Resource, apiHostname, credentials): Promise { - return new Promise((resolve, reject) => { +function retrieveResource(language: Language, resource: Resource, apiHostname, credentials): Promise { + return limiter.queue(() => new Promise((resolve, reject) => { const slug = resource.name.replace(/\//g, '_'); const project = resource.project; - const iso639 = language.toLowerCase(); + const transifexLanguageId = language.transifexId || language.id; const options = { hostname: apiHostname, - path: `/api/2/project/${project}/resource/${slug}/translation/${iso639}?file&mode=onlyreviewed`, + path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`, auth: credentials, + port: 443, method: 'GET' }; + console.log('Fetching ' + options.path); let request = https.request(options, (res) => { let xlfBuffer: Buffer[] = []; res.on('data', (chunk: Buffer) => xlfBuffer.push(chunk)); res.on('end', () => { if (res.statusCode === 200) { - resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${iso639_2_to_3[language]}/${slug}.xlf` })); + resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${slug}.xlf` })); + } else if (res.statusCode === 404) { + console.log(`${slug} in ${project} returned no data.`); + resolve(null); + } else { + reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`); } - reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`); }); }); request.on('error', (err) => { - reject(`Failed to query resource ${slug} with the following error: ${err}`); + reject(`Failed to query resource ${slug} with the following error: ${err}. ${options.path}`); }); request.end(); - }); + })); } -export function prepareJsonFiles(): ThroughStream { +export function prepareI18nFiles(): ThroughStream { let parsePromises: Promise[] = []; - return through(function (xlf: File) { + return through(function (this: ThroughStream, xlf: File) { let stream = this; let parsePromise = XLF.parse(xlf.contents.toString()); parsePromises.push(parsePromise); parsePromise.then( - function (resolvedFiles) { + resolvedFiles => { resolvedFiles.forEach(file => { - let messages = file.messages, translatedFile; - - // ISL file path always starts with 'build/' - if (/^build\//.test(file.originalFilePath)) { - const defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true }; - if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) { - return; - } - - translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]); - } else { - translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages); - } - - stream.emit('data', translatedFile); + let translatedFile = createI18nFile(file.originalFilePath, file.messages); + stream.queue(translatedFile); }); - }, - function (rejectReason) { - throw new Error(`XLF parsing error: ${rejectReason}`); } ); }, function () { Promise.all(parsePromises) - .then(() => { this.emit('end'); }) + .then(() => { this.queue(null); }) .catch(reason => { throw new Error(reason); }); }); } -function createI18nFile(base: string, originalFilePath: string, messages: Map): File { - let content = [ - '/*---------------------------------------------------------------------------------------------', - ' * Copyright (c) Microsoft Corporation. All rights reserved.', - ' * Licensed under the MIT License. See License.txt in the project root for license information.', - ' *--------------------------------------------------------------------------------------------*/', - '// Do not edit this file. It is machine generated.' - ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n'); +function createI18nFile(originalFilePath: string, messages: any): File { + let result = Object.create(null); + result[''] = [ + '--------------------------------------------------------------------------------------------', + 'Copyright (c) Microsoft Corporation. All rights reserved.', + 'Licensed under the MIT License. See License.txt in the project root for license information.', + '--------------------------------------------------------------------------------------------', + 'Do not edit this file. It is machine generated.' + ]; + for (let key of Object.keys(messages)) { + result[key] = messages[key]; + } + let content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n'); return new File({ - path: path.join(base, originalFilePath + '.i18n.json'), + path: path.join(originalFilePath + '.i18n.json'), contents: new Buffer(content, 'utf8') }); } +interface I18nPack { + version: string; + contents: { + [path: string]: Map; + }; +} -const languageNames: Map = { - 'chs': 'Simplified Chinese', - 'cht': 'Traditional Chinese', - 'kor': 'Korean' -}; +const i18nPackVersion = "1.0.0"; -const languageIds: Map = { - 'chs': '$0804', - 'cht': '$0404', - 'kor': '$0412' -}; +export function pullI18nPackFiles(apiHostname: string, username: string, password: string, language: Language): NodeJS.ReadableStream { + return pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language).pipe(prepareI18nPackFiles()); +} -const encodings: Map = { - 'chs': 'CP936', - 'cht': 'CP950', - 'jpn': 'CP932', - 'kor': 'CP949', - 'deu': 'CP1252', - 'fra': 'CP1252', - 'esn': 'CP1252', - 'rus': 'CP1251', - 'ita': 'CP1252', - 'ptb': 'CP1252', - 'hun': 'CP1250', - 'trk': 'CP1254' -}; +export function prepareI18nPackFiles() { + let parsePromises: Promise[] = []; + let mainPack: I18nPack = { version: i18nPackVersion, contents: {} }; + let extensionsPacks: Map = {}; + return through(function (this: ThroughStream, xlf: File) { + let stream = this; + let parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then( + resolvedFiles => { + resolvedFiles.forEach(file => { + const path = file.originalFilePath; + const firstSlash = path.indexOf('/'); + const firstSegment = path.substr(0, firstSlash); + if (firstSegment === 'src') { + mainPack.contents[path.substr(firstSlash + 1)] = file.messages; + } else if (firstSegment === 'extensions') { + const secondSlash = path.indexOf('/', firstSlash + 1); + const secondSegment = path.substring(firstSlash + 1, secondSlash); + if (secondSegment) { + let extPack = extensionsPacks[secondSegment]; + if (!extPack) { + extPack = extensionsPacks[secondSegment] = { version: i18nPackVersion, contents: {} }; + } + extPack.contents[path.substr(secondSlash + 1)] = file.messages; + } else { + console.log('Unknown second segment ' + path); + } + } else { + console.log('Unknown first segment ' + path); + } + }); + } + ); + }, function () { + Promise.all(parsePromises) + .then(() => { + const translatedMainFile = createI18nFile('./main', mainPack); + this.queue(translatedMainFile); + for (let extension in extensionsPacks) { + const translatedExtFile = createI18nFile(`./extensions/${extension}`, extensionsPacks[extension]); + this.queue(translatedExtFile); + } + this.queue(null); + }) + .catch(reason => { throw new Error(reason); }); + }); +} -function createIslFile(base: string, originalFilePath: string, messages: Map, language: string): File { +export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup): ThroughStream { + let parsePromises: Promise[] = []; + + return through(function (this: ThroughStream, xlf: File) { + let stream = this; + let parsePromise = XLF.parse(xlf.contents.toString()); + parsePromises.push(parsePromise); + parsePromise.then( + resolvedFiles => { + resolvedFiles.forEach(file => { + if (path.basename(file.originalFilePath) === 'Default' && !innoSetupConfig.defaultInfo) { + return; + } + let translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig); + stream.queue(translatedFile); + }); + } + ); + }, function () { + Promise.all(parsePromises) + .then(() => { this.queue(null); }) + .catch(reason => { throw new Error(reason); }); + }); +} + +function createIslFile(originalFilePath: string, messages: Map, language: Language, innoSetup: InnoSetup): File { let content: string[] = []; let originalContent: TextModel; if (path.basename(originalFilePath) === 'Default') { @@ -1046,13 +1225,12 @@ function createIslFile(base: string, originalFilePath: string, messages: Map { if (line.length > 0) { let firstChar = line.charAt(0); if (firstChar === '[' || firstChar === ';') { if (line === '; *** Inno Setup version 5.5.3+ English messages ***') { - content.push(`; *** Inno Setup version 5.5.3+ ${languageNames[language]} messages ***`); + content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo.name} messages ***`); } else { content.push(line); } @@ -1062,11 +1240,11 @@ function createIslFile(base: string, originalFilePath: string, messages: Map NodeJS.ReadWriteStream { const entryPoints = opts.entryPoints; @@ -239,7 +239,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr })) .pipe(gulp.dest(out)); }; -}; +} declare class FileWithCopyright extends VinylFile { public __hasOurCopyright: boolean; @@ -324,4 +324,4 @@ export function minifyTask(src: string, sourceMapBaseUrl: string): (cb: any) => cb(err); }); }; -}; +} diff --git a/build/lib/typings/event-stream.d.ts b/build/lib/typings/event-stream.d.ts index 7e5ccee5e17..d79ac9183d0 100644 --- a/build/lib/typings/event-stream.d.ts +++ b/build/lib/typings/event-stream.d.ts @@ -1,7 +1,14 @@ declare module "event-stream" { import { Stream } from 'stream'; - import { ThroughStream } from 'through'; + import { ThroughStream as _ThroughStream} from 'through'; import { MapStream } from 'map-stream'; + import * as File from 'vinyl'; + + export interface ThroughStream extends _ThroughStream { + queue(data: File | null); + push(data: File | null); + paused: boolean; + } function merge(streams: Stream[]): ThroughStream; function merge(...streams: Stream[]): ThroughStream; diff --git a/build/npm/update-localization-extension.js b/build/npm/update-localization-extension.js new file mode 100644 index 00000000000..ca8a4139d6d --- /dev/null +++ b/build/npm/update-localization-extension.js @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +let i18n = require("../lib/i18n"); + +let fs = require("fs"); +let path = require("path"); +let vfs = require("vinyl-fs"); +let rimraf = require('rimraf'); + +function update(idOrPath) { + if (!idOrPath) { + throw new Error('Argument must be the location of the localization extension.'); + return; + } + let locExtFolder = idOrPath; + if (/^\w{2}(-\w+)?$/.test(idOrPath)) { + locExtFolder = '../vscode-localization-' + idOrPath; + } + let locExtStat = fs.statSync(locExtFolder); + if (!locExtStat || !locExtStat.isDirectory) { + throw new Error('No directory found at ' + idOrPath); + } + let packageJSON = JSON.parse(fs.readFileSync(path.join(locExtFolder, 'package.json')).toString()); + let contributes = packageJSON['contributes']; + if (!contributes) { + throw new Error('The extension must define a "localizations" contribution in the "package.json"'); + } + let localizations = contributes['localizations']; + if (!localizations) { + throw new Error('The extension must define a "localizations" contribution of type array in the "package.json"'); + } + + localizations.forEach(function (localization) { + if (!localization.languageId || !localization.languageName || !localization.translations) { + throw new Error('Each localization contribution must define "languageId", "languageName" and "translations" properties.'); + } + let server = localization.server || 'www.transifex.com'; + let userName = localization.userName || 'api'; + let apiToken = process.env.TRANSIFEX_API_TOKEN; + let languageId = localization.transifexId || localization.languageId; + let translationDataFolder = path.join(locExtFolder, localization.translations); + + if (fs.existsSync(translationDataFolder) && fs.existsSync(path.join(translationDataFolder, 'main.i18n.json'))) { + console.log('Clearing \'' + translationDataFolder + '\'...'); + rimraf.sync(translationDataFolder); + } + + console.log('Downloading translations for \'' + languageId + '\' to \'' + translationDataFolder + '\'...'); + i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }) + .pipe(vfs.dest(translationDataFolder)); + }); + + +} +if (path.basename(process.argv[1]) === 'update-localization-extension.js') { + update(process.argv[2]); +} diff --git a/build/tfs/common/publish.ts b/build/tfs/common/publish.ts index e4cbdc80f0e..ca580ce1b4d 100644 --- a/build/tfs/common/publish.ts +++ b/build/tfs/common/publish.ts @@ -69,6 +69,7 @@ interface Asset { hash: string; sha256hash: string; size: number; + supportsFastUpdate?: boolean; } function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise { @@ -234,6 +235,13 @@ async function publish(commit: string, quality: string, platform: string, type: size }; + // Remove this if we ever need to rollback fast updates for windows + if (/win32/.test(platform)) { + asset.supportsFastUpdate = true; + } + + console.log('Asset:', JSON.stringify(asset, null, ' ')); + const release = { id: commit, timestamp: (new Date()).getTime(), diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1 index bc6ade13de3..0fcb56c1b9e 100644 --- a/build/tfs/win32/1_build.ps1 +++ b/build/tfs/win32/1_build.ps1 @@ -45,6 +45,10 @@ step "Build minified" { exec { & npm run gulp -- "vscode-win32-$global:arch-min" } } +step "Copy Inno updater" { + exec { & npm run gulp -- "vscode-win32-$global:arch-copy-inno-updater" } +} + # step "Create loader snapshot" { # exec { & node build\lib\snapshotLoader.js --arch=$global:arch } # } diff --git a/build/tslint.json b/build/tslint.json index a85e98b95dc..15275279139 100644 --- a/build/tslint.json +++ b/build/tslint.json @@ -9,5 +9,6 @@ "always" ], "triple-equals": true - } + }, + "defaultSeverity": "warning" } \ No newline at end of file diff --git a/build/win32/code.iss b/build/win32/code.iss index f4374ee099d..4230f7d0517 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -18,7 +18,7 @@ OutputDir={#OutputDir} OutputBaseFilename=VSCodeSetup Compression=lzma SolidCompression=yes -AppMutex={#AppMutex} +AppMutex={code:GetAppMutex} SetupMutex={#AppMutex}setup WizardImageFile={#RepoDir}\resources\win32\inno-big.bmp WizardSmallImageFile={#RepoDir}\resources\win32\inno-small.bmp @@ -47,11 +47,15 @@ Name: "simplifiedChinese"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.zh Name: "traditionalChinese"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.zh-tw.isl,{#RepoDir}\build\win32\i18n\messages.zh-tw.isl" {#LocalizedLanguageFile("cht")} [InstallDelete] -Type: filesandordirs; Name: {app}\resources\app\out -Type: filesandordirs; Name: {app}\resources\app\plugins -Type: filesandordirs; Name: {app}\resources\app\extensions -Type: filesandordirs; Name: {app}\resources\app\node_modules -Type: files; Name: {app}\resources\app\Credits_45.0.2454.85.html +Type: filesandordirs; Name: "{app}\resources\app\out"; Check: IsNotUpdate +Type: filesandordirs; Name: "{app}\resources\app\plugins"; Check: IsNotUpdate +Type: filesandordirs; Name: "{app}\resources\app\extensions"; Check: IsNotUpdate +Type: filesandordirs; Name: "{app}\resources\app\node_modules"; Check: IsNotUpdate +Type: files; Name: "{app}\resources\app\Credits_45.0.2454.85.html"; Check: IsNotUpdate + +[UninstallDelete] +Type: filesandordirs; Name: "{app}\_" +Type: filesandordirs; Name: "{app}\old" [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked @@ -63,7 +67,8 @@ Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}" Name: "runcode"; Description: "{cm:RunAfter,{#NameShort}}"; GroupDescription: "{cm:Other}"; Check: WizardSilent [Files] -Source: "*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "*"; Excludes: "inno_updater.exe"; DestDir: "{code:GetDestDir}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "inno_updater.exe"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs [Icons] Name: "{group}\{#NameLong}"; Filename: "{app}\{#ExeBasename}.exe"; AppUserModelID: "{#AppUserId}" @@ -71,7 +76,7 @@ Name: "{commondesktop}\{#NameLong}"; Filename: "{app}\{#ExeBasename}.exe"; Tasks Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#NameLong}"; Filename: "{app}\{#ExeBasename}.exe"; Tasks: quicklaunchicon; AppUserModelID: "{#AppUserId}" [Run] -Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong}}"; Tasks: runcode; Flags: nowait postinstall; Check: WizardSilent +Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong}}"; Tasks: runcode; Flags: nowait postinstall; Check: ShouldRunAfterUpdate Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong}}"; Flags: nowait postinstall; Check: WizardNotSilent [Registry] @@ -955,6 +960,75 @@ begin Result := not WizardSilent(); end; +// Updates +function IsBackgroundUpdate(): Boolean; +begin + Result := ExpandConstant('{param:update|false}') <> 'false'; +end; + +function IsNotUpdate(): Boolean; +begin + Result := not IsBackgroundUpdate(); +end; + +// VS Code will create a flag file before the update starts (/update=C:\foo\bar) +// - if the file exists at this point, the user quit Code before the update finished, so don't start Code after update +// - otherwise, the user has accepted to apply the update and Code should start +function LockFileExists(): Boolean; +begin + Result := FileExists(ExpandConstant('{param:update}')) +end; + +function ShouldRunAfterUpdate(): Boolean; +begin + if IsBackgroundUpdate() then + Result := not LockFileExists() + else + Result := True; +end; + +function GetAppMutex(Value: string): string; +begin + if IsBackgroundUpdate() then + Result := '' + else + Result := '{#AppMutex}'; +end; + +function GetDestDir(Value: string): string; +begin + if IsBackgroundUpdate() then + Result := ExpandConstant('{app}\_') + else + Result := ExpandConstant('{app}'); +end; + +function BoolToStr(Value: Boolean): String; +begin + if Value then + Result := 'true' + else + Result := 'false'; +end; + +procedure CurStepChanged(CurStep: TSetupStep); +var + UpdateResultCode: Integer; +begin + if IsBackgroundUpdate() and (CurStep = ssPostInstall) then + begin + CreateMutex('{#AppMutex}-ready'); + + while (CheckForMutexes('{#AppMutex}')) do + begin + Log('Application is still running, waiting'); + Sleep(1000); + end; + + Exec(ExpandConstant('{app}\inno_updater.exe'), ExpandConstant('_ "{app}\unins000.dat" ' + BoolToStr(LockFileExists())), '', SW_SHOW, ewWaitUntilTerminated, UpdateResultCode); + end; +end; + // http://stackoverflow.com/a/23838239/261019 procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String); var diff --git a/build/win32/inno_updater.exe b/build/win32/inno_updater.exe new file mode 100644 index 00000000000..2d5d1ab1d49 Binary files /dev/null and b/build/win32/inno_updater.exe differ diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index cbf3960da86..ed2819ba97f 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "jsonc-parser": "^1.0.0", - "vscode-nls": "^2.0.1" + "vscode-nls": "^3.1.2" }, "contributes": { "jsonValidation": [ diff --git a/extensions/configuration-editing/src/extension.ts b/extensions/configuration-editing/src/extension.ts index e215f0fb5a9..ab31432ee85 100644 --- a/extensions/configuration-editing/src/extension.ts +++ b/extensions/configuration-editing/src/extension.ts @@ -2,16 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - 'use strict'; +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); import * as vscode from 'vscode'; import { getLocation, visit, parse } from 'jsonc-parser'; import * as path from 'path'; import { SettingsDocument } from './settingsDocumentHelper'; -import * as nls from 'vscode-nls'; - -const localize = nls.loadMessageBundle(); const decoration = vscode.window.createTextEditorDecorationType({ color: '#9e9e9e' @@ -30,6 +28,9 @@ export function activate(context: vscode.ExtensionContext): void { //extensions suggestions context.subscriptions.push(...registerExtensionsCompletions()); + //locale suggestions + context.subscriptions.push(registerLocaleCompletionsInLanguageDocument()); + // launch.json decorations context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions)); context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(event => { @@ -67,6 +68,44 @@ function registerSettingsCompletions(): vscode.Disposable { }); } +function registerLocaleCompletionsInLanguageDocument(): vscode.Disposable { + return vscode.languages.registerCompletionItemProvider({ pattern: '**/locale.json' }, { + provideCompletionItems(document, position, token) { + const location = getLocation(document.getText(), document.offsetAt(position)); + const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position); + if (location.path[0] === 'locale') { + const extensionsContent = parse(document.getText()); + return provideContributedLocalesProposals(range); + } + return []; + } + }); +} + +function provideContributedLocalesProposals(range: vscode.Range): vscode.ProviderResult { + const contributedLocales: string[] = []; + for (const extension of vscode.extensions.all) { + if (extension.packageJSON && extension.packageJSON['contributes'] && extension.packageJSON['contributes']['localizations'] && extension.packageJSON['contributes']['localizations'].length) { + const localizations: { languageId: string }[] = extension.packageJSON['contributes']['localizations']; + for (const localization of localizations) { + if (contributedLocales.indexOf(localization.languageId) === -1) { + contributedLocales.push(localization.languageId); + } + } + } + } + return contributedLocales.map(locale => { + const text = `"${locale}"`; + const item = new vscode.CompletionItem(text); + item.kind = vscode.CompletionItemKind.Value; + item.insertText = text; + item.range = range; + item.filterText = text; + return item; + }); +} + + interface IExtensionsContent { recommendations: string[]; } diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock index 6e178dd74ea..3aecfb034d5 100644 --- a/extensions/configuration-editing/yarn.lock +++ b/extensions/configuration-editing/yarn.lock @@ -10,6 +10,6 @@ jsonc-parser@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272" -vscode-nls@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/css/client/src/cssMain.ts b/extensions/css/client/src/cssMain.ts index 6c64c46a54e..930deba4a6e 100644 --- a/extensions/css/client/src/cssMain.ts +++ b/extensions/css/client/src/cssMain.ts @@ -3,18 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; - import * as path from 'path'; +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); + import { languages, window, commands, ExtensionContext, TextDocument, ColorInformation, ColorPresentation, Color, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; import { ConfigurationFeature } from 'vscode-languageclient/lib/configuration.proposed'; import { DocumentColorRequest, DocumentColorParams, ColorPresentationRequest, ColorPresentationParams } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; -import * as nls from 'vscode-nls'; -let localize = nls.loadMessageBundle(); - // this method is called when vs code is activated export function activate(context: ExtensionContext) { diff --git a/extensions/css/package.json b/extensions/css/package.json index e404748578a..5f4354623e6 100644 --- a/extensions/css/package.json +++ b/extensions/css/package.json @@ -714,7 +714,7 @@ }, "dependencies": { "vscode-languageclient": "^3.5.0", - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/css/yarn.lock b/extensions/css/yarn.lock index f50be178c48..e6c3983fb99 100644 --- a/extensions/css/yarn.lock +++ b/extensions/css/yarn.lock @@ -27,6 +27,6 @@ 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" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 5085e13b2b6..8e9c4b0236e 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -317,9 +317,9 @@ "@emmetio/html-matcher": "^0.3.3", "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", "@emmetio/math-expression": "^0.1.1", - "vscode-emmet-helper": "^1.1.20", + "vscode-emmet-helper": "^1.1.21", "vscode-languageserver-types": "^3.5.0", "image-size": "^0.5.2", - "vscode-nls": "2.0.2" + "vscode-nls": "3.1.2" } } \ No newline at end of file diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index e6e3d58ae97..02ac3f982b3 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -336,7 +336,9 @@ export function getEmmetConfiguration(syntax: string) { showExpandedAbbreviation: emmetConfig['showExpandedAbbreviation'], showAbbreviationSuggestions: emmetConfig['showAbbreviationSuggestions'], syntaxProfiles, - variables: emmetConfig['variables'] + variables: emmetConfig['variables'], + excludeLanguages: emmetConfig['excludeLanguages'], + showSuggestionsAsSnippets: emmetConfig['showSuggestionsAsSnippets'] }; } diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 5ba2df336e0..bc19aef330b 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -1027,6 +1027,10 @@ json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" +jsonc-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -2048,11 +2052,12 @@ vinyl@~2.0.1: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vscode-emmet-helper@^1.1.20: - version "1.1.20" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-1.1.20.tgz#7523dc7f635f74e4becc44d4e519a9db5055a023" +vscode-emmet-helper@^1.1.21: + version "1.1.21" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-1.1.21.tgz#4c77c2c5f5acc316d9a47cc564a51a732609ef7b" dependencies: "@emmetio/extract-abbreviation" "^0.1.1" + jsonc-parser "^1.0.0" vscode-languageserver-types "^3.0.3" vscode-languageserver-types@^3.0.3: @@ -2063,9 +2068,9 @@ 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" +vscode-nls@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.0.tgz#a8a264c0d4bd3e1ed4746a9883235fec5b62968a" vscode@1.0.1: version "1.0.1" diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index 8f4b631803e..fe7e6bdb413 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -23,7 +23,7 @@ "jsonc-parser": "^1.0.0", "markdown-it": "^8.3.1", "parse5": "^3.0.2", - "vscode-nls": "^2.0.1" + "vscode-nls": "^3.1.2" }, "contributes": { "jsonValidation": [ diff --git a/extensions/extension-editing/src/extensionLinter.ts b/extensions/extension-editing/src/extensionLinter.ts index 63dab8afefb..0e486252598 100644 --- a/extensions/extension-editing/src/extensionLinter.ts +++ b/extensions/extension-editing/src/extensionLinter.ts @@ -6,8 +6,10 @@ import * as fs from 'fs'; import * as path from 'path'; -import { parseTree, findNodeAtLocation, Node as JsonNode } from 'jsonc-parser'; import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); + +import { parseTree, findNodeAtLocation, Node as JsonNode } from 'jsonc-parser'; import * as MarkdownItType from 'markdown-it'; import { languages, workspace, Disposable, TextDocument, Uri, Diagnostic, Range, DiagnosticSeverity, Position } from 'vscode'; @@ -15,8 +17,6 @@ import { languages, workspace, Disposable, TextDocument, Uri, Diagnostic, Range, const product = require('../../../product.json'); const allowedBadgeProviders: string[] = (product.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase()); -const localize = nls.loadMessageBundle(); - const httpsRequired = localize('httpsRequired', "Images must use the HTTPS protocol."); const svgsNotValid = localize('svgsNotValid', "SVGs are not a valid image source."); const embeddedSvgsNotValid = localize('embeddedSvgsNotValid', "Embedded SVGs are not a valid image source."); diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock index ce500bb28a0..e0072b69ac8 100644 --- a/extensions/extension-editing/yarn.lock +++ b/extensions/extension-editing/yarn.lock @@ -58,6 +58,6 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" -vscode-nls@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/git/package.json b/extensions/git/package.json index 645361ff5ec..5834266c26e 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -726,7 +726,7 @@ }, { "command": "git.openFile2", - "when": "scmProvider == git && scmResourceGroup == merge", + "when": "scmProvider == git && scmResourceGroup == merge && config.git.showInlineOpenFileAction", "group": "inline0" }, { @@ -756,7 +756,7 @@ }, { "command": "git.openFile2", - "when": "scmProvider == git && scmResourceGroup == index", + "when": "scmProvider == git && scmResourceGroup == index && config.git.showInlineOpenFileAction", "group": "inline0" }, { @@ -796,7 +796,7 @@ }, { "command": "git.openFile2", - "when": "scmProvider == git && scmResourceGroup == workingTree", + "when": "scmProvider == git && scmResourceGroup == workingTree && config.git.showInlineOpenFileAction", "group": "inline0" }, { @@ -936,6 +936,16 @@ "type": "boolean", "default": true, "description": "%config.decorations.enabled%" + }, + "git.promptToSaveFilesBeforeCommit": { + "type": "boolean", + "default": false, + "description": "%config.promptToSaveFilesBeforeCommit%" + }, + "git.showInlineOpenFileAction": { + "type": "boolean", + "default": true, + "description": "%config.showInlineOpenFileAction%" } } }, @@ -1001,7 +1011,7 @@ "file-type": "^7.2.0", "iconv-lite": "0.4.19", "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "2.0.2", + "vscode-nls": "^3.1.2", "which": "^1.3.0" }, "devDependencies": { diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 179c430eb4b..28c41092842 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -55,7 +55,7 @@ "config.enableLongCommitWarning": "Whether long commit messages should be warned about", "config.confirmSync": "Confirm before synchronizing git repositories", "config.countBadge": "Controls the git badge counter. `all` counts all changes. `tracked` counts only the tracked changes. `off` turns it off.", - "config.checkoutType": "Controls what type of branches are listed when running `Checkout to...`. `all` shows all refs, `local` shows only the local branchs, `tags` shows only tags and `remote` shows only remote branches.", + "config.checkoutType": "Controls what type of branches are listed when running `Checkout to...`. `all` shows all refs, `local` shows only the local branches, `tags` shows only tags and `remote` shows only remote branches.", "config.ignoreLegacyWarning": "Ignores the legacy Git warning", "config.ignoreMissingGitWarning": "Ignores the warning when Git is missing", "config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository", @@ -64,6 +64,8 @@ "config.enableCommitSigning": "Enables commit signing with GPG.", "config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.", "config.decorations.enabled": "Controls if Git contributes colors and badges to the explorer and the open editors view.", + "config.promptToSaveFilesBeforeCommit": "Controls whether Git should check for unsaved files before committing.", + "config.showInlineOpenFileAction": "Controls whether to show an inline Open File action in the Git changes view.", "colors.modified": "Color for modified resources.", "colors.deleted": "Color for deleted resources.", "colors.untracked": "Color for untracked resources.", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 84a011a8881..776e6c8ac1b 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -963,26 +963,30 @@ export class CommandCenter { getCommitMessage: () => Promise, opts?: CommitOptions ): Promise { - const unsavedTextDocuments = workspace.textDocuments - .filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath)); + const config = workspace.getConfiguration('git'); + const promptToSaveFilesBeforeCommit = config.get('promptToSaveFilesBeforeCommit') === true; - if (unsavedTextDocuments.length > 0) { - const message = unsavedTextDocuments.length === 1 - ? localize('unsaved files single', "The following file is unsaved: {0}.\n\nWould you like to save it before comitting?", path.basename(unsavedTextDocuments[0].uri.fsPath)) - : localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before comitting?", unsavedTextDocuments.length); - const saveAndCommit = localize('save and commit', "Save All & Commit"); - const commit = localize('commit', "Commit Anyway"); - const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit); + if (promptToSaveFilesBeforeCommit) { + const unsavedTextDocuments = workspace.textDocuments + .filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath)); - if (pick === saveAndCommit) { - await Promise.all(unsavedTextDocuments.map(d => d.save())); - await repository.status(); - } else if (pick !== commit) { - return false; // do not commit on cancel + if (unsavedTextDocuments.length > 0) { + const message = unsavedTextDocuments.length === 1 + ? localize('unsaved files single', "The following file is unsaved: {0}.\n\nWould you like to save it before comitting?", path.basename(unsavedTextDocuments[0].uri.fsPath)) + : localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before comitting?", unsavedTextDocuments.length); + const saveAndCommit = localize('save and commit', "Save All & Commit"); + const commit = localize('commit', "Commit Anyway"); + const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit); + + if (pick === saveAndCommit) { + await Promise.all(unsavedTextDocuments.map(d => d.save())); + await repository.status(); + } else if (pick !== commit) { + return false; // do not commit on cancel + } } } - const config = workspace.getConfiguration('git'); const enableSmartCommit = config.get('enableSmartCommit') === true; const enableCommitSigning = config.get('enableCommitSigning') === true; const noStagedChanges = repository.indexGroup.resourceStates.length === 0; diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index d82223f0099..c00b71b12af 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -6,7 +6,7 @@ 'use strict'; import * as nls from 'vscode-nls'; -const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); +const localize = nls.loadMessageBundle(); import { ExtensionContext, workspace, window, Disposable, commands, Uri, OutputChannel } from 'vscode'; import { findGit, Git, IGit } from './git'; import { Model } from './model'; diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index a9d4c679d30..807d677b30a 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -242,9 +242,9 @@ vscode-extension-telemetry@0.0.8: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" which@^1.3.0: version "1.3.0" diff --git a/extensions/go/test/colorize-fixtures/test.go b/extensions/go/test/colorize-fixtures/test.go index ef1d22a3bff..ade235742c6 100644 --- a/extensions/go/test/colorize-fixtures/test.go +++ b/extensions/go/test/colorize-fixtures/test.go @@ -8,6 +8,7 @@ import ( func main() { dnsName := "test-vm-from-go" storageAccount := "mystorageaccount" + c := make(chan int) client, err := management.ClientFromPublishSettingsFile("path/to/downloaded.publishsettings", "") if err != nil { diff --git a/extensions/go/test/colorize-results/test_go.json b/extensions/go/test/colorize-results/test_go.json index 0a876071e60..6916ec49cd2 100644 --- a/extensions/go/test/colorize-results/test_go.json +++ b/extensions/go/test/colorize-results/test_go.json @@ -428,6 +428,127 @@ "hc_black": "default: #FFFFFF" } }, + { + "c": "c", + "t": "source.go variable.other.assignment.go", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE" + } + }, + { + "c": " ", + "t": "source.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": ":=", + "t": "source.go keyword.operator.assignment.go", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4" + } + }, + { + "c": " ", + "t": "source.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "make", + "t": "source.go support.function.builtin.go", + "r": { + "dark_plus": "support.function: #DCDCAA", + "light_plus": "support.function: #795E26", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "support.function: #DCDCAA" + } + }, + { + "c": "(", + "t": "source.go punctuation.definition.begin.bracket.round.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "chan", + "t": "source.go keyword.channel.go", + "r": { + "dark_plus": "keyword: #569CD6", + "light_plus": "keyword: #0000FF", + "dark_vs": "keyword: #569CD6", + "light_vs": "keyword: #0000FF", + "hc_black": "keyword: #569CD6" + } + }, + { + "c": " ", + "t": "source.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": "int", + "t": "source.go storage.type.numeric.go", + "r": { + "dark_plus": "storage.type.numeric.go: #4EC9B0", + "light_plus": "storage.type.numeric.go: #267F99", + "dark_vs": "storage.type: #569CD6", + "light_vs": "storage.type: #0000FF", + "hc_black": "storage.type: #569CD6" + } + }, + { + "c": ")", + "t": "source.go punctuation.definition.end.bracket.round.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, + { + "c": " ", + "t": "source.go", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF" + } + }, { "c": "client", "t": "source.go variable.other.assignment.go", diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index b330d18326c..c63b52e02b4 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -15,7 +15,7 @@ "watch": "gulp watch-extension:grunt" }, "dependencies": { - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/grunt/src/main.ts b/extensions/grunt/src/main.ts index d08e845c1ba..3f425451a30 100644 --- a/extensions/grunt/src/main.ts +++ b/extensions/grunt/src/main.ts @@ -9,8 +9,7 @@ import * as fs from 'fs'; import * as cp from 'child_process'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; - -const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); +const localize = nls.loadMessageBundle(); type AutoDetect = 'on' | 'off'; @@ -68,7 +67,7 @@ interface GruntTaskDefinition extends vscode.TaskDefinition { class FolderDetector { - private fileWatcher: vscode.FileSystemWatcher; + private fileWatcher: vscode.FileSystemWatcher | undefined; private promise: Thenable | undefined; constructor(private _workspaceFolder: vscode.WorkspaceFolder) { diff --git a/extensions/grunt/yarn.lock b/extensions/grunt/yarn.lock index cde3e475ca8..e2fc7ae342e 100644 --- a/extensions/grunt/yarn.lock +++ b/extensions/grunt/yarn.lock @@ -6,6 +6,6 @@ version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 00e098d9b20..525398dcf9a 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -15,7 +15,7 @@ "watch": "gulp watch-extension:gulp" }, "dependencies": { - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index 51a64054021..def484dc13f 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -8,9 +8,9 @@ import * as path from 'path'; import * as fs from 'fs'; import * as cp from 'child_process'; import * as vscode from 'vscode'; -import * as nls from 'vscode-nls'; -const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); type AutoDetect = 'on' | 'off'; diff --git a/extensions/gulp/yarn.lock b/extensions/gulp/yarn.lock index cde3e475ca8..e2fc7ae342e 100644 --- a/extensions/gulp/yarn.lock +++ b/extensions/gulp/yarn.lock @@ -6,6 +6,6 @@ version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/html/client/src/htmlMain.ts b/extensions/html/client/src/htmlMain.ts index b4b84b3ee01..a3bc91466ea 100644 --- a/extensions/html/client/src/htmlMain.ts +++ b/extensions/html/client/src/htmlMain.ts @@ -5,6 +5,8 @@ 'use strict'; import * as path from 'path'; +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); import { languages, ExtensionContext, IndentAction, Position, TextDocument, Color, ColorInformation, ColorPresentation, Range, CompletionItem, CompletionItemKind, SnippetString } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams } from 'vscode-languageclient'; @@ -14,9 +16,6 @@ import TelemetryReporter from 'vscode-extension-telemetry'; import { DocumentColorRequest, DocumentColorParams, ColorPresentationRequest, ColorPresentationParams } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; -import * as nls from 'vscode-nls'; -let localize = nls.loadMessageBundle(); - namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); } diff --git a/extensions/html/package.json b/extensions/html/package.json index 13e5d82ca51..c9662fab156 100644 --- a/extensions/html/package.json +++ b/extensions/html/package.json @@ -226,7 +226,7 @@ "dependencies": { "vscode-extension-telemetry": "0.0.8", "vscode-languageclient": "^3.5.0", - "vscode-nls": "2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/html/server/package.json b/extensions/html/server/package.json index 65cd75b02e9..37ab867085e 100644 --- a/extensions/html/server/package.json +++ b/extensions/html/server/package.json @@ -11,7 +11,7 @@ "vscode-css-languageservice": "^3.0.3", "vscode-html-languageservice": "^2.0.14", "vscode-languageserver": "^3.5.0", - "vscode-nls": "^2.0.2", + "vscode-nls": "^3.1.2", "vscode-uri": "^1.0.1" }, "devDependencies": { diff --git a/extensions/html/server/src/htmlServerMain.ts b/extensions/html/server/src/htmlServerMain.ts index 85383529fd4..cf03f00d561 100644 --- a/extensions/html/server/src/htmlServerMain.ts +++ b/extensions/html/server/src/htmlServerMain.ts @@ -18,10 +18,6 @@ import { getDocumentContext } from './utils/documentContext'; import uri from 'vscode-uri'; import { formatError, runSafe } from './utils/errors'; -import * as nls from 'vscode-nls'; - -nls.config(process.env['VSCODE_NLS_CONFIG']); - namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); } diff --git a/extensions/html/server/src/modes/javascriptMode.ts b/extensions/html/server/src/modes/javascriptMode.ts index a1d0c2850fc..7255840e3cf 100644 --- a/extensions/html/server/src/modes/javascriptMode.ts +++ b/extensions/html/server/src/modes/javascriptMode.ts @@ -85,7 +85,7 @@ export function getJavascriptMode(documentRegions: LanguageModelCache | undefined; constructor(private _workspaceFolder: vscode.WorkspaceFolder) { diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock index cde3e475ca8..e2fc7ae342e 100644 --- a/extensions/jake/yarn.lock +++ b/extensions/jake/yarn.lock @@ -6,6 +6,6 @@ version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/javascript/package.json b/extensions/javascript/package.json index 8a6e0ed6708..b3377418c01 100644 --- a/extensions/javascript/package.json +++ b/extensions/javascript/package.json @@ -13,7 +13,7 @@ "dependencies": { "jsonc-parser": "^1.0.0", "request-light": "^0.2.2", - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "scripts": { "compile": "gulp compile-extension:javascript", diff --git a/extensions/javascript/src/javascriptMain.ts b/extensions/javascript/src/javascriptMain.ts index ed2552b87f0..319c5bae577 100644 --- a/extensions/javascript/src/javascriptMain.ts +++ b/extensions/javascript/src/javascriptMain.ts @@ -8,13 +8,9 @@ import { addJSONProviders } from './features/jsonContributions'; import * as httpRequest from 'request-light'; -import { ExtensionContext, env, workspace } from 'vscode'; - -import * as nls from 'vscode-nls'; +import { ExtensionContext, workspace } from 'vscode'; export function activate(context: ExtensionContext): any { - nls.config({ locale: env.language }); - configureHttpRequest(); workspace.onDidChangeConfiguration(() => configureHttpRequest()); diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 29765c0ba34..45dc54b7115 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/8b44958a27860957872cc6f628d843a71686af63", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/51323af933792ffbb9a088fd500536122be38b59", "name": "JavaScript (with React support)", "scopeName": "source.js", "fileTypes": [ @@ -292,7 +292,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js entity.name.function.js" @@ -354,7 +354,7 @@ "patterns": [ { "name": "meta.object-binding-pattern-variable.js", - "begin": "(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js" @@ -753,7 +753,7 @@ }, { "name": "meta.definition.property.js entity.name.function.js", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))" }, { "name": "meta.definition.property.js variable.object.property.js", @@ -1884,7 +1884,7 @@ }, "after-operator-block-as-object-literal": { "name": "meta.objectliteral.js", - "begin": "(?<=[=(,\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\|\\||\\*)\\s*(\\{)", + "begin": "(?<=[=(,\\[?+!]|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^yield|[^\\._$[:alnum:]]yield|^throw|[^\\._$[:alnum:]]throw|^in|[^\\._$[:alnum:]]in|^of|[^\\._$[:alnum:]]of|^typeof|[^\\._$[:alnum:]]typeof|&&|\\|\\||\\*)\\s*(\\{)", "beginCaptures": { "1": { "name": "punctuation.definition.block.js" @@ -2057,13 +2057,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3295,7 +3295,7 @@ "patterns": [ { "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.js" @@ -4041,7 +4041,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "end": "(?!\\s*(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "patterns": [ { @@ -4089,7 +4089,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", "end": "(/>)|(?:())", "endCaptures": { "0": { diff --git a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json index 30557f4a531..85ebfe2446f 100644 --- a/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/8b44958a27860957872cc6f628d843a71686af63", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/51323af933792ffbb9a088fd500536122be38b59", "name": "JavaScript (with React support)", "scopeName": "source.js.jsx", "fileTypes": [ @@ -292,7 +292,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.js.jsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.js.jsx entity.name.function.js.jsx" @@ -354,7 +354,7 @@ "patterns": [ { "name": "meta.object-binding-pattern-variable.js.jsx", - "begin": "(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.js.jsx" @@ -753,7 +753,7 @@ }, { "name": "meta.definition.property.js.jsx entity.name.function.js.jsx", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))" }, { "name": "meta.definition.property.js.jsx variable.object.property.js.jsx", @@ -1884,7 +1884,7 @@ }, "after-operator-block-as-object-literal": { "name": "meta.objectliteral.js.jsx", - "begin": "(?<=[=(,\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\|\\||\\*)\\s*(\\{)", + "begin": "(?<=[=(,\\[?+!]|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^yield|[^\\._$[:alnum:]]yield|^throw|[^\\._$[:alnum:]]throw|^in|[^\\._$[:alnum:]]in|^of|[^\\._$[:alnum:]]of|^typeof|[^\\._$[:alnum:]]typeof|&&|\\|\\||\\*)\\s*(\\{)", "beginCaptures": { "1": { "name": "punctuation.definition.block.js.jsx" @@ -2057,13 +2057,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js.jsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3295,7 +3295,7 @@ "patterns": [ { "name": "string.regexp.js.jsx", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.js.jsx" @@ -4041,7 +4041,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "end": "(?!\\s*(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "patterns": [ { @@ -4089,7 +4089,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", "end": "(/>)|(?:())", "endCaptures": { "0": { diff --git a/extensions/javascript/yarn.lock b/extensions/javascript/yarn.lock index c74f9ca2c9f..72d121783eb 100644 --- a/extensions/javascript/yarn.lock +++ b/extensions/javascript/yarn.lock @@ -71,3 +71,7 @@ request-light@^0.2.2: vscode-nls@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" + +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/json/client/src/jsonMain.ts b/extensions/json/client/src/jsonMain.ts index 654db136a3f..e6fe6e4253b 100644 --- a/extensions/json/client/src/jsonMain.ts +++ b/extensions/json/client/src/jsonMain.ts @@ -5,6 +5,8 @@ 'use strict'; import * as path from 'path'; +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorInformation, Color, ColorPresentation, LanguageConfiguration } from 'vscode'; import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient'; @@ -12,10 +14,7 @@ import TelemetryReporter from 'vscode-extension-telemetry'; import { ConfigurationFeature } from 'vscode-languageclient/lib/configuration.proposed'; import { DocumentColorRequest, DocumentColorParams, ColorPresentationParams, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; - -import * as nls from 'vscode-nls'; import { hash } from './utils/hash'; -let localize = nls.loadMessageBundle(); namespace VSCodeContentRequest { export const type: RequestType = new RequestType('vscode/content'); diff --git a/extensions/json/package.json b/extensions/json/package.json index 31f13d8017b..e5ae54bde5b 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -164,7 +164,7 @@ "dependencies": { "vscode-extension-telemetry": "0.0.8", "vscode-languageclient": "^3.5.0", - "vscode-nls": "2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json index 2dc13ac6bef..562689ecf52 100644 --- a/extensions/json/server/package.json +++ b/extensions/json/server/package.json @@ -12,7 +12,7 @@ "request-light": "^0.2.2", "vscode-json-languageservice": "^3.0.4", "vscode-languageserver": "^3.5.0", - "vscode-nls": "^2.0.2", + "vscode-nls": "^3.1.2", "vscode-uri": "^1.0.1" }, "devDependencies": { diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json/server/src/jsonServerMain.ts index 182dfc60ddf..3137b954d36 100644 --- a/extensions/json/server/src/jsonServerMain.ts +++ b/extensions/json/server/src/jsonServerMain.ts @@ -21,9 +21,6 @@ import { formatError, runSafe } from './utils/errors'; import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService, DocumentLanguageSettings } from 'vscode-json-languageservice'; import { getLanguageModelCache } from './languageModelCache'; -import * as nls from 'vscode-nls'; -nls.config(process.env['VSCODE_NLS_CONFIG']); - interface ISchemaAssociations { [pattern: string]: string[]; } diff --git a/extensions/json/server/yarn.lock b/extensions/json/server/yarn.lock index c526bf67451..8c005a3357a 100644 --- a/extensions/json/server/yarn.lock +++ b/extensions/json/server/yarn.lock @@ -99,6 +99,10 @@ vscode-nls@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" + vscode-uri@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.1.tgz#11a86befeac3c4aa3ec08623651a3c81a6d0bbc8" diff --git a/extensions/json/yarn.lock b/extensions/json/yarn.lock index 4ebd6092170..fac01e86dad 100644 --- a/extensions/json/yarn.lock +++ b/extensions/json/yarn.lock @@ -38,9 +38,9 @@ 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" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" winreg@1.2.3: version "1.2.3" diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index db8a18ec737..6d86a3d88fb 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -314,7 +314,7 @@ "markdown-it": "^8.4.0", "markdown-it-named-headers": "0.0.4", "vscode-extension-telemetry": "^0.0.8", - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/highlight.js": "9.1.10", diff --git a/extensions/markdown/src/commands.ts b/extensions/markdown/src/commands.ts index b0b029f1b24..583c0f85292 100644 --- a/extensions/markdown/src/commands.ts +++ b/extensions/markdown/src/commands.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vscode-nls'; -const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); +const localize = nls.loadMessageBundle(); import * as vscode from 'vscode'; import * as path from 'path'; diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage b/extensions/markdown/syntaxes/markdown.tmLanguage index 26a48c15d3e..bb0e0c36761 100644 --- a/extensions/markdown/syntaxes/markdown.tmLanguage +++ b/extensions/markdown/syntaxes/markdown.tmLanguage @@ -3318,7 +3318,7 @@ begin (?x) - (\*|_)(?=\S) # Open + \b(\*|_)(?=\S) # Open (?= ( <[^>]*+> # HTML tags @@ -3368,7 +3368,7 @@ end - (?<=\S)(\1)((?!\1)|(?=\1\1)) + (?<=\S)(\1)((?!\1)|(?=\1\1))\b name markup.italic.markdown patterns diff --git a/extensions/markdown/syntaxes/markdown.tmLanguage.base b/extensions/markdown/syntaxes/markdown.tmLanguage.base index ca8b920a22f..442b45acce8 100644 --- a/extensions/markdown/syntaxes/markdown.tmLanguage.base +++ b/extensions/markdown/syntaxes/markdown.tmLanguage.base @@ -808,7 +808,7 @@ begin (?x) - (\*|_)(?=\S) # Open + \b(\*|_)(?=\S) # Open (?= ( <[^>]*+> # HTML tags @@ -858,7 +858,7 @@ end - (?<=\S)(\1)((?!\1)|(?=\1\1)) + (?<=\S)(\1)((?!\1)|(?=\1\1))\b name markup.italic.markdown patterns diff --git a/extensions/markdown/test/colorize-results/test_md.json b/extensions/markdown/test/colorize-results/test_md.json index 01b3aac1707..a3dd8829dfe 100644 --- a/extensions/markdown/test/colorize-results/test_md.json +++ b/extensions/markdown/test/colorize-results/test_md.json @@ -1584,51 +1584,7 @@ } }, { - "c": "in", - "t": "text.html.markdown meta.paragraph.markdown", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "_", - "t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown punctuation.definition.italic.markdown", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "words", - "t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "_", - "t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown punctuation.definition.italic.markdown", - "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" - } - }, - { - "c": "are ignored.", + "c": "in_words_are ignored.", "t": "text.html.markdown meta.paragraph.markdown", "r": { "dark_plus": "default: #D4D4D4", diff --git a/extensions/markdown/yarn.lock b/extensions/markdown/yarn.lock index 4baed92f526..5e1e4c7a48b 100644 --- a/extensions/markdown/yarn.lock +++ b/extensions/markdown/yarn.lock @@ -162,9 +162,9 @@ vscode-extension-telemetry@^0.0.8: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" winreg@1.2.3: version "1.2.3" diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index 1a0f35f9b34..d7a0031df97 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -100,7 +100,7 @@ }, "dependencies": { "vscode-extension-telemetry": "0.0.8", - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "8.0.33" diff --git a/extensions/merge-conflict/src/extension.ts b/extensions/merge-conflict/src/extension.ts index 3168d67ab42..33c996955db 100644 --- a/extensions/merge-conflict/src/extension.ts +++ b/extensions/merge-conflict/src/extension.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vscode-nls'; -nls.config(process.env.VSCODE_NLS_CONFIG)(); import * as vscode from 'vscode'; import MergeConflictServices from './services'; diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index feea62445f1..bd0aecc3553 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -17,9 +17,9 @@ vscode-extension-telemetry@0.0.8: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" winreg@1.2.3: version "1.2.3" diff --git a/extensions/ms-vscode.node-debug/package-lock.json b/extensions/ms-vscode.node-debug/package-lock.json deleted file mode 100644 index 526e856f483..00000000000 --- a/extensions/ms-vscode.node-debug/package-lock.json +++ /dev/null @@ -1,7087 +0,0 @@ -{ - "name": "node-debug", - "version": "1.19.7", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dev": true, - "requires": { - "acorn": "5.2.1", - "css": "2.2.1", - "normalize-path": "2.1.1", - "source-map": "0.5.7", - "through2": "2.0.3" - }, - "dependencies": { - "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "2.1.1", - "through2": "2.0.3" - } - }, - "@types/mocha": { - "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": "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.2", - "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.2.tgz", - "integrity": "sha512-++w4WmMbk3dS3UeHGzAG+xJOSz5Xqtjys/TBkqG3qp3SeWE7Wwezqe5eB7B51cxUyh4PW7bwVotpsLdBK0D8cw==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - }, - "agent-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz", - "integrity": "sha1-aJDT+yFwBLYrcPiSjg+uX4lSpwY=" - }, - "ajv": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.4.0.tgz", - "integrity": "sha1-MtHPCNvIDEMvQm8S4QslEfa0ZHQ=", - "dev": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "2.1.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", - "dev": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "boxen": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.2.2.tgz", - "integrity": "sha1-Px1AMsMP/qnUsCwyLq8up0HcvOU=", - "dev": true, - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "2.3.0", - "cli-boxes": "1.0.0", - "string-width": "2.1.1", - "term-size": "1.2.0", - "widest-line": "1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash": "4.17.4", - "parse5": "3.0.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "fsevents": "1.1.3", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "configstore": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", - "dev": true, - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.1.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.35" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "debug-fabulous": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.2.1.tgz", - "integrity": "sha512-u0TV6HcfLsZ03xLBhdhSViQMldaiQ2o+8/nSILaXkuNSWvxkx66vYJUAam0Eu7gAilJRX/69J4kKdqajQPaPyw==", - "dev": true, - "requires": { - "debug": "3.1.0", - "memoizee": "0.4.11", - "object-assign": "4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-assign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", - "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", - "dev": true, - "requires": { - "is-obj": "1.0.1" - } - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.3" - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "6.1.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "p-map": "1.2.0", - "pify": "3.0.0", - "rimraf": "2.6.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true, - "requires": { - "fs-exists-sync": "0.1.0" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "1.0.1" - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", - "dev": true, - "requires": { - "end-of-stream": "1.4.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "es5-ext": { - "version": "0.10.35", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz", - "integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=", - "dev": true, - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-symbol": "3.1.1" - } - }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "1.2.0" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true, - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", - "dev": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "aproba": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", - "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz", - "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", - "dev": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.39", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz", - "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", - "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", - "dev": true - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", - "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", - "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", - "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", - "dev": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - } - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "1.3.5" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true, - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "0.2.0", - "which": "1.3.0" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "safe-buffer": "5.1.1", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.0" - } - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.4", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - } - }, - "gulp-chmod": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", - "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", - "dev": true, - "requires": { - "deep-assign": "1.0.0", - "stat-mode": "0.2.2", - "through2": "2.0.3" - } - }, - "gulp-filter": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A==", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "multimatch": "2.1.0", - "streamfilter": "1.0.5" - } - }, - "gulp-gunzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", - "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "gulp-remote-src": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", - "integrity": "sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "node.extend": "1.1.6", - "request": "2.79.0", - "through2": "2.0.3", - "vinyl": "2.0.2" - }, - "dependencies": { - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.1.0" - } - }, - "vinyl": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", - "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "is-stream": "1.1.0", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - } - } - }, - "gulp-sourcemaps": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz", - "integrity": "sha512-1qHCI3hdmsMdq/SUotxwUh/L8YzlI6J9zQ5ifNOtx4Y6KV5y5sGuORv1KZzWhuKtz/mXNh5xLESUtwC4EndCjA==", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.0.1", - "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "4.0.13", - "convert-source-map": "1.5.0", - "css": "2.2.1", - "debug-fabulous": "0.2.1", - "detect-newline": "2.1.0", - "graceful-fs": "4.1.11", - "source-map": "0.6.1", - "strip-bom-string": "1.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-symdest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", - "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "mkdirp": "0.5.1", - "queue": "3.1.0", - "vinyl-fs": "2.4.4" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - } - } - } - }, - "gulp-tsb": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/gulp-tsb/-/gulp-tsb-2.0.4.tgz", - "integrity": "sha1-CymAktTf1OXP2AZ57Uwdk7/bpko=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "through": "2.3.8", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "gulp-tslint": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.2.tgz", - "integrity": "sha512-0RNGqbp2TKPdbG+sWU3mNMXEMuF/noY1KS4+jd5lOStkvuFINkFL29dHX3IT1u+vVFD4Glwf+lkcdR2QMVNMzA==", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "map-stream": "0.0.7", - "through": "2.3.8" - }, - "dependencies": { - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - } - } - }, - "gulp-typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.2.tgz", - "integrity": "sha1-t+Xh08s193LlPmBAJmAYJuK+d/w=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "source-map": "0.5.7", - "through2": "2.0.3", - "vinyl-fs": "2.4.4" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - } - } - } - }, - "gulp-uglify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-2.0.0.tgz", - "integrity": "sha1-y+Sq5P4La912AzW8RvIA//aZxK8=", - "dev": true, - "requires": { - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash": "4.17.4", - "make-error-cause": "1.2.2", - "through2": "2.0.3", - "uglify-js": "2.7.0", - "uglify-save-license": "0.4.1", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "gulp-untar": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.6.tgz", - "integrity": "sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "streamifier": "0.1.1", - "tar": "2.2.1", - "through2": "2.0.3" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulp-vinyl-zip": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", - "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "queue": "4.4.2", - "through2": "2.0.3", - "vinyl": "2.1.0", - "vinyl-fs": "2.4.4", - "yauzl": "2.9.1", - "yazl": "2.4.3" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "queue": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", - "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.1", - "pinkie-promise": "2.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "http-proxy-agent": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.7.tgz", - "integrity": "sha1-4X/aZfCQLZUs55IeYsf/iGJlWl4=", - "requires": { - "agent-base": "1.0.2", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "https-proxy-agent": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.6.tgz", - "integrity": "sha1-cT+jjl01P1DrFKNC/r4pAz7RYZs=", - "requires": { - "agent-base": "1.0.2", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, - "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true, - "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "1.11.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "0.1.1", - "is-path-inside": "1.0.0" - } - }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true, - "requires": { - "is-unc-path": "0.1.2" - } - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "4.0.1" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "0.4.3", - "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "1.5.0" - } - }, - "linkify-it": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz", - "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", - "dev": true, - "requires": { - "uc.micro": "1.0.3" - } - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._createassigner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", - "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", - "dev": true, - "requires": { - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9", - "lodash.restparam": "3.6.1" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.assign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", - "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._createassigner": "3.1.1", - "lodash.keys": "3.1.2" - } - }, - "lodash.defaults": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", - "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", - "dev": true, - "requires": { - "lodash.assign": "3.2.0", - "lodash.restparam": "3.6.1" - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "0.10.35" - } - }, - "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", - "dev": true, - "requires": { - "pify": "3.0.0" - } - }, - "make-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", - "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "1.3.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "markdown-it": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "integrity": "sha512-tNuOCCfunY5v5uhcO2AUMArvKAyKMygX8tfup/JrgnsDqcCATQsAExBq7o5Ml9iMmO82bk6jYNLj6khcrl0JGA==", - "dev": true, - "requires": { - "argparse": "1.0.9", - "entities": "1.1.1", - "linkify-it": "2.0.3", - "mdurl": "1.0.1", - "uc.micro": "1.0.3" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memoizee": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", - "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-weak-map": "2.0.2", - "event-emitter": "0.3.5", - "is-promise": "2.1.0", - "lru-queue": "0.1.0", - "next-tick": "1.0.0", - "timers-ext": "0.1.2" - } - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "mime": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.5.0.tgz", - "integrity": "sha512-v/jMDoK/qKptnTuC3YUNbIj8uUYvTCIHzVu9BHldKSWja48wusAtfjlcBlqnFrqClu3yf69ScDxBPrIyFnF51g==", - "dev": true - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mocha": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", - "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", - "dev": true, - "optional": true - }, - "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "3.2.1" - } - }, - "nodemon": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.12.1.tgz", - "integrity": "sha1-mWpW3EnZ8Wu/G3ik3gjxNjSzh40=", - "dev": true, - "requires": { - "chokidar": "1.7.0", - "debug": "2.6.9", - "es6-promise": "3.3.1", - "ignore-by-default": "1.0.1", - "lodash.defaults": "3.1.2", - "minimatch": "3.0.4", - "ps-tree": "1.1.0", - "touch": "3.1.0", - "undefsafe": "0.0.3", - "update-notifier": "2.3.0" - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1.1.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "dev": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.1", - "registry-url": "3.1.0", - "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 - } - } - }, - "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true, - "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "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": "7.0.43" - } - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "ps-tree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", - "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", - "dev": true, - "requires": { - "event-stream": "3.3.4" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", - "dev": true - }, - "queue": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", - "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "rc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", - "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", - "dev": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "0.0.7" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.3", - "set-immediate-shim": "1.0.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.5.0" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "registry-auth-token": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", - "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", - "dev": true, - "requires": { - "rc": "1.2.2", - "safe-buffer": "5.1.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "1.2.2" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", - "dev": true, - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "5.4.0", - "har-schema": "2.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "request-light": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz", - "integrity": "sha1-mG9agok+nRymqJbr5vRsUca0VX8=", - "requires": { - "http-proxy-agent": "0.2.7", - "https-proxy-agent": "0.3.6", - "vscode-nls": "2.0.2" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true, - "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "run-sequence": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz", - "integrity": "sha512-xW5DmUwdvoyYQUMPKN8UW7TZSFs7AxtT59xo1m5y91jHbvwGlGgOmdV1Yw5P68fkjf3aHUZ4G1o1mZCtNe0qtw==", - "dev": true, - "requires": { - "chalk": "1.1.3", - "gulp-util": "3.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "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 - } - } - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "dev": true, - "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" - } - }, - "source-map-support": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", - "dev": true, - "requires": { - "source-map": "0.6.1" - } - }, - "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", - "dev": true - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "0.1.1" - } - }, - "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamfilter": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.5.tgz", - "integrity": "sha1-h1BxEb644phFFxe1Ec/tjwAqv1M=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "streamifier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", - "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "0.7.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "timers-ext": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", - "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", - "dev": true, - "requires": { - "es5-ext": "0.10.35", - "next-tick": "1.0.0" - } - }, - "tmp": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", - "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "1.0.10" - } - }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tslib": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==", - "dev": true - }, - "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.3.0", - "commander": "2.11.0", - "diff": "3.3.1", - "glob": "7.1.2", - "minimatch": "3.0.4", - "resolve": "1.5.0", - "semver": "5.4.1", - "tslib": "1.8.0", - "tsutils": "2.12.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "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 - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "tslint-microsoft-contrib": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.1.tgz", - "integrity": "sha1-Mo7pwo0HzfeTKTIEyW4v+rkiGZQ=", - "dev": true, - "requires": { - "tsutils": "1.9.1" - }, - "dependencies": { - "tsutils": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", - "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", - "dev": true - } - } - }, - "tsutils": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.12.2.tgz", - "integrity": "sha1-rVikhl0X7D3bZjG2ylO+FKVlb/M=", - "dev": true, - "requires": { - "tslib": "1.8.0" - } - }, - "tunnel": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", - "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "typed-rest-client": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.9.0.tgz", - "integrity": "sha1-92jMDcP06VDwbgSCXDaz54NKofI=", - "dev": true, - "requires": { - "tunnel": "0.0.4", - "underscore": "1.8.3" - } - }, - "typescript": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz", - "integrity": "sha1-7znN6ierrAtQAkLWcmq5DgyEZjE=", - "dev": true - }, - "uc.micro": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", - "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=", - "dev": true - }, - "uglify-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.0.tgz", - "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", - "dev": true, - "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undefsafe": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-0.0.3.tgz", - "integrity": "sha1-7Mo6A+VrmvFzhbqsgSrIO5lKli8=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "1.0.0" - } - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "update-notifier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", - "integrity": "sha1-TognpruRUUCrCTVZ1wFOPruDdFE=", - "dev": true, - "requires": { - "boxen": "1.2.2", - "chalk": "2.3.0", - "configstore": "3.1.1", - "import-lazy": "2.1.0", - "is-installed-globally": "0.1.0", - "is-npm": "1.0.0", - "latest-version": "3.1.0", - "semver-diff": "2.1.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", - "dev": true, - "requires": { - "querystringify": "1.0.0", - "requires-port": "1.0.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "1.0.4" - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "vsce": { - "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", - "commander": "2.11.0", - "denodeify": "1.2.1", - "glob": "7.1.2", - "lodash": "4.17.4", - "markdown-it": "8.4.0", - "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", - "url-join": "1.1.0", - "vso-node-api": "6.1.2-preview", - "yauzl": "2.9.1", - "yazl": "2.4.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "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 - } - } - }, - "vscode": { - "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", - "gulp-chmod": "2.0.0", - "gulp-filter": "5.0.1", - "gulp-gunzip": "1.0.0", - "gulp-remote-src": "0.4.3", - "gulp-symdest": "1.1.0", - "gulp-untar": "0.0.6", - "gulp-vinyl-zip": "2.1.0", - "mocha": "4.0.1", - "request": "2.83.0", - "semver": "5.4.1", - "source-map-support": "0.5.0", - "url-parse": "1.2.0", - "vinyl-source-stream": "1.1.0" - }, - "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 - } - } - }, - "vscode-debugadapter": { - "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" - } - }, - "vscode-debugadapter-testsupport": { - "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.25.0" - } - }, - "vscode-debugprotocol": { - "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", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz", - "integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=" - }, - "vscode-nls-dev": { - "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", - "event-stream": "3.3.4", - "glob": "6.0.4", - "gulp-util": "3.0.8", - "iconv-lite": "0.4.19", - "is": "3.2.1", - "source-map": "0.5.7", - "typescript": "2.6.1", - "vinyl": "1.2.0", - "xml2js": "0.4.19", - "yargs": "3.32.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" - } - } - } - }, - "vso-node-api": { - "version": "6.1.2-preview", - "resolved": "https://registry.npmjs.org/vso-node-api/-/vso-node-api-6.1.2-preview.tgz", - "integrity": "sha1-qrNUbfJFHs2JTgcbuZtd8Zxfp48=", - "dev": true, - "requires": { - "q": "1.5.1", - "tunnel": "0.0.4", - "typed-rest-client": "0.9.0", - "underscore": "1.8.3" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "widest-line": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", - "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", - "dev": true, - "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": "1.2.4", - "xmlbuilder": "9.0.4" - } - }, - "xmlbuilder": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", - "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - }, - "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } - }, - "yazl": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", - "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13" - } - } - } -} diff --git a/extensions/ms-vscode.node-debug/package.json b/extensions/ms-vscode.node-debug/package.json deleted file mode 100644 index 87569809e43..00000000000 --- a/extensions/ms-vscode.node-debug/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "node-debug-placeholder", - "version": "1.6.0", - "publisher": "vscode", - "engines": { - "vscode": "1.6.x" - } -} \ No newline at end of file diff --git a/extensions/ms-vscode.node-debug2/package-lock.json b/extensions/ms-vscode.node-debug2/package-lock.json deleted file mode 100644 index 7f8ba502cc4..00000000000 --- a/extensions/ms-vscode.node-debug2/package-lock.json +++ /dev/null @@ -1,5106 +0,0 @@ -{ - "name": "node-debug2", - "version": "1.19.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "css": "2.2.1", - "normalize-path": "2.1.1", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "through2": "2.0.3" - }, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha1-MXrHghgmwixwLWYYmrg1lnXxNdc=", - "dev": true - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "2.1.1", - "through2": "2.0.3" - } - }, - "@types/mocha": { - "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.92", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz", - "integrity": "sha512-awEYSSTn7dauwVCYSx2CJaPTu0Z1Ht2oR1b2AD3CYao6ZRb+opb6EL43fzmD7eMFgMHzTBWSUzlWSD+S8xN0Nw==", - "dev": true - }, - "@types/source-map": { - "version": "https://registry.npmjs.org/@types/source-map/-/source-map-0.1.29.tgz", - "integrity": "sha1-1wSKYBgLCfiqbVO9oxHGtRy9cBg=" - }, - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - }, - "agent-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz", - "integrity": "sha1-aJDT+yFwBLYrcPiSjg+uX4lSpwY=" - }, - "ajv": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.0.tgz", - "integrity": "sha1-6yhAdG6dxIvV4GOjbj/UAMXqtak=", - "dev": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } - }, - "arr-flatten": { - "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", - "dev": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash": "4.17.4", - "parse5": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.37" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, - "debug-fabulous": { - "version": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.2.1.tgz", - "integrity": "sha1-V+EWS6DprW2aZfIAdf88K9a94Nw=", - "dev": true, - "requires": { - "debug": "3.1.0", - "memoizee": "0.4.11", - "object-assign": "4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - } - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-assign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", - "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", - "dev": true, - "requires": { - "is-obj": "1.0.1" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.3" - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true, - "requires": { - "fs-exists-sync": "0.1.0" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "duplexify": { - "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha1-ThUWvmiDi8kKSZlPCzmm5ZYL780=", - "dev": true, - "requires": { - "end-of-stream": "1.4.0", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - } - } - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", - "dev": true, - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-symbol": "3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37" - } - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", - "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "1.2.0" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true, - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "mkdirp": "0.5.1", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "2.0.10", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true, - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "0.2.0", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" - } - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.0" - } - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.4", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - } - }, - "gulp-chmod": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", - "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", - "dev": true, - "requires": { - "deep-assign": "1.0.0", - "stat-mode": "0.2.2", - "through2": "2.0.3" - } - }, - "gulp-filter": { - "version": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha1-XYf2YuMX5YOe92UOYg5skAj/ktA=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "multimatch": "2.1.0", - "streamfilter": "1.0.5" - } - }, - "gulp-gunzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", - "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "gulp-remote-src": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", - "integrity": "sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "node.extend": "1.1.6", - "request": "2.79.0", - "through2": "2.0.3", - "vinyl": "2.0.2" - }, - "dependencies": { - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" - } - }, - "vinyl": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", - "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "is-stream": "1.1.0", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - } - } - }, - "gulp-sourcemaps": { - "version": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz", - "integrity": "sha1-gzpOKPC49GYQdQMs14JBf3zY+ws=", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.0.1", - "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "4.0.13", - "convert-source-map": "1.5.1", - "css": "2.2.1", - "debug-fabulous": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.2.1.tgz", - "detect-newline": "2.1.0", - "graceful-fs": "4.1.11", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "strip-bom-string": "1.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulp-symdest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", - "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "mkdirp": "0.5.1", - "queue": "3.1.0", - "vinyl-fs": "2.4.4" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - } - } - } - }, - "gulp-tslint": { - "version": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.2.tgz", - "integrity": "sha1-4PQxlLRz1+drtFpY/oxg59/jvrI=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "map-stream": "0.0.7", - "through": "2.3.8" - }, - "dependencies": { - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - } - } - }, - "gulp-typescript": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.3.tgz", - "integrity": "sha512-Np2sJXgtDUwIAoMtlJ9uXsVmpu1FWXlKZw164hLuo56uJa7qo5W2KZ0yAYiYH/HUsaz5L0O2toMOcLIokpFCPg==", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "through2": "2.0.3", - "vinyl-fs": "2.4.4" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - } - } - } - }, - "gulp-untar": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.6.tgz", - "integrity": "sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "streamifier": "0.1.1", - "tar": "2.2.1", - "through2": "2.0.3" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulp-vinyl-zip": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", - "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", - "dev": true, - "requires": { - "event-stream": "3.3.4", - "queue": "4.4.2", - "through2": "2.0.3", - "vinyl": "2.1.0", - "vinyl-fs": "2.4.4", - "yauzl": "2.9.1", - "yazl": "2.4.3" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "queue": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", - "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "2.1.1", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.9.0", - "is-my-json-valid": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "pinkie-promise": "2.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "http-proxy-agent": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.7.tgz", - "integrity": "sha1-4X/aZfCQLZUs55IeYsf/iGJlWl4=", - "requires": { - "agent-base": "1.0.2", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "https-proxy-agent": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.6.tgz", - "integrity": "sha1-cT+jjl01P1DrFKNC/r4pAz7RYZs=", - "requires": { - "agent-base": "1.0.2", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" - } - }, - "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", - "dev": true - }, - "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - }, - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", - "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", - "dev": true - }, - "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true, - "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" - } - }, - "is-buffer": { - "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-my-json-valid": { - "version": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha1-WoRnd+LCYg0eaRBOXToDsfYIjxE=", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-object": { - "version": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true, - "requires": { - "is-unc-path": "0.1.2" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "findup-sync": "0.4.3", - "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } - }, - "linkify-it": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz", - "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", - "dev": true, - "requires": { - "uc.micro": "1.0.3" - } - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "0.10.37" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "markdown-it": { - "version": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "integrity": "sha1-4kAIgb8XH3AY7RvZ2kQdrIr2MG0=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "entities": "1.1.1", - "linkify-it": "2.0.3", - "mdurl": "1.0.1", - "uc.micro": "1.0.3" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memoizee": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", - "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.37", - "es6-weak-map": "2.0.2", - "event-emitter": "0.3.5", - "is-promise": "2.1.0", - "lru-queue": "0.1.0", - "next-tick": "1.0.0", - "timers-ext": "0.1.2" - } - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node.extend": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", - "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", - "dev": true, - "requires": { - "is": "3.2.1" - } - }, - "noice-json-rpc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/noice-json-rpc/-/noice-json-rpc-1.0.1.tgz", - "integrity": "sha1-XnKJpgocIIgEicsVEBVSusOSJm4=" - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "dev": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true, - "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "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": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha1-BC95L/3TaFFVHPTp4Gazh0q0W1w=", - "dev": true, - "requires": { - "@types/node": "6.0.92" - } - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", - "dev": true - }, - "queue": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", - "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "randomatic": { - "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "0.0.7" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } - }, - "regex-cache": { - "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", - "dev": true, - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "0.6.1", - "form-data": "2.3.1", - "har-validator": "5.0.3", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz" - }, - "dependencies": { - "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" - } - } - } - }, - "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "5.5.0", - "har-schema": "2.0.0" - } - }, - "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", - "dev": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "sntp": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz" - } - }, - "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", - "dev": true - }, - "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", - "dev": true, - "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "request-light": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.1.0.tgz", - "integrity": "sha1-/mXd/7suh5RPDMr9hcuDnpE4U0U=", - "requires": { - "http-proxy-agent": "0.2.7", - "https-proxy-agent": "0.3.6", - "vscode-nls": "1.0.7" - }, - "dependencies": { - "vscode-nls": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-1.0.7.tgz", - "integrity": "sha1-KYwB/Oh4AsZEwKFe9SajPGLA1Y4=" - } - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true, - "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "dev": true, - "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" - } - }, - "run-sequence": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.2.2.tgz", - "integrity": "sha1-UJWgvr6YczsBQL0I3YDsAw3azes=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "gulp-util": "3.0.8" - } - }, - "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", - "dev": true - }, - "sax": { - "version": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", - "dev": true - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" - }, - "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "dev": true, - "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" - } - }, - "source-map-support": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", - "dev": true, - "requires": { - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", - "dev": true - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2.3.8" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "0.1.1" - } - }, - "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamfilter": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.5.tgz", - "integrity": "sha1-h1BxEb644phFFxe1Ec/tjwAqv1M=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "streamifier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", - "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-ext": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", - "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", - "dev": true, - "requires": { - "es5-ext": "0.10.37", - "next-tick": "1.0.0" - } - }, - "tmp": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", - "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tslib": { - "version": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "integrity": "sha1-3GBOutZLy/aW1hPabJVKoOfqHrY=", - "dev": true - }, - "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.3.0", - "commander": "2.9.0", - "diff": "3.2.0", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "tslib": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "tsutils": "2.12.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", - "dev": true - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "tsutils": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.12.2.tgz", - "integrity": "sha1-rVikhl0X7D3bZjG2ylO+FKVlb/M=", - "dev": true, - "requires": { - "tslib": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz" - } - }, - "tunnel": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", - "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "typed-rest-client": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.9.0.tgz", - "integrity": "sha1-92jMDcP06VDwbgSCXDaz54NKofI=", - "dev": true, - "requires": { - "tunnel": "0.0.4", - "underscore": "1.8.3" - } - }, - "typescript": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz", - "integrity": "sha1-7znN6ierrAtQAkLWcmq5DgyEZjE=", - "dev": true - }, - "uc.micro": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", - "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=", - "dev": true - }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "url-parse": { - "version": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha1-OhnoqqbQI93SfcxEy0/I9/7COYY=", - "dev": true, - "requires": { - "querystringify": "1.0.0", - "requires-port": "1.0.0" - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vsce": { - "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", - "commander": "2.9.0", - "denodeify": "1.2.1", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "lodash": "4.17.4", - "markdown-it": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "mime": "1.6.0", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "osenv": "0.1.4", - "parse-semver": "1.1.1", - "read": "1.0.7", - "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "tmp": "0.0.29", - "url-join": "1.1.0", - "vso-node-api": "6.1.2-preview", - "yauzl": "2.9.1", - "yazl": "2.4.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", - "dev": true - } - } - }, - "vscode": { - "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": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "gulp-chmod": "2.0.0", - "gulp-filter": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "gulp-gunzip": "1.0.0", - "gulp-remote-src": "0.4.3", - "gulp-symdest": "1.1.0", - "gulp-untar": "0.0.6", - "gulp-vinyl-zip": "2.1.0", - "mocha": "4.0.1", - "request": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "source-map-support": "0.5.0", - "url-parse": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "vinyl-source-stream": "1.1.0" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "mocha": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", - "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - } - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", - "dev": true - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "vscode-chrome-debug-core": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/vscode-chrome-debug-core/-/vscode-chrome-debug-core-3.19.0.tgz", - "integrity": "sha1-70aLFweJqQhC+2wsQVS7OsZXvvc=", - "requires": { - "@types/source-map": "https://registry.npmjs.org/@types/source-map/-/source-map-0.1.29.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "noice-json-rpc": "1.0.1", - "request-light": "0.1.0", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "vscode-debugadapter": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.24.0.tgz", - "vscode-debugprotocol": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz", - "vscode-nls": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz", - "ws": "1.1.5" - } - }, - "vscode-chrome-debug-core-testsupport": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-chrome-debug-core-testsupport/-/vscode-chrome-debug-core-testsupport-3.17.1.tgz", - "integrity": "sha1-DUazMXWZooWLSkz+QgzDUuQZiBw=", - "dev": true, - "requires": { - "vscode-debugadapter-testsupport": "1.24.0" - }, - "dependencies": { - "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=", - "dev": true, - "requires": { - "vscode-debugprotocol": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz" - } - } - } - }, - "vscode-debugadapter": { - "version": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.24.0.tgz", - "integrity": "sha1-KAY7AcyorB5fehPRGOMgem6If/0=", - "requires": { - "vscode-debugprotocol": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz" - } - }, - "vscode-debugadapter-testsupport": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.23.0.tgz", - "integrity": "sha1-pItd5CrYChckDZxRHDeGA41pbRs=", - "dev": true, - "requires": { - "vscode-debugprotocol": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz" - } - }, - "vscode-debugprotocol": { - "version": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.24.0.tgz", - "integrity": "sha1-28EOjX2VsQJyehmvPw/O9+JSsI4=" - }, - "vscode-nls": { - "version": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz", - "integrity": "sha1-gIUiOAhEuK0VNJmvXDsDkhrqAto=" - }, - "vscode-nls-dev": { - "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", - "event-stream": "3.3.4", - "glob": "6.0.4", - "gulp-util": "3.0.8", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "is": "3.2.1", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "typescript": "2.6.1", - "vinyl": "1.2.0", - "xml2js": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "yargs": "3.32.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "vso-node-api": { - "version": "6.1.2-preview", - "resolved": "https://registry.npmjs.org/vso-node-api/-/vso-node-api-6.1.2-preview.tgz", - "integrity": "sha1-qrNUbfJFHs2JTgcbuZtd8Zxfp48=", - "dev": true, - "requires": { - "q": "1.5.1", - "tunnel": "0.0.4", - "typed-rest-client": "0.9.0", - "underscore": "1.8.3" - } - }, - "which": { - "version": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - } - }, - "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "requires": { - "options": "0.0.6", - "ultron": "1.0.2" - } - }, - "xml2js": { - "version": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", - "dev": true, - "requires": { - "sax": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "xmlbuilder": "9.0.4" - } - }, - "xmlbuilder": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", - "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" - } - }, - "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } - }, - "yazl": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", - "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", - "dev": true, - "requires": { - "buffer-crc32": "0.2.13" - } - } - } -} \ No newline at end of file diff --git a/extensions/ms-vscode.node-debug2/package.json b/extensions/ms-vscode.node-debug2/package.json deleted file mode 100644 index 26777f7dae6..00000000000 --- a/extensions/ms-vscode.node-debug2/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "node-debug2-placeholder", - "version": "0.0.3", - "publisher": "vscode", - "engines": { - "vscode": "1.6.x" - } -} \ No newline at end of file diff --git a/extensions/npm/package.json b/extensions/npm/package.json index 5810b4ee483..dba83356e28 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -15,7 +15,7 @@ "watch": "gulp watch-extension:npm" }, "dependencies": { - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "7.0.43" diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index e18287872db..17d2c47b1c9 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -let localize = nls.loadMessageBundle(); +const localize = nls.loadMessageBundle(); type AutoDetect = 'on' | 'off'; let taskProvider: vscode.Disposable | undefined; diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index cde3e475ca8..e2fc7ae342e 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -6,6 +6,6 @@ version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/package.json b/extensions/package.json index ad30699b786..01f99336e66 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,9 +3,9 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "2.7.0-insiders.20180108" + "typescript": "2.7.0-insiders.20180119" }, "scripts": { "postinstall": "node ./postinstall" } -} +} \ No newline at end of file diff --git a/extensions/php/package.json b/extensions/php/package.json index fb5758ff8bf..bfe9fcaa5c5 100644 --- a/extensions/php/package.json +++ b/extensions/php/package.json @@ -10,7 +10,7 @@ ], "main": "./out/phpMain", "dependencies": { - "vscode-nls": "^1.0.4" + "vscode-nls": "^3.1.2" }, "contributes": { "languages": [ diff --git a/extensions/php/src/phpMain.ts b/extensions/php/src/phpMain.ts index 64eda6c7809..060f7587c18 100644 --- a/extensions/php/src/phpMain.ts +++ b/extensions/php/src/phpMain.ts @@ -5,8 +5,6 @@ 'use strict'; import * as vscode from 'vscode'; -import * as nls from 'vscode-nls'; -nls.config({ locale: vscode.env.language }); import PHPCompletionItemProvider from './features/completionItemProvider'; import PHPHoverProvider from './features/hoverProvider'; diff --git a/extensions/php/yarn.lock b/extensions/php/yarn.lock index fdd1d36b518..e2fc7ae342e 100644 --- a/extensions/php/yarn.lock +++ b/extensions/php/yarn.lock @@ -6,6 +6,6 @@ version "7.0.43" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c" -vscode-nls@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-1.0.7.tgz#298c01fce87802c644c0a15ef526a33c62c0d58e" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" diff --git a/extensions/swift/snippets/swift.json b/extensions/swift/snippets/swift.json index 43591d13a7b..08161d1c825 100644 --- a/extensions/swift/snippets/swift.json +++ b/extensions/swift/snippets/swift.json @@ -1,133 +1,175 @@ { - "print(\"...\")": { - "prefix": "pr", - "body": "print(\"$1\")$0" + "print": { + "prefix": "print", + "body": "print(\"$1\")\n$0", + "description": "print(\"...\")" }, - "print(\"\\(...)\")": { - "prefix": "po", - "body": "print(\"\\($1)\")$0" + "print value": { + "prefix": "printv", + "body": "print(\"\\($1)\")\n$0", + "description": "print(\"\\(...)\")" }, - "repeat...while loop": { + "while": { + "prefix": "while", + "body": [ + "while ${1:condition} {", + "\t$0", + "}" + ], + "description": "while statement" + }, + "repeat-while": { "prefix": "repeat", "body": [ "repeat {", "\t$0", - "} while ${1:true}" + "} while ${1:condition}" ], - "description": "repeat...while loop" + "description": "repeat-while statement" }, - "While loop": { - "prefix": "while", - "body": [ - "while ${1:true} {", - "\t$0", - "}" - ], - "description": "While loop" - }, - "For-In statement": { - "prefix": "forin", + "for": { + "prefix": "for", "body": [ "for ${1:item} in ${2:collection} {", "\t$0", "}" ], - "description": "For-In statement" + "description": "for-in statement" }, - "Reverse for loop": { - "prefix": "forr", - "body": [ - "for var ${1:i} = ${2:length} - 1; ${1:i} >= 0; ${1:i}-- {", - "\t$0", - "}" - ], - "description": "Reverse for loop" - }, - "for loop": { - "prefix": "for", - "body": [ - "for var ${1:i} = 0; ${1:i} < ${2:length}; ${1:i}++ {", - "\t$0", - "}" - ], - "description": "for loop" - }, - "if statement": { + "if": { "prefix": "if", "body": [ - "if ${1:true} {", + "if ${1:condition} {", "\t$0", "}" ], "description": "if statement" }, - "else-if statement": { + "else if": { "prefix": "elif", "body": [ - "else if ${1:true} {", + "else if ${1:condition} {", "\t$0", "}" ], - "description": "if statement" + "description": "else clause with a nested if statement" }, - "Else statement": { + "else": { "prefix": "else", "body": [ "else {", "\t$0", "}" ], - "description": "Else statement" + "description": "else clause" }, - "Guard statement": { + "if let": { + "prefix": "iflet", + "body": [ + "if let ${1:value} = ${2:optional} {", + "\t$0", + "}" + ], + "description": "if statement with optional binding" + }, + "guard": { "prefix": "guard", "body": [ - "guard let ${1:a} = ${2:optional} else {", + "guard ${1:condition} else {", "\t$0", "}" ], - "description": "Guard statement" + "description": "guard statement" }, - "Optional Binding statement": { - "prefix": "ifnil", + "guard let": { + "prefix": "guardlet", "body": [ - "if let ${1:a} = ${2:optional} {", + "guard let ${1:value} = ${2:optional} else {", "\t$0", "}" ], - "description": "Optional Binding statement" + "description": "guard statement with optional binding" }, - "Switch statement": { + "switch": { "prefix": "switch", "body": [ - "switch ${1:switch_on} {", - "case ${2:a}:", + "switch ${1:value} {", + "case ${2:pattern}:", "\t$0", "default:", - "\t$1", + "\t", "}" ], - "description": "Switch statement" + "description": "switch statement" }, - "Do catch": { - "prefix": "docatch", + "do": { + "prefix": "do", "body": [ "do {", - "\ttry ${1:function that throws}", - "} catch ${2:pattern} {", + "\t$0", + "} catch ${1:error} {", + "\t$2", + "}" + ], + "description": "do statement" + }, + "func": { + "prefix": "func", + "body": [ + "func ${1:name}(${2:parameters}) -> ${3:Type} {", "\t$0", "}" ], - "description": "Try catch" + "description": "function declaration" }, - "Enum": { + "struct": { + "prefix": "struct", + "body": [ + "struct ${1:Name} {", + "", + "\t$0", + "}" + ], + "description": "struct declaration" + }, + "enum": { "prefix": "enum", "body": [ "enum ${1:Name} {", + "", "\tcase $0", "}" ], - "description": "Enum" + "description": "enum declaration" + }, + "class": { + "prefix": "class", + "body": [ + "class ${1:Name} {", + "", + "\t$0", + "}" + ], + "description": "class declaration" + }, + "protocol": { + "prefix": "protocol", + "body": [ + "protocol ${1:Name} {", + "", + "\t$0", + "}" + ], + "description": "protocol declaration" + }, + "extension": { + "prefix": "extension", + "body": [ + "extension ${1:Type} {", + "", + "\t$0", + "}" + ], + "description": "extension declaration" } } - diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index fe868c9a375..9767fa79c74 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -22,6 +22,11 @@ "support.type", "entity.name.type", "entity.name.class", + "storage.type.numeric.go", + "storage.type.byte.go", + "storage.type.boolean.go", + "storage.type.string.go", + "storage.type.uintptr.go", "storage.type.cs", "storage.type.generic.cs", "storage.type.modifier.cs", diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index 0ab71013c2f..a4b6b642a9a 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -22,6 +22,11 @@ "support.type", "entity.name.type", "entity.name.class", + "storage.type.numeric.go", + "storage.type.byte.go", + "storage.type.boolean.go", + "storage.type.string.go", + "storage.type.uintptr.go", "storage.type.cs", "storage.type.generic.cs", "storage.type.modifier.cs", diff --git a/extensions/typescript/package.json b/extensions/typescript/package.json index 6e182cef3d1..27656dec922 100644 --- a/extensions/typescript/package.json +++ b/extensions/typescript/package.json @@ -14,7 +14,7 @@ "dependencies": { "semver": "4.3.6", "vscode-extension-telemetry": "^0.0.8", - "vscode-nls": "^2.0.2" + "vscode-nls": "^3.1.2" }, "devDependencies": { "@types/node": "8.0.33", diff --git a/extensions/typescript/src/extension.ts b/extensions/typescript/src/extension.ts index 5116fa9af72..73604a21c3f 100644 --- a/extensions/typescript/src/extension.ts +++ b/extensions/typescript/src/extension.ts @@ -5,12 +5,6 @@ import * as vscode from 'vscode'; -// This must be the first statement otherwise modules might got loaded with -// the wrong locale. -import * as nls from 'vscode-nls'; -nls.config({ locale: vscode.env.language }); -nls.loadMessageBundle(); - import { CommandManager } from './utils/commandManager'; import TypeScriptServiceClientHost from './typeScriptServiceClientHost'; import * as commands from './commands'; diff --git a/extensions/typescript/src/features/bufferSyncSupport.ts b/extensions/typescript/src/features/bufferSyncSupport.ts index 63f0bdfbc86..186cd02ba6b 100644 --- a/extensions/typescript/src/features/bufferSyncSupport.ts +++ b/extensions/typescript/src/features/bufferSyncSupport.ts @@ -48,10 +48,7 @@ class SyncedBuffer { } if (this.client.apiVersion.has230Features()) { - const root = this.client.getWorkspaceRootForResource(this.document.uri); - if (root) { - args.projectRootPath = root; - } + args.projectRootPath = this.client.getWorkspaceRootForResource(this.document.uri); } if (this.client.apiVersion.has240Features()) { diff --git a/extensions/typescript/src/features/completionItemProvider.ts b/extensions/typescript/src/features/completionItemProvider.ts index f58134b67bd..75c44273c7d 100644 --- a/extensions/typescript/src/features/completionItemProvider.ts +++ b/extensions/typescript/src/features/completionItemProvider.ts @@ -53,7 +53,7 @@ class MyCompletionItem extends CompletionItem { this.range = tsTextSpanToVsRange(tsEntry.replacementSpan); } - if (typeof (tsEntry as any).insertText === 'string') { + if (typeof tsEntry.insertText === 'string') { this.insertText = (tsEntry as any).insertText as string; if (tsEntry.replacementSpan) { diff --git a/extensions/typescript/src/features/quickFixProvider.ts b/extensions/typescript/src/features/quickFixProvider.ts index 21b7dabe37e..d83c23d64da 100644 --- a/extensions/typescript/src/features/quickFixProvider.ts +++ b/extensions/typescript/src/features/quickFixProvider.ts @@ -11,6 +11,10 @@ import { vsRangeToTsFileRange } from '../utils/convert'; import FormattingConfigurationManager from './formattingConfigurationManager'; import { getEditForCodeAction, applyCodeActionCommands } from '../utils/codeAction'; import { Command, CommandManager } from '../utils/commandManager'; +import { createWorkspaceEditFromFileCodeEdits } from '../utils/workspaceEdit'; + +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); class ApplyCodeActionCommand implements Command { public static readonly ID = '_typescript.applyCodeActionCommand'; @@ -34,11 +38,9 @@ class SupportedCodeActionProvider { private readonly client: ITypeScriptServiceClient ) { } - public async getSupportedActionsForContext(context: vscode.CodeActionContext): Promise> { + public async getFixableDiagnosticsForContext(context: vscode.CodeActionContext): Promise { const supportedActions = await this.supportedCodeActions; - return new Set(context.diagnostics - .map(diagnostic => +diagnostic.code) - .filter(code => supportedActions.has(code))); + return context.diagnostics.filter(diagnostic => supportedActions.has(+diagnostic.code)); } private get supportedCodeActions(): Thenable> { @@ -67,7 +69,7 @@ export default class TypeScriptQuickFixProvider implements vscode.CodeActionProv public async provideCodeActions( document: vscode.TextDocument, - range: vscode.Range, + _range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken ): Promise { @@ -80,23 +82,58 @@ export default class TypeScriptQuickFixProvider implements vscode.CodeActionProv return []; } - const supportedActions = await this.supportedCodeActionProvider.getSupportedActionsForContext(context); - if (!supportedActions.size) { + const fixableDiagnostics = await this.supportedCodeActionProvider.getFixableDiagnosticsForContext(context); + if (!fixableDiagnostics.length) { return []; } await this.formattingConfigurationManager.ensureFormatOptionsForDocument(document, token); - const args: Proto.CodeFixRequestArgs = { - ...vsRangeToTsFileRange(file, range), - errorCodes: Array.from(supportedActions) - }; - const response = await this.client.execute('getCodeFixes', args, token); - return (response.body || []).map(action => this.getCommandForAction(action)); + const results: vscode.CodeAction[] = []; + for (const diagnostic of fixableDiagnostics) { + results.push(...await this.getFixesForDiagnostic(file, diagnostic, token)); + } + return results; } - private getCommandForAction(tsAction: Proto.CodeAction): vscode.CodeAction { - const codeAction = new vscode.CodeAction(tsAction.description, getEditForCodeAction(this.client, tsAction)); + private async getFixesForDiagnostic( + file: string, + diagnostic: vscode.Diagnostic, + token: vscode.CancellationToken + ): Promise> { + const args: Proto.CodeFixRequestArgs = { + ...vsRangeToTsFileRange(file, diagnostic.range), + errorCodes: [+diagnostic.code] + }; + const codeFixesResponse = await this.client.execute('getCodeFixes', args, token); + if (codeFixesResponse.body) { + const results: vscode.CodeAction[] = []; + for (const tsCodeFix of codeFixesResponse.body) { + results.push(...await this.getAllFixesForTsCodeAction(file, diagnostic, tsCodeFix, token)); + } + return results; + } + return []; + } + + private async getAllFixesForTsCodeAction( + file: string, + diagnostic: vscode.Diagnostic, + tsAction: Proto.CodeFixAction, + token: vscode.CancellationToken + ): Promise> { + const singleFix = this.getSingleFixForTsCodeAction(diagnostic, tsAction); + const fixAll = await this.getFixAllForTsCodeAction(file, diagnostic, tsAction, token); + return fixAll ? [singleFix, fixAll] : [singleFix]; + } + + private getSingleFixForTsCodeAction( + diagnostic: vscode.Diagnostic, + tsAction: Proto.CodeFixAction + ): vscode.CodeAction { + const codeAction = new vscode.CodeAction(tsAction.description, vscode.CodeActionKind.QuickFix); + codeAction.edit = getEditForCodeAction(this.client, tsAction); + codeAction.diagnostics = [diagnostic]; if (tsAction.commands) { codeAction.command = { command: ApplyCodeActionCommand.ID, @@ -106,4 +143,46 @@ export default class TypeScriptQuickFixProvider implements vscode.CodeActionProv } return codeAction; } + + private async getFixAllForTsCodeAction( + file: string, + diagnostic: vscode.Diagnostic, + tsAction: Proto.CodeFixAction, + token: vscode.CancellationToken + ): Promise { + if (!tsAction.fixId || !this.client.apiVersion.has270Features()) { + return undefined; + } + + const args: Proto.GetCombinedCodeFixRequestArgs = { + scope: { + type: 'file', + args: { file } + }, + fixId: tsAction.fixId + }; + + try { + const combinedCodeFixesResponse = await this.client.execute('getCombinedCodeFix', args, token); + if (!combinedCodeFixesResponse.body) { + return undefined; + } + + const codeAction = new vscode.CodeAction( + localize('fixAllInFileLabel', '{0} (Fix all in file)', tsAction.description), + vscode.CodeActionKind.QuickFix); + codeAction.edit = createWorkspaceEditFromFileCodeEdits(this.client, combinedCodeFixesResponse.body.changes); + codeAction.diagnostics = [diagnostic]; + if (tsAction.commands) { + codeAction.command = { + command: ApplyCodeActionCommand.ID, + arguments: [tsAction], + title: tsAction.description + }; + } + return codeAction; + } catch { + return undefined; + } + } } diff --git a/extensions/typescript/src/features/refactorProvider.ts b/extensions/typescript/src/features/refactorProvider.ts index 14dca20a4b5..c6310dcf0d9 100644 --- a/extensions/typescript/src/features/refactorProvider.ts +++ b/extensions/typescript/src/features/refactorProvider.ts @@ -96,6 +96,9 @@ class SelectRefactorCommand implements Command { } export default class TypeScriptRefactorProvider implements vscode.CodeActionProvider { + private static readonly extractFunctionKind = vscode.CodeActionKind.RefactorExtract.append('function'); + private static readonly extractConstantKind = vscode.CodeActionKind.RefactorExtract.append('constant'); + constructor( private readonly client: ITypeScriptServiceClient, formattingOptionsManager: FormattingOptionsManager, @@ -108,13 +111,17 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv public async provideCodeActions( document: vscode.TextDocument, _range: vscode.Range, - _context: vscode.CodeActionContext, + context: vscode.CodeActionContext, token: vscode.CancellationToken ): Promise { if (!this.client.apiVersion.has240Features()) { return []; } + if (context.only && !vscode.CodeActionKind.Refactor.contains(context.only)) { + return []; + } + if (!vscode.window.activeTextEditor) { return []; } @@ -140,24 +147,22 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv const actions: vscode.CodeAction[] = []; for (const info of response.body) { if (info.inlineable === false) { - actions.push({ + const codeAction = new vscode.CodeAction(info.description, vscode.CodeActionKind.Refactor); + codeAction.command = { title: info.description, - command: { - title: info.description, - command: SelectRefactorCommand.ID, - arguments: [document, file, info, range] - } - }); + command: SelectRefactorCommand.ID, + arguments: [document, file, info, range] + }; + actions.push(codeAction); } else { for (const action of info.actions) { - actions.push({ + const codeAction = new vscode.CodeAction(action.description, TypeScriptRefactorProvider.getKind(action)); + codeAction.command = { title: action.description, - command: { - title: action.description, - command: ApplyRefactoringCommand.ID, - arguments: [document, file, info.name, action.name, range] - } - }); + command: ApplyRefactoringCommand.ID, + arguments: [document, file, info.name, action.name, range] + }; + actions.push(codeAction); } } } @@ -166,4 +171,13 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv return []; } } + + private static getKind(refactor: Proto.RefactorActionInfo) { + if (refactor.name.startsWith('function_')) { + return TypeScriptRefactorProvider.extractFunctionKind; + } else if (refactor.name.startsWith('constant_')) { + return TypeScriptRefactorProvider.extractConstantKind; + } + return vscode.CodeActionKind.Refactor; + } } \ No newline at end of file diff --git a/extensions/typescript/src/typescriptService.ts b/extensions/typescript/src/typescriptService.ts index fbcda9c7938..db51d60464c 100644 --- a/extensions/typescript/src/typescriptService.ts +++ b/extensions/typescript/src/typescriptService.ts @@ -61,6 +61,7 @@ export interface ITypeScriptServiceClient { execute(command: 'navtree', args: Proto.FileRequestArgs, token?: CancellationToken): Promise; execute(command: 'getCodeFixes', args: Proto.CodeFixRequestArgs, token?: CancellationToken): Promise; execute(command: 'getSupportedCodeFixes', args: null, token?: CancellationToken): Promise; + execute(command: 'getCombinedCodeFix', args: Proto.GetCombinedCodeFixRequestArgs, token?: CancellationToken): Promise; execute(command: 'docCommentTemplate', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise; execute(command: 'getApplicableRefactors', args: Proto.GetApplicableRefactorsRequestArgs, token?: CancellationToken): Promise; execute(command: 'getEditsForRefactor', args: Proto.GetEditsForRefactorRequestArgs, token?: CancellationToken): Promise; diff --git a/extensions/typescript/src/typescriptServiceClient.ts b/extensions/typescript/src/typescriptServiceClient.ts index 2901d184ba1..a36818b3905 100644 --- a/extensions/typescript/src/typescriptServiceClient.ts +++ b/extensions/typescript/src/typescriptServiceClient.ts @@ -578,12 +578,12 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient } public normalizePath(resource: Uri): string | null { - if (resource.scheme === fileSchemes.walkThroughSnippet) { - return resource.toString(); - } - - if (resource.scheme === fileSchemes.untitled && this._apiVersion.has213Features()) { - return resource.toString(); + if (this._apiVersion.has213Features()) { + if (resource.scheme === fileSchemes.walkThroughSnippet || resource.scheme === fileSchemes.untitled) { + const dirName = path.dirname(resource.path); + const fileName = this.inMemoryResourcePrefix + path.basename(resource.path); + return resource.with({ path: path.join(dirName, fileName) }).toString(true); + } } if (resource.scheme !== fileSchemes.file) { @@ -599,11 +599,24 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/'); } + private get inMemoryResourcePrefix(): string { + return this._apiVersion.has270Features() ? '^' : ''; + } + public asUrl(filepath: string): Uri { - if (filepath.startsWith(TypeScriptServiceClient.WALK_THROUGH_SNIPPET_SCHEME_COLON) - || (filepath.startsWith(fileSchemes.untitled + ':') && this._apiVersion.has213Features()) - ) { - return Uri.parse(filepath); + if (this._apiVersion.has213Features()) { + if (filepath.startsWith(TypeScriptServiceClient.WALK_THROUGH_SNIPPET_SCHEME_COLON) || (filepath.startsWith(fileSchemes.untitled + ':')) + ) { + let resource = Uri.parse(filepath); + if (this.inMemoryResourcePrefix) { + const dirName = path.dirname(resource.path); + const fileName = path.basename(resource.path); + if (fileName.startsWith(this.inMemoryResourcePrefix)) { + resource = resource.with({ path: path.join(dirName, fileName.slice(this.inMemoryResourcePrefix.length)) }); + } + } + return resource; + } } return Uri.file(filepath); } @@ -620,8 +633,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient return root.uri.fsPath; } } + return roots[0].uri.fsPath; } - return roots[0].uri.fsPath; + + return undefined; } public execute(command: string, args: any, expectsResultOrToken?: boolean | CancellationToken): Promise { diff --git a/extensions/typescript/src/utils/api.ts b/extensions/typescript/src/utils/api.ts index 6e13c01a574..e4103a29231 100644 --- a/extensions/typescript/src/utils/api.ts +++ b/extensions/typescript/src/utils/api.ts @@ -7,6 +7,9 @@ import * as semver from 'semver'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); +import { memoize } from './memoize'; + + export default class API { public static readonly defaultVersion = new API('1.0.0', '1.0.0'); @@ -29,51 +32,68 @@ export default class API { private readonly version: string ) { } + @memoize public has203Features(): boolean { return semver.gte(this.version, '2.0.3'); } + @memoize public has206Features(): boolean { return semver.gte(this.version, '2.0.6'); } + @memoize public has208Features(): boolean { return semver.gte(this.version, '2.0.8'); } + @memoize public has213Features(): boolean { return semver.gte(this.version, '2.1.3'); } + @memoize public has220Features(): boolean { return semver.gte(this.version, '2.2.0'); } + @memoize public has222Features(): boolean { return semver.gte(this.version, '2.2.2'); } + @memoize public has230Features(): boolean { return semver.gte(this.version, '2.3.0'); } + @memoize public has234Features(): boolean { return semver.gte(this.version, '2.3.4'); } + @memoize public has240Features(): boolean { return semver.gte(this.version, '2.4.0'); } + @memoize public has250Features(): boolean { return semver.gte(this.version, '2.5.0'); } + @memoize public has260Features(): boolean { return semver.gte(this.version, '2.6.0'); } + @memoize public has262Features(): boolean { return semver.gte(this.version, '2.6.2'); } + + @memoize + public has270Features(): boolean { + return semver.gte(this.version, '2.7.0'); + } } \ No newline at end of file diff --git a/extensions/typescript/src/utils/codeAction.ts b/extensions/typescript/src/utils/codeAction.ts index e3fc0178af1..4c05629c78c 100644 --- a/extensions/typescript/src/utils/codeAction.ts +++ b/extensions/typescript/src/utils/codeAction.ts @@ -5,26 +5,16 @@ import { WorkspaceEdit, workspace } from 'vscode'; import * as Proto from '../protocol'; -import { tsTextSpanToVsRange } from './convert'; import { ITypeScriptServiceClient } from '../typescriptService'; +import { createWorkspaceEditFromFileCodeEdits } from './workspaceEdit'; export function getEditForCodeAction( client: ITypeScriptServiceClient, action: Proto.CodeAction ): WorkspaceEdit | undefined { - if (action.changes && action.changes.length) { - const workspaceEdit = new WorkspaceEdit(); - for (const change of action.changes) { - for (const textChange of change.textChanges) { - workspaceEdit.replace(client.asUrl(change.fileName), - tsTextSpanToVsRange(textChange), - textChange.newText); - } - } - - return workspaceEdit; - } - return undefined; + return action.changes && action.changes.length + ? createWorkspaceEditFromFileCodeEdits(client, action.changes) + : undefined; } export async function applyCodeAction( diff --git a/extensions/typescript/src/utils/memoize.ts b/extensions/typescript/src/utils/memoize.ts new file mode 100644 index 00000000000..beeb0035b89 --- /dev/null +++ b/extensions/typescript/src/utils/memoize.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export function memoize(_target: any, key: string, descriptor: any) { + let fnKey: string | undefined = undefined; + let fn: Function | undefined = undefined; + + if (typeof descriptor.value === 'function') { + fnKey = 'value'; + fn = descriptor.value; + } else if (typeof descriptor.get === 'function') { + fnKey = 'get'; + fn = descriptor.get; + } else { + throw new Error('not supported'); + } + + const memoizeKey = `$memoize$${key}`; + + descriptor[fnKey] = function (...args: any[]) { + if (!this.hasOwnProperty(memoizeKey)) { + Object.defineProperty(this, memoizeKey, { + configurable: false, + enumerable: false, + writable: false, + value: fn!.apply(this, args) + }); + } + + return this[memoizeKey]; + }; +} diff --git a/extensions/typescript/src/utils/previewer.ts b/extensions/typescript/src/utils/previewer.ts index 22e39cf9079..647ae3bf91b 100644 --- a/extensions/typescript/src/utils/previewer.ts +++ b/extensions/typescript/src/utils/previewer.ts @@ -27,7 +27,7 @@ function getTagBodyText(tag: Proto.JSDocTagInfo): string | undefined { function getTagDocumentation(tag: Proto.JSDocTagInfo): string | undefined { switch (tag.name) { case 'param': - const body = (tag.text || '').split(/^(\w+)\s*/); + const body = (tag.text || '').split(/^([\w\.]+)\s*/); if (body && body.length === 3) { const param = body[1]; const doc = body[2]; diff --git a/extensions/typescript/src/utils/versionStatus.ts b/extensions/typescript/src/utils/versionStatus.ts index 3ed92289670..69871458646 100644 --- a/extensions/typescript/src/utils/versionStatus.ts +++ b/extensions/typescript/src/utils/versionStatus.ts @@ -40,8 +40,10 @@ export default class VersionStatus { if (vscode.languages.match([languageModeIds.typescript, languageModeIds.typescriptreact], doc)) { if (this.normalizePath(doc.uri)) { this.versionBarEntry.show(); - return; + } else { + this.versionBarEntry.hide(); } + return; } if (!vscode.window.activeTextEditor.viewColumn) { diff --git a/extensions/typescript/src/utils/workspaceEdit.ts b/extensions/typescript/src/utils/workspaceEdit.ts new file mode 100644 index 00000000000..4cb29eb8467 --- /dev/null +++ b/extensions/typescript/src/utils/workspaceEdit.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as vscode from 'vscode'; +import { ITypeScriptServiceClient } from '../typescriptService'; +import * as Proto from '../protocol'; +import { tsTextSpanToVsRange } from './convert'; + +export function createWorkspaceEditFromFileCodeEdits( + client: ITypeScriptServiceClient, + edits: Iterable +): vscode.WorkspaceEdit { + const workspaceEdit = new vscode.WorkspaceEdit(); + for (const edit of edits) { + for (const textChange of edit.textChanges) { + workspaceEdit.replace(client.asUrl(edit.fileName), + tsTextSpanToVsRange(textChange), + textChange.newText); + } + } + + return workspaceEdit; +} \ No newline at end of file diff --git a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json index cc81558cfc2..b76d98425eb 100644 --- a/extensions/typescript/syntaxes/TypeScript.tmLanguage.json +++ b/extensions/typescript/syntaxes/TypeScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/8b44958a27860957872cc6f628d843a71686af63", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/51323af933792ffbb9a088fd500536122be38b59", "name": "TypeScript", "scopeName": "source.ts", "fileTypes": [ @@ -286,7 +286,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.ts", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.ts entity.name.function.ts" @@ -348,7 +348,7 @@ "patterns": [ { "name": "meta.object-binding-pattern-variable.ts", - "begin": "(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.ts" @@ -747,7 +747,7 @@ }, { "name": "meta.definition.property.ts entity.name.function.ts", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))" }, { "name": "meta.definition.property.ts variable.object.property.ts", @@ -1878,7 +1878,7 @@ }, "after-operator-block-as-object-literal": { "name": "meta.objectliteral.ts", - "begin": "(?<=[=(,\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\|\\||\\*)\\s*(\\{)", + "begin": "(?<=[=(,\\[?+!]|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^yield|[^\\._$[:alnum:]]yield|^throw|[^\\._$[:alnum:]]throw|^in|[^\\._$[:alnum:]]in|^of|[^\\._$[:alnum:]]of|^typeof|[^\\._$[:alnum:]]typeof|&&|\\|\\||\\*)\\s*(\\{)", "beginCaptures": { "1": { "name": "punctuation.definition.block.ts" @@ -2051,13 +2051,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.ts", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2163,7 +2163,7 @@ "patterns": [ { "name": "cast.expr.ts", - "begin": "(?:(?<=return|throw|yield|await|default|[=(,:>*?\\&\\|\\^]|[^_$[:alnum:]](?:\\+\\+|\\-\\-)|[^\\+]\\+|[^\\-]\\-))\\s*(<)(?!*?\\&\\|\\^]|[^_$[:alnum:]](?:\\+\\+|\\-\\-)|[^\\+]\\+|[^\\-]\\-))\\s*(<)(?!|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.ts" diff --git a/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json b/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json index 5da35c8fe7f..c8bb27a8610 100644 --- a/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json +++ b/extensions/typescript/syntaxes/TypeScriptReact.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/8b44958a27860957872cc6f628d843a71686af63", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/51323af933792ffbb9a088fd500536122be38b59", "name": "TypeScriptReact", "scopeName": "source.tsx", "fileTypes": [ @@ -289,7 +289,7 @@ "patterns": [ { "name": "meta.var-single-variable.expr.tsx", - "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx entity.name.function.tsx" @@ -351,7 +351,7 @@ "patterns": [ { "name": "meta.object-binding-pattern-variable.tsx", - "begin": "(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))", "captures": { "1": { "name": "storage.modifier.tsx" @@ -750,7 +750,7 @@ }, { "name": "meta.definition.property.tsx entity.name.function.tsx", - "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)))" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n# function assignment |\n(=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)) |\n# typeannotation is fn type: < | () | (... | (param: | (param, | (param? | (param= | (param) =>\n(:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n)) |\n(:\\s*(=>|(\\([^\\(\\)]*\\))|(<[^<>]*>)|[^<>(),=])+=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n # sure shot arrow functions even if => is on new line\n(\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n) |\n(\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends\n) |\n# arrow function possible to detect only with => on same line\n(\n (<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<]|\\<\\s*([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))([^=<>]|=[^<])*\\>)*>\\s*)? # typeparameters\n \\(\\s*([_$[:alpha:]\\{\\[]([^()]|\\((\\s*[^()]*)?\\))*)?\\) # parameteres\n (\\s*:\\s*([^<>\\(\\)]|\\<[^<>]+\\>|\\([^\\(\\)]+\\))+)? # return type\n \\s*=> # arrow operator\n)\n ))\n)))" }, { "name": "meta.definition.property.tsx variable.object.property.tsx", @@ -1881,7 +1881,7 @@ }, "after-operator-block-as-object-literal": { "name": "meta.objectliteral.tsx", - "begin": "(?<=[=(,\\[?+!]|await|return|yield|throw|in|of|typeof|&&|\\|\\||\\*)\\s*(\\{)", + "begin": "(?<=[=(,\\[?+!]|^await|[^\\._$[:alnum:]]await|^return|[^\\._$[:alnum:]]return|^yield|[^\\._$[:alnum:]]yield|^throw|[^\\._$[:alnum:]]throw|^in|[^\\._$[:alnum:]]in|^of|[^\\._$[:alnum:]]of|^typeof|[^\\._$[:alnum:]]typeof|&&|\\|\\||\\*)\\s*(\\{)", "beginCaptures": { "1": { "name": "punctuation.definition.block.tsx" @@ -2054,13 +2054,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.tsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\??\\.\\s*)*|(\\??\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\)))*\\>)*>\\s*)?\\()", + "end": "(?=\\s*(\\?\\.\\s*)?(<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>|\\<\\s*(([_$[:alpha:]]|(\\{[^\\{\\}]*\\})|(\\([^\\(\\)]*\\))|(\\[[^\\[\\]]*\\]))|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))([^<>\\(]|(\\([^\\(\\)]*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -3292,7 +3292,7 @@ "patterns": [ { "name": "string.regexp.tsx", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.tsx" @@ -4038,7 +4038,7 @@ ] }, "jsx-tag-without-attributes-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?=(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "end": "(?!\\s*(<)\\s*((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?))", "patterns": [ { @@ -4086,7 +4086,7 @@ ] }, "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", + "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", "end": "(/>)|(?:())", "endCaptures": { "0": { diff --git a/extensions/typescript/tsconfig.json b/extensions/typescript/tsconfig.json index 56de6915ae5..e9800fa4b00 100644 --- a/extensions/typescript/tsconfig.json +++ b/extensions/typescript/tsconfig.json @@ -12,7 +12,8 @@ "noUnusedLocals": true, "noUnusedParameters": true, "strict": true, - "alwaysStrict": true + "alwaysStrict": true, + "experimentalDecorators": true }, "include": [ "src/**/*" diff --git a/extensions/typescript/yarn.lock b/extensions/typescript/yarn.lock index eb4fd8e25fd..5f6bdee5635 100644 --- a/extensions/typescript/yarn.lock +++ b/extensions/typescript/yarn.lock @@ -25,9 +25,9 @@ vscode-extension-telemetry@^0.0.8: applicationinsights "0.18.0" winreg "1.2.3" -vscode-nls@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da" +vscode-nls@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.1.2.tgz#c1b63f4338ac49c852267633dd99717916424a74" winreg@1.2.3: version "1.2.3" diff --git a/extensions/vscode-api-tests/src/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts similarity index 100% rename from extensions/vscode-api-tests/src/commands.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts diff --git a/extensions/vscode-api-tests/src/configuration.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts similarity index 100% rename from extensions/vscode-api-tests/src/configuration.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts diff --git a/extensions/vscode-api-tests/src/editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts similarity index 99% rename from extensions/vscode-api-tests/src/editor.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts index a5d597b4bc0..0743a5e0cb3 100644 --- a/extensions/vscode-api-tests/src/editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { workspace, window, Position, Range, commands, TextEditor, TextDocument, TextEditorCursorStyle, TextEditorLineNumbersStyle, SnippetString, Selection } from 'vscode'; -import { createRandomFile, deleteFile, closeAllEditors } from './utils'; +import { createRandomFile, deleteFile, closeAllEditors } from '../utils'; suite('editor tests', () => { diff --git a/extensions/vscode-api-tests/src/env.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts similarity index 100% rename from extensions/vscode-api-tests/src/env.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts diff --git a/extensions/vscode-api-tests/src/index.ts b/extensions/vscode-api-tests/src/singlefolder-tests/index.ts similarity index 100% rename from extensions/vscode-api-tests/src/index.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/index.ts diff --git a/extensions/vscode-api-tests/src/languages.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts similarity index 99% rename from extensions/vscode-api-tests/src/languages.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts index 01dea3ddc3f..e385d5287fd 100644 --- a/extensions/vscode-api-tests/src/languages.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts @@ -21,7 +21,7 @@ suite('languages namespace tests', () => { constructor() { super(new Range(0, 2, 0, 7), 'sonntag'); } - }; + } let diag1 = new Diagnostic(new Range(0, 0, 0, 5), 'montag'); let diag2 = new D2(); diff --git a/extensions/vscode-api-tests/src/window.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts similarity index 99% rename from extensions/vscode-api-tests/src/window.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts index 2a2f92c90e7..97bace17e73 100644 --- a/extensions/vscode-api-tests/src/window.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { workspace, window, commands, ViewColumn, TextEditorViewColumnChangeEvent, Uri, Selection, Position, CancellationTokenSource, TextEditorSelectionChangeKind } from 'vscode'; import { join } from 'path'; -import { closeAllEditors, pathEquals, createRandomFile } from './utils'; +import { closeAllEditors, pathEquals, createRandomFile } from '../utils'; suite('window namespace tests', () => { diff --git a/extensions/vscode-api-tests/src/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts similarity index 90% rename from extensions/vscode-api-tests/src/workspace.test.ts rename to extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index d4c4ae7013c..87ec01ef072 100644 --- a/extensions/vscode-api-tests/src/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; -import { createRandomFile, deleteFile, closeAllEditors, pathEquals } from './utils'; +import { createRandomFile, deleteFile, closeAllEditors, pathEquals } from '../utils'; import { join, basename } from 'path'; import * as fs from 'fs'; @@ -38,11 +38,27 @@ suite('workspace-namespace', () => { test('rootPath', () => { if (vscode.workspace.rootPath) { - assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../testWorkspace'))); + assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../../testWorkspace'))); } assert.throws(() => vscode.workspace.rootPath = 'farboo'); }); + test('workspaceFolders', () => { + if (vscode.workspace.workspaceFolders) { + assert.equal(vscode.workspace.workspaceFolders.length, 1); + assert.ok(pathEquals(vscode.workspace.workspaceFolders[0].uri.fsPath, join(__dirname, '../../testWorkspace'))); + } + }); + + test('getWorkspaceFolder', () => { + const folder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(join(__dirname, '../../testWorkspace/far.js'))); + assert.ok(!!folder); + + if (folder) { + assert.ok(pathEquals(folder.uri.fsPath, join(__dirname, '../../testWorkspace'))); + } + }); + test('openTextDocument', () => { let len = vscode.workspace.textDocuments.length; return vscode.workspace.openTextDocument(join(vscode.workspace.rootPath || '', './simple.txt')).then(doc => { @@ -505,4 +521,44 @@ suite('workspace-namespace', () => { return vscode.workspace.applyEdit(edit); }); }); + + + test('applyEdit should fail when editing deleted resource', async () => { + const resource = await createRandomFile(); + + const edit = new vscode.WorkspaceEdit(); + edit.deleteResource(resource); + try { + edit.insert(resource, new vscode.Position(0, 0), ''); + assert.fail(false, 'Should disallow edit of deleted resource'); + } catch { + // noop + } + }); + + test('applyEdit should fail when renaming deleted resource', async () => { + const resource = await createRandomFile(); + + const edit = new vscode.WorkspaceEdit(); + edit.deleteResource(resource); + try { + edit.renameResource(resource, resource); + assert.fail(false, 'Should disallow rename of deleted resource'); + } catch { + // noop + } + }); + + test('applyEdit should fail when editing renamed from resource', async () => { + const resource = await createRandomFile(); + const newResource = vscode.Uri.parse(resource.fsPath + '.1'); + const edit = new vscode.WorkspaceEdit(); + edit.renameResource(resource, newResource); + try { + edit.insert(resource, new vscode.Position(0, 0), ''); + assert.fail(false, 'Should disallow editing renamed file'); + } catch { + // noop + } + }); }); diff --git a/extensions/vscode-api-tests/src/workspace-tests/index.ts b/extensions/vscode-api-tests/src/workspace-tests/index.ts new file mode 100644 index 00000000000..f65a756a8de --- /dev/null +++ b/extensions/vscode-api-tests/src/workspace-tests/index.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// +// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING +// +// This file is providing the test runner to use when running extension tests. +// By default the test runner in use is Mocha based. +// +// You can provide your own test runner if you want to override it by exporting +// a function run(testRoot: string, clb: (error:Error) => void) that the extension +// host can call to run the tests. The test runner is expected to use console.log +// to report the results back to the caller. When the tests are finished, return +// a possible error to the callback or null if none. + +const testRunner = require('vscode/lib/testrunner'); + +// You can directly control Mocha options by uncommenting the following lines +// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info +testRunner.configure({ + ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) + useColors: process.platform !== 'win32', // colored output from test results (only windows cannot handle) + timeout: 60000 +}); + +export = testRunner; diff --git a/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts new file mode 100644 index 00000000000..5453c2adec3 --- /dev/null +++ b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { closeAllEditors, pathEquals } from '../utils'; +import { join } from 'path'; + +suite('workspace-namespace', () => { + + teardown(closeAllEditors); + + test('rootPath', () => { + if (vscode.workspace.rootPath) { + assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../../testWorkspace'))); + } + }); + + test('workspaceFolders', () => { + if (vscode.workspace.workspaceFolders) { + assert.equal(vscode.workspace.workspaceFolders.length, 2); + assert.ok(pathEquals(vscode.workspace.workspaceFolders[0].uri.fsPath, join(__dirname, '../../testWorkspace'))); + assert.ok(pathEquals(vscode.workspace.workspaceFolders[1].uri.fsPath, join(__dirname, '../../testWorkspace2'))); + assert.ok(pathEquals(vscode.workspace.workspaceFolders[1].name, 'Test Workspace 2')); + } + }); + + test('getWorkspaceFolder', () => { + const folder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(join(__dirname, '../../testWorkspace2/far.js'))); + assert.ok(!!folder); + + if (folder) { + assert.ok(pathEquals(folder.uri.fsPath, join(__dirname, '../../testWorkspace2'))); + } + }); +}); diff --git a/extensions/vscode-api-tests/testWorkspace2/simple.txt b/extensions/vscode-api-tests/testWorkspace2/simple.txt new file mode 100644 index 00000000000..b5462829966 --- /dev/null +++ b/extensions/vscode-api-tests/testWorkspace2/simple.txt @@ -0,0 +1 @@ +Just a simple file... \ No newline at end of file diff --git a/extensions/vscode-api-tests/testworkspace.code-workspace b/extensions/vscode-api-tests/testworkspace.code-workspace new file mode 100644 index 00000000000..7e93fe23c42 --- /dev/null +++ b/extensions/vscode-api-tests/testworkspace.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "testWorkspace" + }, + { + "path": "testWorkspace2", + "name": "Test Workspace 2" + } + ] +} \ No newline at end of file diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 64815a3eb3f..1fc13a8f83b 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,6 +2,6 @@ # yarn lockfile v1 -typescript@2.7.0-insiders.20180108: - version "2.7.0-insiders.20180108" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.0-insiders.20180108.tgz#b9230ca5a0020e92133f63e6a4272f8c1b301bdb" +typescript@2.7.0-insiders.20180119: + version "2.7.0-insiders.20180119" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.0-insiders.20180119.tgz#556c59eaabb0758dd1a2f0b0602a355746d33277" diff --git a/i18n/chs/extensions/git/out/autofetch.i18n.json b/i18n/chs/extensions/git/out/autofetch.i18n.json index 6df74592845..823bb93043f 100644 --- a/i18n/chs/extensions/git/out/autofetch.i18n.json +++ b/i18n/chs/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "是", + "read more": "了解详细信息", "no": "否", - "not now": "不是现在", - "suggest auto fetch": "是否启用自动抓取 Git 存储库?" + "not now": "稍后询问", + "suggest auto fetch": "您希望 Code 定期运行 \"git fetch\" 吗?" } \ No newline at end of file diff --git a/i18n/chs/extensions/git/out/commands.i18n.json b/i18n/chs/extensions/git/out/commands.i18n.json index 8f5f2a83f79..a19bebe875b 100644 --- a/i18n/chs/extensions/git/out/commands.i18n.json +++ b/i18n/chs/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\n此操作不可撤销,你当前的工作集将会永远丢失。", "yes discard tracked": "放弃 1 个已跟踪的文件", "yes discard tracked multiple": "放弃 {0} 个已跟踪的文件", + "unsaved files single": "以下文件尚未保存:{0}。\n\n您要在提交之前保存吗?", + "unsaved files": "当前有 {0} 个文件尚未保存。\n\n您要在提交之前保存吗?", + "save and commit": "全部保存并提交", + "commit": "仍要提交", "no staged changes": "现在没有暂存的更改以供提交\n\n是否要直接自动暂存所有更改并提交?", "always": "始终", "no changes": "没有要提交的更改。", @@ -64,12 +68,13 @@ "no remotes to pull": "存储库未配置任何从其中进行拉取的远程存储库。", "pick remote pull repo": "选择要从其拉取分支的远程位置", "no remotes to push": "存储库未配置任何要推送到的远程存储库。", - "push with tags success": "已成功带标签进行推送。", "nobranch": "请签出一个分支以推送到远程。", + "confirm publish branch": "分支“{0}”没有上游分支。您要发布此分支吗?", + "ok": "确定", + "push with tags success": "已成功带标签进行推送。", "pick remote": "选取要将分支“{0}”发布到的远程:", "sync is unpredictable": "此操作将推送提交至“{0}”,并从中拉取提交。", - "ok": "确定", - "never again": "好,永不再显示", + "never again": "确定,且不再显示", "no remotes to publish": "存储库未配置任何要发布到的远程存储库。", "no changes stash": "没有要储藏的更改。", "provide stash message": "提供储藏消息(可选)", diff --git a/i18n/chs/extensions/git/package.i18n.json b/i18n/chs/extensions/git/package.i18n.json index cb8443b7aec..7b47c05b8f9 100644 --- a/i18n/chs/extensions/git/package.i18n.json +++ b/i18n/chs/extensions/git/package.i18n.json @@ -54,12 +54,13 @@ "command.stashPopLatest": "弹出最新储藏", "config.enabled": "是否启用 Git", "config.path": "Git 可执行文件路径", + "config.autoRepositoryDetection": "是否自动检测存储库", "config.autorefresh": "是否启用自动刷新", "config.autofetch": "是否启用自动拉取", "config.enableLongCommitWarning": "是否针对长段提交消息进行警告", "config.confirmSync": "同步 GIT 存储库前请先进行确认", "config.countBadge": "控制 Git 徽章计数器。“all”计算所有更改。“tracked”只计算跟踪的更改。“off”关闭此功能。", - "config.checkoutType": "控制运行“签出到...”命令时列出的分支的类型。\"all\" 显示所有 refs,\"local\" 只显示本地分支,\"tags\" 只显示标记,\"remote\" 只显示远程分支。", + "config.checkoutType": "控制运行“签出到...”功能时列出的分支类型。\"all\" 显示所有 refs,\"local\" 只显示本地分支,\"tags\" 只显示标签,\"remote\" 只显示远程分支。", "config.ignoreLegacyWarning": "忽略旧版 Git 警告", "config.ignoreMissingGitWarning": "忽略“缺失 Git”警告", "config.ignoreLimitWarning": "忽略“存储库中存在大量更改”的警告", @@ -72,5 +73,6 @@ "colors.deleted": "已删除资源的颜色。", "colors.untracked": "未跟踪资源的颜色。", "colors.ignored": "已忽略资源的颜色。", - "colors.conflict": "存在冲突的资源的颜色。" + "colors.conflict": "存在冲突的资源的颜色。", + "colors.submodule": "子模块资源的颜色。" } \ No newline at end of file diff --git a/i18n/chs/extensions/typescript/out/commands.i18n.json b/i18n/chs/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..36b3b2d5f6b --- /dev/null +++ b/i18n/chs/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "请在 VS Code 中打开一个文件夹,以使用 TypeScript 或 JavaScript 项目", + "typescript.projectConfigUnsupportedFile": "无法确定 TypeScript 或 JavaScript 项目。不受支持的文件类型", + "typescript.projectConfigCouldNotGetInfo": "无法确定 TypeScript 或 JavaScript 项目", + "typescript.noTypeScriptProjectConfig": "文件不属于 TypeScript 项目", + "typescript.noJavaScriptProjectConfig": "文件不属于 JavaScript 项目", + "typescript.configureTsconfigQuickPick": "配置 tsconfig.json", + "typescript.configureJsconfigQuickPick": "配置 jsconfig.json", + "typescript.projectConfigLearnMore": "了解详细信息" +} \ No newline at end of file diff --git a/i18n/chs/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/chs/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..dabfe74346b --- /dev/null +++ b/i18n/chs/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (修复文件中所有问题)" +} \ No newline at end of file diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/media/codeEditor.css b/i18n/chs/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json similarity index 79% rename from src/vs/workbench/parts/codeEditor/electron-browser/media/codeEditor.css rename to i18n/chs/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json index 443058958ac..ed15423097d 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/media/codeEditor.css +++ b/i18n/chs/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -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. *--------------------------------------------------------------------------------------------*/ - -.toggle-word-wrap-action { - background: url('WordWrap_16x.svg') center center no-repeat; -} +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/base/node/ps.i18n.json b/i18n/chs/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..da69e94cccc --- /dev/null +++ b/i18n/chs/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "正在收集 CPU 与内存信息。这可能需要几秒钟的时间。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json index 9c145d8c4d9..7633e13d1a4 100644 --- a/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/chs/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "将行号显示为绝对行数。", "lineNumbers.relative": "将行号显示为与光标相隔的行数。", "lineNumbers.interval": "每 10 行显示一次行号。", - "lineNumbers": "控制行号的显示。可选值为 \"on\"、\"off\" 和 \"relative\"。", + "lineNumbers": "控制行号的显示。可选值为 \"on\"、\"off\"、\"relative\" 和 \"interval\"。", "rulers": "在一定数量的等宽字符后显示垂直标尺。输入多个值,显示多个标尺。若数组为空,则不绘制标尺。", "wordSeparators": "执行文字相关的导航或操作时将用作文字分隔符的字符", "tabSize": "一个制表符等于的空格数。该设置在 \"editor.detectIndentation\" 启用时根据文件内容可能会被覆盖。", @@ -40,9 +40,9 @@ "wordWrapColumn": "在 \"editor.wordWrap\" 为 \"wordWrapColumn\" 或 \"bounded\" 时控制编辑器列的换行。", "wrappingIndent": "控制折行的缩进。可以是“none”、“same”或“indent”。", "mouseWheelScrollSensitivity": "要对鼠标滚轮滚动事件的 \"deltaX\" 和 \"deltaY\" 使用的乘数 ", - "multiCursorModifier.ctrlCmd": "映射到“Control”(Windows 和 Linux)或“Command”(OSX)。", - "multiCursorModifier.alt": "映射到“Alt”(Windows 和 Linux)或“Option”(OSX)。", - "multiCursorModifier": "用鼠标添加多个光标时使用的修改键。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (OSX)。“转到定义”和“打开链接”功能所需的动作将会相应调整,不与多光标修改键冲突。", + "multiCursorModifier.ctrlCmd": "映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)", + "multiCursorModifier.alt": "映射为 \"Alt\" (Windows 和 Linux) 或 \"Option\" (macOS)", + "multiCursorModifier": "在通过鼠标添加多个光标时使用的修改键。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)。“转到定义”和“打开链接”功能所需的鼠标动作将会相应调整,不与多光标修改键冲突。", "quickSuggestions.strings": "在字符串内启用快速建议。", "quickSuggestions.comments": "在注释内启用快速建议。", "quickSuggestions.other": "在字符串和注释外启用快速建议。", @@ -72,6 +72,7 @@ "cursorBlinking": "控制光标动画样式,可能的值为 \"blink\"、\"smooth\"、\"phase\"、\"expand\" 和 \"solid\"", "mouseWheelZoom": "通过使用鼠标滚轮同时按住 Ctrl 可缩放编辑器的字体", "cursorStyle": "控制光标样式,接受的值为 \"block\"、\"block-outline\"、\"line\"、\"line-thin\" 、\"underline\" 和 \"underline-thin\"", + "lineCursorWidth": "当 editor.cursorStyle 设置为 \"line\" 时控制光标的宽度。", "fontLigatures": "启用字体连字", "hideCursorInOverviewRuler": "控制光标是否应隐藏在概述标尺中。", "renderWhitespace": "控制编辑器中呈现空白字符的方式,可能为“无”、“边界”和“全部”。“边界”选项不会在单词之间呈现单空格。", diff --git a/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json index 168dd2fb958..6d1dfc8be23 100644 --- a/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/chs/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "光标所在行高亮内容的背景颜色。", "lineHighlightBorderBox": "光标所在行四周边框的背景颜色。", - "rangeHighlight": "高亮范围的背景色,例如由 \"Quick Open\" 和“查找”功能高亮的范围。", + "rangeHighlight": "高亮范围的背景色,例如由 \"Quick Open\" 和“查找”功能高亮的范围。颜色必须透明,这样不会挡住其下的其他元素。", "caret": "编辑器光标颜色。", "editorCursorBackground": "编辑器光标的背景色。可以自定义块型光标覆盖字符的颜色。", "editorWhitespaces": "编辑器中空白字符的颜色。", diff --git a/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 8dc6ee58760..2e70001e92c 100644 --- a/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "转到下一个错误或警告", - "markerAction.previous.label": "转到上一个错误或警告", + "markerAction.next.label": "转到下一个问题 (错误、警告、信息)", + "markerAction.previous.label": "转到上一个问题 (错误、警告、信息)", "editorMarkerNavigationError": "编辑器标记导航小组件错误颜色。", "editorMarkerNavigationWarning": "编辑器标记导航小组件警告颜色。", "editorMarkerNavigationInfo": "编辑器标记导航小组件信息颜色。", diff --git a/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 7926047995c..185a3d31620 100644 --- a/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/chs/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "读取访问时符号的背景颜色,例如读取变量时。", - "wordHighlightStrong": "写入访问时符号的背景颜色,例如写入变量时。", + "wordHighlight": "进行读取访问操作时符号的背景颜色,例如读取变量时。颜色必须透明,这样不会挡住其下的其他元素。", + "wordHighlightStrong": "进行写入访问操作时符号的背景颜色,例如写入变量时。颜色必须透明,这样不会挡住其下的其他元素。", "overviewRulerWordHighlightForeground": "概述符号突出显示的标尺标记颜色。", "overviewRulerWordHighlightStrongForeground": "概述写访问符号突出显示的标尺标记颜色。", "wordHighlight.next.label": "转到下一个突出显示的符号", diff --git a/i18n/chs/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/chs/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index d14243882a7..dd181ef9f45 100644 --- a/i18n/chs/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/chs/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "“{0}”为无效菜单标识符", "missing.command": "菜单项引用未在“命令”部分进行定义的命令“{0}”。", "missing.altCommand": "菜单项引用了未在 \"commands\" 部分定义的替代命令“{0}”。", - "dupe.command": "菜单项引用的命令中默认和替代命令相同", - "nosupport.altCommand": "抱歉,目前仅有 \"editor/title\" 菜单的 \"navigation\" 组支持替代命令" + "dupe.command": "菜单项引用的命令中默认和替代命令相同" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/environment/node/argv.i18n.json b/i18n/chs/src/vs/platform/environment/node/argv.i18n.json index 9a1faa5d983..2f9194ac09c 100644 --- a/i18n/chs/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/chs/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,36 @@ "diff": "将两个文件相互比较。", "add": "将文件夹添加到最后一个活动窗口。", "goto": "打开路径下的文件并定位到特定行和特定列。", - "locale": "要使用的区域设置(例如 en-US 或 zh-TW)。", "newWindow": "强制创建一个新的 Code 实例。", - "performance": "通过启用 \"Developer: Startup Performance\" 命令开始。", - "prof-startup": "启动期间运行 CPU 探查器", - "inspect-extensions": "允许进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", - "inspect-brk-extensions": "允许在扩展主机在启动后暂停时进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", "reuseWindow": "在上一活动窗口中强制打开文件或文件夹。", - "userDataDir": "指定存放用户数据的目录。此目录在以 root 身份运行时十分有用。", - "log": "使用的日志级别。默认值为 \"info\"。允许的值为 \"critical\" (关键)、\"error\" (错误)、\"warn\" (警告)、\"info\" (信息)、\"debug\" (调试)、\"trace\" (跟踪) 和 \"off\" (关闭)。", - "verbose": "打印详细输出(隐含 --wait 参数)。", "wait": "等文件关闭后再返回。", + "locale": "要使用的区域设置(例如 en-US 或 zh-TW)。", + "userDataDir": "指定存放用户数据的目录。此目录在以 root 身份运行时十分有用。", + "version": "打印版本。", + "help": "打印使用情况。", "extensionHomePath": "设置扩展的根路径。", "listExtensions": "列出已安装的扩展。", "showVersions": "使用 --list-extension 时,显示已安装扩展的版本。", "installExtension": "安装扩展。", "uninstallExtension": "卸载扩展。", "experimentalApis": "启用扩展程序实验性 api 功能。", - "disableExtensions": "禁用所有已安装的扩展。", - "disableGPU": "禁用 GPU 硬件加速。", + "verbose": "打印详细输出(隐含 --wait 参数)。", + "log": "使用的日志级别。默认值为 \"info\"。允许的值为 \"critical\" (关键)、\"error\" (错误)、\"warn\" (警告)、\"info\" (信息)、\"debug\" (调试)、\"trace\" (跟踪) 和 \"off\" (关闭)。", "status": "打印进程使用情况和诊断信息。", - "version": "打印版本。", - "help": "打印使用情况。", + "performance": "通过启用 \"Developer: Startup Performance\" 命令开始。", + "prof-startup": "启动期间运行 CPU 探查器", + "disableExtensions": "禁用所有已安装的扩展。", + "inspect-extensions": "允许进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", + "inspect-brk-extensions": "允许在扩展主机在启动后暂停时进行扩展的调试与分析。检查开发人员工具可获取连接 URI。", + "disableGPU": "禁用 GPU 硬件加速。", + "uploadLogs": "将当前会话的日志上传到安全端点。", + "issue": "报告问题。", "usage": "使用情况", "options": "选项", "paths": "路径", - "optionsUpperCase": "选项" + "stdinWindows": "要读取其他程序的输出,请追加 \"-\" (例如 \"echo Hello World\" | {0} -')", + "stdinUnix": "要从 stdin 中读取,请追加 \"-\" (例如 \"ps aux | grep code | {0} -')", + "optionsUpperCase": "选项", + "extensionsManagement": "扩展管理", + "troubleshooting": "故障排查" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index a6e3a8ea7bc..c72b93d1de9 100644 --- a/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/chs/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "扩展无效: package.json 不是 JSON 文件。", - "restartCodeLocal": "请先重启 Code 再重新安装 {0}。", + "restartCode": "请先重启 Code 再重新安装 {0}。", "installingOutdatedExtension": "您已安装此扩展的新版程序。是否要使用旧版覆盖?", "override": "覆盖", "cancel": "取消", - "notFoundCompatible": "无法安装。找不到与 VS Code 当前版本 ({1}) 兼容的扩展“{0}”。", - "quitCode": "无法安装,因为此扩展的一个过时实例仍在运行。请先完全重启 VS Code,再重新安装。", - "exitCode": "无法安装,因为此扩展的一个过时实例仍在运行。请先完全重启 VS Code,再重新安装。", + "errorInstallingDependencies": "安装依赖项时出错。{0}", + "notFoundCompatible": "无法安装“{0}”;没有可用的版本与 VS Code “{1}”兼容。", "notFoundCompatibleDependency": "无法安装。找不到与 VS Code 当前版本 ({1}) 兼容的依赖扩展“{0}”。", + "quitCode": "无法安装扩展。请在重启 VS Code 后重新安装。", + "exitCode": "无法安装扩展。请在重启 VS Code 后重新安装。", "uninstallDependeciesConfirmation": "要仅卸载“{0}”或者其依赖项也一起卸载?", "uninstallOnly": "仅", "uninstallAll": "全部", diff --git a/i18n/chs/src/vs/platform/list/browser/listService.i18n.json b/i18n/chs/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..6abcaadf646 --- /dev/null +++ b/i18n/chs/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "工作台", + "multiSelectModifier.ctrlCmd": "映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)", + "multiSelectModifier.alt": "映射为 \"Alt\" (Windows 和 Linux) 或 \"Option\" (macOS)", + "multiSelectModifier": "在通过鼠标添加条目到多选项中时使用的修改键 (例如在支持此项操作的树或列表中)。\"ctrlCmd\" 会映射为 \"Ctrl\" (Windows 和 Linux) 或 \"Command\" (macOS)。“打开到侧边”功能所需的鼠标动作 (若可用) 将会相应调整,不与多选修改键冲突。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/message/common/message.i18n.json b/i18n/chs/src/vs/platform/message/common/message.i18n.json index 864f82423ea..6ab699b790e 100644 --- a/i18n/chs/src/vs/platform/message/common/message.i18n.json +++ b/i18n/chs/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "关闭", "later": "稍后", - "cancel": "取消" + "cancel": "取消", + "moreFile": "...1 个其他文件未显示", + "moreFiles": "...{0} 个其他文件未显示" } \ No newline at end of file diff --git a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json index 7c3d96dd488..0e3e7d546d3 100644 --- a/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/chs/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "编辑器小部件的边框颜色。此颜色仅在小部件有边框且不被小部件重写时适用。", "editorSelectionBackground": "编辑器所选内容的颜色。", "editorSelectionForeground": "用以彰显高对比度的所选文本的颜色。", - "editorInactiveSelection": "非活动编辑器中所选内容的颜色。", - "editorSelectionHighlight": "与所选内容具有相同内容的区域颜色。", + "editorInactiveSelection": "非活动编辑器选择内容的颜色。颜色必须透明,这样不会挡住其下的其他元素。", + "editorSelectionHighlight": "与已选项内容相同区域的颜色。颜色必须透明,这样不会挡住其下的其他元素。", "editorFindMatch": "当前搜索匹配项的颜色。", - "findMatchHighlight": "其他搜索匹配项的颜色。", - "findRangeHighlight": "限制搜索的范围的颜色。", - "hoverHighlight": "悬停提示显示时文本底下的高亮颜色。", + "findMatchHighlight": "其他搜索匹配项的颜色。颜色必须透明,这样不会挡住其下的其他元素。", + "findRangeHighlight": "搜索限制范围的颜色。颜色必须透明,这样不会挡住其下的其他元素。", + "hoverHighlight": "悬停提示显示时文本的高亮颜色。颜色必须透明,这样不会挡住其下的其他元素。", "hoverBackground": "编辑器悬停提示的背景颜色。", "hoverBorder": "光标悬停时编辑器的边框颜色。", "activeLinkForeground": "活动链接颜色。", @@ -76,12 +76,12 @@ "diffEditorRemoved": "被删除文本的背景颜色。", "diffEditorInsertedOutline": "插入的文本的轮廓颜色。", "diffEditorRemovedOutline": "被删除文本的轮廓颜色。", - "mergeCurrentHeaderBackground": "内联合并冲突中当前版本区域的标头背景色。", - "mergeCurrentContentBackground": "内联合并冲突中当前版本区域的内容背景色。", - "mergeIncomingHeaderBackground": "内联合并冲突中传入的版本区域的标头背景色。", - "mergeIncomingContentBackground": "内联合并冲突中传入的版本区域的内容背景色。", - "mergeCommonHeaderBackground": "内联合并冲突中共同祖先区域的标头背景色。", - "mergeCommonContentBackground": "内联合并冲突中共同祖先区域的内容背景色。", + "mergeCurrentHeaderBackground": "内联合并冲突中当前版本区域头部的背景色。颜色必须透明,这样不会挡住其下的其他元素。", + "mergeCurrentContentBackground": "内联合并冲突中当前版本区域内容的背景色。颜色必须透明,这样不会挡住其下的其他元素。", + "mergeIncomingHeaderBackground": "内联合并冲突中传入版本区域头部的背景色。颜色必须透明,这样不会挡住其下的其他元素。", + "mergeIncomingContentBackground": "内联合并冲突中传入版本区域内容的背景色。颜色必须透明,这样不会挡住其下的其他元素。", + "mergeCommonHeaderBackground": "内联合并冲突中共同上级区域头部的背景色。颜色必须透明,这样不会挡住其下的其他元素。", + "mergeCommonContentBackground": "内联合并冲突中共同上级区域内容的背景色。颜色必须透明,这样不会挡住其下的其他元素。", "mergeBorder": "内联合并冲突中标头和分割线的边框颜色。", "overviewRulerCurrentContentForeground": "内联合并冲突中当前版本区域的概览标尺前景色。", "overviewRulerIncomingContentForeground": "内联合并冲突中传入的版本区域的概览标尺前景色。", diff --git a/i18n/chs/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/chs/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..103d823dcdd --- /dev/null +++ b/i18n/chs/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirearray": "localizations 必须为数组", + "requirestring": "属性“{0}”是必要属性,其类型必须是 \"string\"", + "optstring": "属性“{0}”可以省略,否则其类型必须是 \"string\"", + "vscode.extension.contributes.localizations": "向编辑器提供本地化内容", + "vscode.extension.contributes.localizations.languageId": "显示字符串翻译的目标语言 ID。", + "vscode.extension.contributes.localizations.languageName": "显示字符串翻译的目标语言名称。", + "vscode.extension.contributes.localizations.translations": "文件夹的相对路径,其中包含了提供语言的所有翻译文件。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..519a8e806a7 --- /dev/null +++ b/i18n/chs/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "正在运行保存参与程序..." +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/chs/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 7bfb0b886de..26bd748a8a9 100644 --- a/i18n/chs/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/chs/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "没有注册 ID 为“{0}”的树形图。", - "treeItem.notFound": "没有在树中找到 ID 为“{0}”的项目。", - "treeView.duplicateElement": "已注册元素 {0}。" + "treeView.duplicateElement": "ID 为 {0} 的元素已被注册" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/chs/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 1893d29afa7..c8121010a5a 100644 --- a/i18n/chs/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "切换边栏位置", + "toggleSidebarPosition": "切换边栏位置", "view": "查看" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json index b282efac3d0..0ac87020d7b 100644 --- a/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "打开文件...", "openFolder": "打开文件夹...", "openFileFolder": "打开...", - "addFolderToWorkspace": "将文件夹添加到工作区...", - "add": "添加(&&A)", - "addFolderToWorkspaceTitle": "将文件夹添加到工作区", "globalRemoveFolderFromWorkspace": "将文件夹从工作区删除…", - "removeFolderFromWorkspace": "将文件夹从工作区删除", - "openFolderSettings": "打开文件夹设置", "saveWorkspaceAsAction": "将工作区另存为...", "save": "保存(&&S)", "saveWorkspace": "保存工作区", "openWorkspaceAction": "打开工作区...", "openWorkspaceConfigFile": "打开工作区配置文件", - "openFolderAsWorkspaceInNewWindow": "在新窗口中将文件夹作为工作区打开", - "workspaceFolderPickerPlaceholder": "选择工作区文件夹" + "openFolderAsWorkspaceInNewWindow": "在新窗口中将文件夹作为工作区打开" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/chs/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..ff43d2fcbf7 --- /dev/null +++ b/i18n/chs/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "将文件夹添加到工作区...", + "add": "添加(&&A)", + "addFolderToWorkspaceTitle": "将文件夹添加到工作区", + "workspaceFolderPickerPlaceholder": "选择工作区文件夹" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index a2f0727f579..139236ab4a9 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "在第三组中显示编辑器", "allEditorsPicker": "显示所有已打开的编辑器", "view": "查看", - "file": "文件" + "file": "文件", + "close": "关闭", + "closeOthers": "关闭其他", + "closeRight": "关闭右侧", + "closeAllUnmodified": "关闭未更改", + "closeAll": "全部关闭", + "keepOpen": "保持打开状态", + "toggleInlineView": "切换内联视图", + "showOpenedEditors": "显示打开的编辑器", + "keepEditor": "保留编辑器", + "closeEditorsInGroup": "关闭组中的所有编辑器", + "closeUnmodifiedEditors": "关闭组中未作更改的编辑器", + "closeOtherEditors": "关闭其他编辑器", + "closeRightEditors": "关闭右侧编辑器" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index dd3e01e846c..1d48cf8bccc 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "关闭编辑器", "revertAndCloseActiveEditor": "还原并关闭编辑器", "closeEditorsToTheLeft": "关闭左侧编辑器", - "closeEditorsToTheRight": "关闭右侧编辑器", "closeAllEditors": "关闭所有编辑器", - "closeUnmodifiedEditors": "关闭组中未作更改的编辑器", "closeEditorsInOtherGroups": "关闭其他组中的编辑器", - "closeOtherEditorsInGroup": "关闭其他编辑器", - "closeEditorsInGroup": "关闭组中的所有编辑器", "moveActiveGroupLeft": "向左移动编辑器组", "moveActiveGroupRight": "向右移动编辑器组", "minimizeOtherEditorGroups": "最小化其他编辑器组", "evenEditorGroups": "编辑器组平均宽度", "maximizeEditor": "最大化编辑器组并隐藏边栏", - "keepEditor": "保留编辑器", "openNextEditor": "打开下一个编辑器", "openPreviousEditor": "打开上一个编辑器", "nextEditorInGroup": "打开组中的下一个编辑器", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "在第一组中显示编辑器", "showEditorsInSecondGroup": "在第二组中显示编辑器", "showEditorsInThirdGroup": "在第三组中显示编辑器", - "showEditorsInGroup": "显示组中的编辑器", "showAllEditors": "显示所有编辑器", "openPreviousRecentlyUsedEditorInGroup": "打开组中上一个最近使用的编辑器", "openNextRecentlyUsedEditorInGroup": "打开组中下一个最近使用的编辑器", @@ -54,5 +48,8 @@ "moveEditorLeft": "向左移动编辑器", "moveEditorRight": "向右移动编辑器", "moveEditorToPreviousGroup": "将编辑器移动到上一组", - "moveEditorToNextGroup": "将编辑器移动到下一组" + "moveEditorToNextGroup": "将编辑器移动到下一组", + "moveEditorToFirstGroup": "将编辑器移动到第一组", + "moveEditorToSecondGroup": "将编辑器移动到第二组", + "moveEditorToThirdGroup": "将编辑器移动到第三组" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 9c9da616c68..94ef2c116b8 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "按标签或按组移动活动编辑器", "editorCommand.activeEditorMove.arg.name": "活动编辑器移动参数", - "editorCommand.activeEditorMove.arg.description": "参数属性:\n\t* \"to\": 提供向何处移动的字符串值。\n\t* \"by\": 提供移动的单位的字符串值。按选项卡或按组。\n\t* \"value\": 提供移动的位置数量或移动到的绝对位置的数字型值。", - "commandDeprecated": "已删除命令 **{0}**。你可以改用 **{1}**", - "openKeybindings": "配置键盘快捷方式" + "editorCommand.activeEditorMove.arg.description": "参数属性:\n\t* \"to\": 提供向何处移动的字符串值。\n\t* \"by\": 提供移动的单位的字符串值。按选项卡或按组。\n\t* \"value\": 提供移动的位置数量或移动到的绝对位置的数字型值。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 9d821488d27..d5044cab660 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "文本文件比较编辑器。", "navigate.next.label": "下一个更改", "navigate.prev.label": "上一个更改", - "inlineDiffLabel": "切换到内联视图", - "sideBySideDiffLabel": "切换到并行视图" + "toggleIgnoreTrimWhitespace.label": "忽略可裁剪的空白字符" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 90dedb611fa..d7a330cd5e2 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "关闭", - "closeOthers": "关闭其他", - "closeRight": "关闭到右侧", - "closeAll": "全部关闭", - "closeAllUnmodified": "关闭未更改", - "keepOpen": "保持打开状态", - "showOpenedEditors": "显示打开的编辑器", "araLabelEditorActions": "编辑器操作" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 452ee0335c5..1b911dc5296 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[不受支持]", + "userIsAdmin": "[管理员]", + "userIsSudo": "[超级用户]", "devExtensionWindowTitlePrefix": "[扩展开发主机]" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/chs/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index e9347e0a6fe..8da27417ba2 100644 --- a/i18n/chs/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/chs/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "从侧边栏中隐藏" + "hideView": "隐藏" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/common/theme.i18n.json b/i18n/chs/src/vs/workbench/common/theme.i18n.json index 8ebf8f723db..1b50f1b309f 100644 --- a/i18n/chs/src/vs/workbench/common/theme.i18n.json +++ b/i18n/chs/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "活动选项卡的背景色。在编辑器区域,选项卡是编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", "tabInactiveBackground": "非活动选项卡的背景色。在编辑器区域,选项卡是编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", + "tabHoverBackground": "选项卡被悬停时的背景色。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", + "tabUnfocusedHoverBackground": "非焦点组选项卡被悬停时的背景色。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", "tabBorder": "用于将选项卡彼此分隔开的边框。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以存在多个编辑器组。", "tabActiveBorder": "用于高亮活动的选项卡的边框。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以存在多个编辑器组。", "tabActiveUnfocusedBorder": "用于高亮一个失去焦点的编辑器组中的活动选项卡的边框。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以存在多个编辑器组。", + "tabHoverBorder": "选项卡被悬停时用于突出显示的边框。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", + "tabUnfocusedHoverBorder": "非焦点组选项卡被悬停时用于突出显示的边框。选项卡是编辑器区域中编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", "tabActiveForeground": "活动组中活动选项卡的前景色。在编辑器区域,选项卡是编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", "tabInactiveForeground": "活动组中非活动选项卡的前景色。在编辑器区域,选项卡是编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", "tabUnfocusedActiveForeground": "一个失去焦点的编辑器组中的活动选项卡的前景色。在编辑器区域,选项卡是编辑器的容器。可在一个编辑器组中打开多个选项卡。可以有多个编辑器组。", @@ -16,7 +20,7 @@ "editorGroupBackground": "编辑器组的背景颜色。编辑器组是编辑器的容器。此颜色在拖动编辑器组时显示。", "tabsContainerBackground": "启用选项卡时编辑器组标题的背景颜色。编辑器组是编辑器的容器。", "tabsContainerBorder": "选项卡启用时编辑器组标题的边框颜色。编辑器组是编辑器的容器。", - "editorGroupHeaderBackground": "禁用选项卡时编辑器组标题的背景颜色。编辑器组是编辑器的容器。", + "editorGroupHeaderBackground": "禁用选项卡 (\"workbench.editor.showTabs\": false) 时编辑器组标题颜色。编辑器组是编辑器的容器。", "editorGroupBorder": "将多个编辑器组彼此分隔开的颜色。编辑器组是编辑器的容器。", "editorDragAndDropBackground": "拖动编辑器时的背景颜色。此颜色应有透明度,以便编辑器内容能透过背景。", "panelBackground": "面板的背景色。面板显示在编辑器区域下方,可包含输出和集成终端等视图。", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "当没有打开文件夹时,用来使状态栏与侧边栏、编辑器分隔的状态栏边框颜色。状态栏显示在窗口底部。", "statusBarItemActiveBackground": "单击时的状态栏项背景色。状态栏显示在窗口底部。", "statusBarItemHoverBackground": "悬停时的状态栏项背景色。状态栏显示在窗口底部。", - "statusBarProminentItemBackground": "状态栏突出显示项的背景颜色。突出显示项比状态栏中的其他条目更显眼,表明其重要性更高。状态栏显示在窗口底部。", - "statusBarProminentItemHoverBackground": "状态栏突出显示项在悬停时的背景颜色。突出显示项比状态栏中的其他条目更显眼,表明其重要性更高。状态栏显示在窗口底部。", + "statusBarProminentItemBackground": "状态栏突出显示项的背景颜色。突出显示项比状态栏中的其他条目更醒目以表明其重要性。在命令面板中更改“切换 Tab 键是否移动焦点”可查看示例。状态栏显示在窗口底部。", + "statusBarProminentItemHoverBackground": "状态栏突出显示项在被悬停时的背景颜色。突出显示项比状态栏中的其他条目更醒目以表明其重要性。在命令面板中更改“切换 Tab 键是否移动焦点”可查看示例。状态栏显示在窗口底部。", "activityBarBackground": "活动栏背景色。活动栏显示在最左侧或最右侧,并允许在侧边栏的视图间切换。", "activityBarForeground": "活动栏前景色(例如用于图标)。活动栏显示在最左侧或最右侧,并允许在侧边栏的视图间切换。", "activityBarBorder": "活动栏分隔侧边栏的边框颜色。活动栏显示在最左侧或最右侧,并可以切换侧边栏的视图。", diff --git a/i18n/chs/src/vs/workbench/common/views.i18n.json b/i18n/chs/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..85f57daaba0 --- /dev/null +++ b/i18n/chs/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "ID 为“{0}”的视图在位置“{1}”已被注册" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json index 24ec2fcb7bd..102013aa46a 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "关闭编辑器", "closeWindow": "关闭窗口", "closeWorkspace": "关闭工作区", "noWorkspaceOpened": "此实例当前没有打开工作区,无法关闭。", @@ -30,6 +29,7 @@ "openRecent": "打开最近的文件…", "quickOpenRecent": "快速打开最近的文件…", "closeMessages": "关闭通知消息", + "openIssueReporter": "打开问题报告程序", "reportIssueInEnglish": "使用英文报告问题", "reportPerformanceIssue": "报告性能问题", "keybindingsReference": "键盘快捷方式参考", @@ -52,21 +52,5 @@ "displayLanguage": "定义 VSCode 的显示语言。", "doc": "请参阅 {0},了解支持的语言列表。", "restart": "更改此值需要重启 VSCode。", - "fail.createSettings": "无法创建“{0}”({1})。", - "openLogsFolder": "打开日志文件夹", - "showLogs": "显示日志...", - "mainProcess": "主进程", - "sharedProcess": "共享进程", - "rendererProcess": "渲染器进程", - "extensionHost": "扩展主机", - "selectProcess": "选择进程", - "setLogLevel": "设置日志级别", - "trace": "跟踪", - "debug": "调试", - "info": "信息", - "warn": "警告", - "err": "错误", - "critical": "关键", - "off": "关闭", - "selectLogLevel": "选择日志级别" + "fail.createSettings": "无法创建“{0}”({1})。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json index e93318a00b8..62b6aada113 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "查看", "help": "帮助", "file": "文件", - "developer": "开发者", "workspaces": "工作区", + "developer": "开发者", + "workbenchConfigurationTitle": "工作台", "showEditorTabs": "控制打开的编辑器是否显示在选项卡中。", "workbench.editor.labelFormat.default": "显示文件名。当启用选项卡且在同一组内有两个相同名称的文件时,将添加每个文件路径中可以用于区分的部分。在选项卡被禁用且编辑器活动时,将显示相对于工作区文件夹的路径。", "workbench.editor.labelFormat.short": "在文件的目录名之后显示文件名。", @@ -20,23 +21,23 @@ "showIcons": "控制打开的编辑器是否随图标一起显示。这还需启用图标主题。", "enablePreview": "控制是否将打开的编辑器显示为预览。预览编辑器将会重用至其被保留(例如,通过双击或编辑),且其字体样式将为斜体。", "enablePreviewFromQuickOpen": "控制 Quick Open 中打开的编辑器是否显示为预览。预览编辑器可以重新使用,直到将其保留(例如,通过双击或编辑)。", + "closeOnFileDelete": "控制文件被其他某些进程删除或重命名时是否应该自动关闭显示文件的编辑器。禁用此项会保持编辑器作为此类事件的脏文件打开。请注意,从应用程序内部进行删除操作会始终关闭编辑器,并且脏文件始终不会关闭以保存数据。", "editorOpenPositioning": "控制打开编辑器的位置。选择“左侧”或“右侧”以在当前活动位置的左侧或右侧打开编辑器。选择“第一个”或“最后一个”以从当前活动位置独立打开编辑器。", "revealIfOpen": "控制打开时编辑器是否显示在任何可见组中。如果禁用,编辑器会优先在当前活动编辑器组中打开。如果启用,会显示已打开的编辑器而不是在当前活动编辑器组中再次打开。请注意,有些情况下会忽略此设置,例如强制编辑器在特定组中或在当前活动组的边侧打开时。", + "swipeToNavigate": "使用三指横扫在打开的文件之间导航", "commandHistory": "控制命令面板中保留最近使用命令的数量。设置为 0 时禁用命令历史功能。", "preserveInput": "控制是否在再次打开命令面板时恢复上一次的输入内容。", "closeOnFocusLost": "控制 Quick Open 是否应在失去焦点时自动关闭。", "openDefaultSettings": "控制打开设置时是否打开显示所有默认设置的编辑器。", "sideBarLocation": "控制边栏的位置。它可显示在工作台的左侧或右侧。", + "panelDefaultLocation": "控制此面板的默认位置。可显示在工作台的底部或右侧。", "statusBarVisibility": "控制工作台底部状态栏的可见性。", "activityBarVisibility": "控制工作台中活动栏的可见性。", - "closeOnFileDelete": "控制文件被其他某些进程删除或重命名时是否应该自动关闭显示文件的编辑器。禁用此项会保持编辑器作为此类事件的脏文件打开。请注意,从应用程序内部进行删除操作会始终关闭编辑器,并且脏文件始终不会关闭以保存数据。", - "enableNaturalLanguageSettingsSearch": "控制是否在设置中启用自然语言搜索模式。", "fontAliasing": "控制工作台中字体的渲染方式\n- default: 次像素平滑字体。将在大多数非 retina 显示器上显示最清晰的文字\n- antialiased: 进行像素而不是次像素级别的字体平滑。可能会导致字体整体显示得更细\n- none: 禁用字体平滑。将显示边缘粗糙、有锯齿的文字", "workbench.fontAliasing.default": "次像素平滑字体。将在大多数非 retina 显示器上显示最清晰的文字。", "workbench.fontAliasing.antialiased": "进行像素而不是次像素级别的字体平滑。可能会导致字体整体显示得更细。", "workbench.fontAliasing.none": "禁用字体平滑。将显示边缘粗糙、有锯齿的文字。", - "swipeToNavigate": "使用三指横扫在打开的文件之间导航", - "workbenchConfigurationTitle": "工作台", + "enableNaturalLanguageSettingsSearch": "控制是否在设置中启用自然语言搜索模式。", "windowConfigurationTitle": "窗口", "window.openFilesInNewWindow.on": "文件将在新窗口中打开", "window.openFilesInNewWindow.off": "文件将在该文件的文件夹打开的窗口中打开,或在上一个活动窗口中打开", diff --git a/i18n/chs/src/vs/workbench/electron-browser/window.i18n.json b/i18n/chs/src/vs/workbench/electron-browser/window.i18n.json index b2c1d0e6763..a2e4b30b59e 100644 --- a/i18n/chs/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/chs/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "剪切", "copy": "复制", "paste": "粘贴", - "selectAll": "全选" + "selectAll": "全选", + "runningAsRoot": "不建议以 root 用户身份运行 {0}。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index fd9702e842b..97d6fae2b3f 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "调试工具栏背景颜色。" + "debugToolBarBackground": "调试工具栏背景颜色。", + "debugToolBarBorder": "调试工具栏边框颜色。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index fd6211c4e06..83ae4f6295a 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,8 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "用于验证 \"launch.json\" 的 JSON 架构配置。", "vscode.extension.contributes.debuggers.windows": "Windows 特定的设置。", "vscode.extension.contributes.debuggers.windows.runtime": "用于 Windows 的运行时。", - "vscode.extension.contributes.debuggers.osx": "OS X 特定的设置。", - "vscode.extension.contributes.debuggers.osx.runtime": "用于 OSX 的运行时。", + "vscode.extension.contributes.debuggers.osx": "macOS 特定的设置。", + "vscode.extension.contributes.debuggers.osx.runtime": "用于 macOS 的运行时。", "vscode.extension.contributes.debuggers.linux": "Linux 特定的设置。", "vscode.extension.contributes.debuggers.linux.runtime": "用于 Linux 的运行时。", "vscode.extension.contributes.breakpoints": "添加断点。", diff --git a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 3fee2b4ab47..0fa0e030ff2 100644 --- a/i18n/chs/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "调试对象", - "debug.terminal.not.available.error": "集成终端不可用" + "debug.terminal.title": "调试对象" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index f54abac52da..2db5cdad108 100644 --- a/i18n/chs/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "打开新命令提示符", "globalConsoleActionMacLinux": "打开新终端", "scopedConsoleActionWin": "在命令提示符中打开", - "scopedConsoleActionMacLinux": "在终端中打开", - "openFolderInIntegratedTerminal": "在终端中打开" + "scopedConsoleActionMacLinux": "在终端中打开" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index efe5507494d..325749e3e0c 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "根据您最近打开的文件推荐此扩展。", + "neverShowAgain": "不再显示", + "close": "关闭", "workspaceRecommendation": "当前工作区的用户推荐此扩展。", + "fileBasedRecommendation": "根据您最近打开的文件推荐此扩展。", "exeBasedRecommendation": "根据你安装的 {0},向你推荐此扩展。", "reallyRecommended2": "建议对这种类型的文件使用“{0}”扩展。", "reallyRecommendedExtensionPack": "建议对这种类型的文件使用“{0}”扩展包。", "showRecommendations": "显示建议", "install": "安装", - "neverShowAgain": "不再显示", - "close": "关闭", + "showLanguageExtensions": "商店中有可以对 \".{0}\" 文件提供帮助的扩展。", + "searchMarketplace": "搜索应用商店", "workspaceRecommended": "此工作区具有扩展建议。", "installAll": "全部安装", "ignoreExtensionRecommendations": "你是否要忽略所有推荐的扩展?", diff --git a/i18n/chs/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/chs/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index 93fab46db22..d11701056cf 100644 --- a/i18n/chs/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "从 VSIX 安装扩展...", + "installingMarketPlaceExtension": "正在从应用商店安装扩展...", + "uninstallingExtension": "正在卸载扩展...", "enableDependeciesConfirmation": "启用“{0}”也会启用其依赖项。是否要继续?", "enable": "是", "doNotEnable": "否", diff --git a/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..475d836e696 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "工作台", + "feedbackVisibility": "控制是否显示工作台底部状态栏中的 Twitter 反馈 (笑脸图标)。" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index a2b15babb5f..84925c604c1 100644 --- a/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "请求缺失功能", "tell us why?": "告诉我们原因?", "commentsHeader": "注释", + "showFeedback": "在状态栏中显示反馈笑脸图标", "tweet": "Tweet", "character left": "剩余字符", "characters left": "剩余字符", diff --git a/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..c5b0fd0e5a5 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "隐藏" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 30c68b4c7ad..93681537820 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "文件", "revealInSideBar": "在侧边栏中显示", "acceptLocalChanges": "使用你的更改并覆盖磁盘上的内容。", - "revertLocalChanges": "放弃你的更改并还原为磁盘上的内容" + "revertLocalChanges": "放弃你的更改并还原为磁盘上的内容", + "copyPathOfActive": "复制活动文件的路径", + "saveAllInGroup": "保存组中的全部内容", + "saveFiles": "保存所有文件", + "revert": "还原文件", + "compareActiveWithSaved": "比较活动与已保存的文件", + "closeEditor": "关闭编辑器", + "view": "查看", + "openToSide": "打开到侧边", + "revealInWindows": "在资源管理器中显示", + "revealInMac": "在 Finder 中显示", + "openContainer": "打开所在的文件夹", + "copyPath": "复制路径", + "saveAll": "全部保存", + "compareWithSaved": "与已保存文件比较", + "compareWithSelected": "与已选项目进行比较", + "compareSource": "选择以进行比较", + "compareSelected": "将已选项进行比较", + "close": "关闭", + "closeOthers": "关闭其他", + "closeUnmodified": "关闭未更改", + "closeAll": "全部关闭", + "deleteFile": "永久删除" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index f9208415003..513e4e1f0d7 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "重试", - "rename": "重命名", "newFile": "新建文件", "newFolder": "新建文件夹", + "rename": "重命名", + "delete": "删除", + "copyFile": "复制", + "pasteFile": "粘贴", + "retry": "重试", "openFolderFirst": "先打开一个文件夹,以在其中创建文件或文件夹。", "newUntitledFile": "新的无标题文件", "createNewFile": "新建文件", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "移动到回收站(&&M)", "deleteButtonLabelTrash": "移动到回收站(&&M)", "deleteButtonLabel": "删除(&&D)", + "dirtyMessageFilesDelete": "你删除的文件中具有未保存的更改。是否继续?", "dirtyMessageFolderOneDelete": "你正在删除的文件夹有 1 个文件具有未保存的更改。是否继续?", "dirtyMessageFolderDelete": "你正在删除的文件夹有 {0} 个文件具有未保存的更改。是否继续?", "dirtyMessageFileDelete": "你正在删除的文件具有未保存的更改。是否继续?", "dirtyWarning": "如果不保存,更改将丢失。", + "confirmMoveTrashMessageMultiple": "是否确定要删除以下 {0} 个文件?", "confirmMoveTrashMessageFolder": "是否确实要删除“{0}”及其内容?", "confirmMoveTrashMessageFile": "是否确实要删除“{0}”?", "undoBin": "可以从回收站还原。", "undoTrash": "可以从回收站还原。", "doNotAskAgain": "不再询问", + "confirmDeleteMessageMultiple": "是否确定要永久删除以下 {0} 个文件?", "confirmDeleteMessageFolder": "是否确定要永久删除“{0}”及其内容?", "confirmDeleteMessageFile": "是否确定要永久删除“{0}”?", "irreversible": "此操作不可逆!", "permDelete": "永久删除", - "delete": "删除", "importFiles": "导入文件", "confirmOverwrite": "目标文件夹中已存在具有相同名称的文件或文件夹。是否要替换它?", "replaceButtonLabel": "替换(&&R)", - "copyFile": "复制", - "pasteFile": "粘贴", + "fileDeleted": "文件已被删除或移动", + "fileIsAncestor": "复制的项目是目标文件夹的上级", "duplicateFile": "重复", - "openToSide": "打开到侧边", - "compareSource": "选择以进行比较", "globalCompareFile": "比较活动文件与...", "openFileToCompare": "首先打开文件以将其与另外一个文件比较。", - "compareWith": "将“{0}”与“{1}”比较", - "compareFiles": "比较文件", "refresh": "刷新", - "save": "保存", - "saveAs": "另存为...", - "saveAll": "全部保存", "saveAllInGroup": "保存组中的全部内容", - "saveFiles": "保存所有文件", - "revert": "还原文件", "focusOpenEditors": "专注于“打开的编辑器”视图", "focusFilesExplorer": "关注文件资源浏览器", "showInExplorer": "在侧边栏中显示活动文件", @@ -56,20 +52,11 @@ "refreshExplorer": "刷新资源管理器", "openFileInNewWindow": "在新窗口中打开活动文件", "openFileToShowInNewWindow": "请先打开要在新窗口中打开的文件", - "revealInWindows": "在资源管理器中显示", - "revealInMac": "在 Finder 中显示", - "openContainer": "打开所在的文件夹", - "revealActiveFileInWindows": "Windows 资源管理器中显示活动文件", - "revealActiveFileInMac": "在 Finder 中显示活动文件", - "openActiveFileContainer": "打开活动文件所在的文件夹", "copyPath": "复制路径", - "copyPathOfActive": "复制活动文件的路径", "emptyFileNameError": "必须提供文件或文件夹名。", "fileNameExistsError": "此位置已存在文件或文件夹 **{0}**。请选择其他名称。", "invalidFileNameError": "名称 **{0}** 作为文件或文件夹名无效。请选择其他名称。", "filePathTooLongError": "名称 **{0}** 导致路径太长。请选择更短的名称。", - "compareWithSaved": "比较活动与已保存的文件", - "modifiedLabel": "{0} (磁盘上) ↔ {1}", "compareWithClipboard": "比较活动文件与剪贴板", "clipboardComparisonLabel": "剪贴板 ↔ {0}" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index 702c021c5f3..e9a10faa823 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "首先打开文件以复制其路径", - "openFileToReveal": "首先打开文件以展现" + "revealInWindows": "在资源管理器中显示", + "revealInMac": "在 Finder 中显示", + "openContainer": "打开所在的文件夹", + "saveAs": "另存为...", + "save": "保存", + "saveAll": "全部保存", + "removeFolderFromWorkspace": "将文件夹从工作区删除", + "genericRevertError": "未能还原“{0}”: {1}", + "modifiedLabel": "{0} (磁盘上) ↔ {1}", + "openFileToReveal": "首先打开文件以展现", + "openFileToCopy": "首先打开文件以复制其路径" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 63427668f5f..1d8701fe103 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "编辑器", "formatOnSave": "保存时设置文件的格式。格式化程序必须可用,不能自动保存文件,并且不能关闭编辑器。", "explorerConfigurationTitle": "文件资源管理器", - "openEditorsVisible": "在“打开的编辑器”窗格中显示的编辑器数量。将其设置为 0 可隐藏窗格。", - "dynamicHeight": "控制打开的编辑器部分的高度是否应动态适应元素数量。", + "openEditorsVisible": "在“打开的编辑器”窗格中显示的编辑器数量。", "autoReveal": "控制资源管理器是否应在打开文件时自动显示并选择它们。", "enableDragAndDrop": "控制资源管理器是否应该允许通过拖放移动文件和文件夹。", "confirmDragAndDrop": "控制在资源管理器内拖放移动文件或文件夹时是否进行确认。", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 8ebee88ce98..4911cddc49b 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "使用右侧编辑器工具栏的操作来**撤消**你的更改或用你的更改来**覆盖**磁盘上的内容", - "discard": "放弃", + "overwriteElevated": "以管理员身份覆盖...", + "saveElevated": "以管理员身份重试...", "overwrite": "覆盖", "retry": "重试", - "readonlySaveError": "无法保存“{0}”: 文件写保护。选择“覆盖”以删除保护。 ", + "discard": "放弃", + "readonlySaveErrorAdmin": "无法保存“{0}”: 文件写保护。选择“以管理员身份覆盖”可作为管理员重试。 ", + "readonlySaveError": "无法保存“{0}”: 文件写保护。选择“覆盖”可尝试移除保护。", + "permissionDeniedSaveError": "无法保存“{0}”: 权限不足。选择“以管理员身份覆盖”可作为管理员重试。", "genericSaveError": "未能保存“{0}”: {1}", "staleSaveError": "无法保存“{0}”: 磁盘上的内容较新。单击 **比较** 以比较你的版本和磁盘上的版本。", "compareChanges": "比较", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index d97098d02f7..0be09e75862 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,6 +10,7 @@ "dropFolder": "你是否要将文件夹添加到工作区?", "addFolders": "添加文件夹(&&A)", "addFolder": "添加文件夹(&&A)", + "confirmMultiMove": "是否确定要移动以下 {0} 个文件?", "confirmMove": "是否确实要移动“{0}”?", "doNotAskAgain": "不再询问", "moveButtonLabel": "移动(&&M)", diff --git a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 0c93f41d44d..f501bedc60f 100644 --- a/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "打开的编辑器", "openEditosrSection": "打开的编辑器部分", - "dirtyCounter": "{0} 个未保存", - "saveAll": "全部保存", - "closeAllUnmodified": "关闭未更改", - "closeAll": "全部关闭", - "compareWithSaved": "与已保存文件比较", - "close": "关闭", - "closeOthers": "关闭其他" + "dirtyCounter": "{0} 个未保存" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..605730c3691 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "日志(主进程)", + "sharedLog": "日志(共享进程)", + "rendererLog": "日志(窗口进程)", + "extensionsLog": "日志(扩展主机)", + "developer": "开发者" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..66dcbba199b --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "打开日志文件夹", + "showLogs": "显示日志...", + "mainProcess": "主进程", + "sharedProcess": "共享进程", + "rendererProcess": "窗口", + "extensionHost": "扩展主机", + "selectProcess": "选择进程", + "openLogFile": "打开日志文件...", + "setLogLevel": "设置日志级别", + "trace": "跟踪", + "debug": "调试", + "info": "信息", + "warn": "警告", + "err": "错误", + "critical": "严重", + "off": "关闭", + "selectLogLevel": "选择日志级别" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/chs/src/vs/workbench/parts/markers/common/messages.i18n.json index 3e34c78c26a..8f40a40df02 100644 --- a/i18n/chs/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "viewCategory": "查看", - "problems.view.toggle.label": "切换显示问题视图", - "problems.view.focus.label": "聚焦于问题视图", + "problems.view.toggle.label": "切换问题 (错误、警告、信息) 视图", + "problems.view.focus.label": "聚焦于问题 (错误、警告、信息) 视图", "problems.panel.configuration.title": "问题预览", "problems.panel.configuration.autoreveal": "控制问题预览是否应在打开文件时自动显示它们。", "markers.panel.title.problems": "问题", diff --git a/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..8942e4d51b6 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "输出", + "logViewer": "日志查看器", + "viewCategory": "查看", + "clearOutput.label": "清除输出" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/chs/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..9d92ce92cd2 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - 输出", + "channel": "“{0}”的输出通道" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 34f4d8ea701..2ddff381a9b 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -17,6 +17,7 @@ "resetLabel": "重置键绑定", "showConflictsLabel": "显示冲突", "copyLabel": "复制", + "copyCommandLabel": "拷贝命令", "error": "编辑键绑定时发生错误“{0}”。请打开 \"keybindings.json\" 文件并检查。", "command": "命令", "keybinding": "键绑定", diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index c40e2e7cf77..56b8e2afaaf 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 个设置匹配", "settingsFound": "{0} 个设置匹配", "totalSettingsMessage": "总计 {0} 个设置", + "nlpResult": "自然语言结果", + "filterResult": "筛选结果", "defaultSettings": "默认设置", "defaultFolderSettings": "默认文件夹设置", "defaultEditorReadonly": "在右侧编辑器中编辑以覆盖默认值。", diff --git a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 5c28c560886..10c2fc221a5 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "试试自然语言搜索!", "defaultSettings": "将您的设置放入右侧编辑器以覆盖。", "noSettingsFound": "未找到设置。", "settingsSwitcherBarAriaLabel": "设置转换器", "userSettings": "用户设置", "workspaceSettings": "工作区设置", - "folderSettings": "文件夹设置", - "enableFuzzySearch": "启用自然语言搜索" + "folderSettings": "文件夹设置" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/chs/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 26f355bb382..ef307afdfbd 100644 --- a/i18n/chs/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "常用设置", - "mostRelevant": "最相关", "defaultKeybindingsHeader": "通过将键绑定放入键绑定文件中来覆盖键绑定。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 4fff98737e8..0f609a35000 100644 --- a/i18n/chs/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "查看", "commandsHandlerDescriptionDefault": "显示并运行命令", "gotoLineDescriptionMac": "转到行", "gotoLineDescriptionWin": "转到行", diff --git a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index cc08da73602..ebf378aac85 100644 --- a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "显示 Git", "source control": "源代码管理", "toggleSCMViewlet": "显示源代码管理", - "view": "查看" + "view": "查看", + "scmConfigurationTitle": "源代码管理", + "alwaysShowProviders": "是否总是显示源代码管理提供程序部分。", + "diffDecorations": "控制编辑器中差异的显示效果。", + "inputCounter": "控制何时显示输入计数。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index eb08e1a3030..dc3530badc8 100644 --- a/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "源代码管理提供程序", "hideRepository": "隐藏", + "commitMessageInfo": "当前行有 {0} 个字符", + "commitMessageCountdown": "当前行剩余 {0} 个字符", + "commitMessageWarning": "当前行比 {1} 超出 {0} 个字符", "installAdditionalSCMProviders": "安装其他源代码管理提供程序...", "no open repo": "没有活动的源代码管理提供程序。", "source control": "源代码管理", diff --git a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json index ebf392aa07d..65d9e1b855d 100644 --- a/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "显示上一个搜索词", "showSearchViewlet": "显示搜索", "findInFiles": "在文件中查找", - "findInFilesWithSelectedText": "在文件中查找所选文本", "replaceInFiles": "在文件中替换", - "replaceInFilesWithSelectedText": "在文件中替换所选文本", "RefreshAction.label": "刷新", "CollapseDeepestExpandedLevelAction.label": "全部折叠", "ClearSearchResultsAction.label": "清除", diff --git a/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 971f3dddcce..e22eff45b62 100644 --- a/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "在文件夹中查找...", + "findInWorkspace": "在工作区中查找...", "showTriggerActions": "转到工作区中的符号...", "name": "搜索", "search": "搜索", + "showSearchViewlet": "显示搜索", "view": "查看", + "findInFiles": "在文件中查找", "openAnythingHandlerDescription": "转到文件", "openSymbolDescriptionNormal": "转到工作区中的符号", - "searchOutputChannelTitle": "搜索", "searchConfigurationTitle": "搜索", "exclude": "配置 glob 模式以在搜索中排除文件和文件夹。从 files.exclude 设置中继承所有 glob 模式。", "exclude.boolean": "匹配文件路径所依据的 glob 模式。设置为 true 或 false 可启用或禁用该模式。", @@ -18,5 +21,6 @@ "useRipgrep": "控制是否在文本和文件搜索中使用 ripgrep", "useIgnoreFiles": "控制搜索文件时是否使用 .gitignore 和 .ignore 文件。", "search.quickOpen.includeSymbols": "配置为在 Quick Open 文件结果中包括全局符号搜索的结果。", - "search.followSymlinks": "控制是否在搜索中跟踪符号链接。" + "search.followSymlinks": "控制是否在搜索中跟踪符号链接。", + "search.smartCase": "若搜索词全为小写,则不区分大小写进行搜索,否则区分大小写进行搜索" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..b6d24a6f921 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.scope": "(全局)", + "global.1": "({0})", + "new.global": "新建全局代码片段文件...", + "group.global": "现有代码片段", + "new.global.sep": "新代码片段", + "openSnippet.pickLanguage": "选择代码片段文件或创建代码片段", + "openSnippet.label": "配置用户代码片段", + "preferences": "首选项" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 6023eaf614f..84c29334b81 100644 --- a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "选择代码片段的语言", - "openSnippet.errorOnCreate": "无法创建 {0}", - "openSnippet.label": "打开用户代码段", - "preferences": "首选项", "snippetSchema.json.default": "空代码片段", "snippetSchema.json": "用户代码片段配置", "snippetSchema.json.prefix": "在 Intellisense 中选择代码片段时将使用的前缀", "snippetSchema.json.body": "代码片段的内容。使用“$1”和“${1:defaultText}”定义光标位置,使用“$0”定义最终光标位置。使用“${varName}”和“${varName:defaultText}”插入变量值,例如“这是文件:$TM_FILENAME”。", - "snippetSchema.json.description": "代码片段描述。" + "snippetSchema.json.description": "代码片段描述。", + "snippetSchema.json.scope": "此代码片段适用语言的名称列表,例如 \"typescript,javascript\"。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..bfcf4616bc8 --- /dev/null +++ b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "用户代码片段" +} \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index e4e7302f246..7c00034a89a 100644 --- a/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "“contributes.{0}.language”中存在未知的语言。提供的值: {1}", "invalid.path.0": "“contributes.{0}.path”中应为字符串。提供的值: {1}", + "invalid.language.0": "省略语言时,\"contributes.{0}.path\" 的值必须为一个 \".code-snippets\" 文件。提供的值: {1}", + "invalid.language": "“contributes.{0}.language”中存在未知的语言。提供的值: {1}", "invalid.path.1": "“contributes.{0}.path”({1})应包含在扩展的文件夹({2})内。这可能会使扩展不可移植。", "vscode.extension.contributes.snippets": "添加代码段。", "vscode.extension.contributes.snippets-language": "此代码片段参与的语言标识符。", "vscode.extension.contributes.snippets-path": "代码片段文件的路径。该路径相对于扩展文件夹,通常以 \"./snippets/\" 开头。", "badVariableUse": "扩展“{0}”中的一个或多个代码片段很可能混淆了片段变量和片段占位符 (有关详细信息,请访问 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax )", "badFile": "无法读取代码片段文件“{0}”。", - "source.snippet": "用户代码片段", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0},{1}" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 75d151b4bb5..40bc57dc321 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -13,7 +13,9 @@ "terminal.integrated.shellArgs.osx": "在 OS X 终端上时要使用的命令行参数。", "terminal.integrated.shell.windows": "终端在 Windows 使用的 shell 路径。使用随 Windows 一起提供的 shell (cmd、PowerShell 或 Bash on Ubuntu) 时。", "terminal.integrated.shellArgs.windows": "在 Windows 终端上时使用的命令行参数。", + "terminal.integrated.macOptionIsMeta": "在终端中,使用 Option 键作为 Meta 键。(macOS)", "terminal.integrated.rightClickCopyPaste": "设置后,在终端内右键单击时,这将阻止显示上下文菜单,相反,它将在有选项时进行复制,并且在没有选项时进行粘贴。", + "terminal.integrated.copyOnSelection": "设置后,终端中选中的文字将被复制到剪贴板。", "terminal.integrated.fontFamily": "控制终端的字体系列,这在编辑器中是默认的。fontFamily 的值。", "terminal.integrated.fontSize": "控制终端的字号(以像素为单位)。", "terminal.integrated.lineHeight": "控制终端的行高,此数字乘上终端字号得到实际行高(以像素为单位)。", @@ -24,10 +26,12 @@ "terminal.integrated.setLocaleVariables": "控制是否在终端启动时设置区域设置变量,在 OS X 上默认设置为 true,在其他平台上为 false。", "terminal.integrated.cwd": "将在其中启动终端的一个显式起始路径,它用作 shell 进程的当前工作目录(cwd)。当根目录为不方便的 cwd 时,此路径在工作区设置中可能十分有用。", "terminal.integrated.confirmOnExit": "在存在活动终端会话的情况下,退出时是否要确认。", + "terminal.integrated.enableBell": "是否启用终端响铃。", "terminal.integrated.commandsToSkipShell": "一组命令 ID,其键绑定不发送到 shell 而始终由 Code 处理。这使得通常由 shell 使用的键绑定的使用效果与未将终端设为焦点时相同,例如按 Ctrl+P 启动 Quick Open。", "terminal.integrated.env.osx": "要添加到 VS Code 进程中的带有环境变量的对象,其会被 OS X 终端使用。", "terminal.integrated.env.linux": "要添加到 VS Code 进程中的带有环境变量的对象,其会被 Linux 终端使用。", "terminal.integrated.env.windows": "要添加到 VS Code 进程中的带有环境变量的对象,其会被 Windows 终端使用。", + "terminal.integrated.showExitAlert": "当退出代码非零时,显示“终端进程以某退出代码终止”的警告。", "terminalCategory": "终端", "viewCategory": "查看" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index d96d23dca0e..916f76ed987 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -12,8 +12,11 @@ "workbench.action.terminal.selectAll": "全选", "workbench.action.terminal.deleteWordLeft": "删除左侧的字符", "workbench.action.terminal.deleteWordRight": "删除右侧的字符", + "workbench.action.terminal.enterLineNavigationMode": "进入屏幕阅读器导航模式", "workbench.action.terminal.new": "新建集成终端", "workbench.action.terminal.new.short": "新的终端", + "workbench.action.terminal.newWorkspacePlaceholder": "选择当前工作目录新建终端", + "workbench.action.terminal.newInActiveWorkspace": "新建集成终端 (活动工作区)", "workbench.action.terminal.focus": "聚焦于终端", "workbench.action.terminal.focusNext": "聚焦于下一终端", "workbench.action.terminal.focusPrevious": "聚焦于上一终端", diff --git a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 25d612371f7..feb3b9cc8cc 100644 --- a/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,7 @@ "terminal.integrated.chooseWindowsShellInfo": "可通过选择“自定义”按钮来更改默认的终端 shell。", "customize": "自定义", "cancel": "取消", - "never again": "我已了解,不再提示", + "never again": "确定,且不再显示", "terminal.integrated.chooseWindowsShell": "选择首选的终端 shell,你可稍后在设置中进行更改", "terminalService.terminalCloseConfirmationSingular": "存在一个活动的终端会话,是否要终止此会话?", "terminalService.terminalCloseConfirmationPlural": "存在 {0} 个活动的终端会话,是否要终止这些会话?" diff --git a/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json index d43fc9ca29b..9460987e42b 100644 --- a/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/chs/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "命令面板...", "settings": "设置", "keyboardShortcuts": "键盘快捷方式", + "userSnippets": "用户代码片段", "selectTheme.label": "颜色主题", "themes.selectIconTheme.label": "文件图标主题", "not available": "更新不可用", diff --git a/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 80b697be3d3..fdbcd8bad77 100644 --- a/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "文件是目录", + "fileNotModifiedError": "自以下时间未修改的文件:", "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json index b385a7a0f15..234d233e533 100644 --- a/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "文件太大,无法打开", "fileNotFoundError": "找不到文件({0})", "fileBinaryError": "文件似乎是二进制文件,无法作为文档打开", + "filePermission": "写入文件时权限被拒绝 ({0})", "fileExists": "已存在要创建的文件 ({0})", "fileMoveConflict": "无法移动/复制。文件已存在于目标位置。", "unableToMoveCopyError": "无法移动/复制。文件将替换其所在的文件夹。", diff --git a/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index af87ffb3672..6b16deb483d 100644 --- a/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "键处于活动状态时的条件。", "keybindings.json.args": "要传递给命令以执行的参数。", "keyboardConfigurationTitle": "键盘", - "dispatch": "控制按键的分派逻辑以使用 \"code\" (推荐) 或 \"keyCode\"。" + "dispatch": "控制按键的分派逻辑以使用 \"code\" (推荐) 或 \"keyCode\"。", + "touchbar.enabled": "启用键盘上的 macOS 触控栏按钮 (若可用)。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/chs/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 6bee4318397..ba2101635d0 100644 --- a/i18n/chs/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "是否要保存对 {0} 的更改?", "saveChangesMessages": "是否要保存对下列 {0} 个文件的更改?", - "moreFile": "...1 个其他文件未显示", - "moreFiles": "...{0} 个其他文件未显示", "saveAll": "全部保存(&&S)", "save": "保存(&&S)", "dontSave": "不保存(&&N)", diff --git a/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index af35cdf722b..fbf48931d61 100644 --- a/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "无文件图标", "iconThemeError": "文件图标主题未知或未安装。", "workbenchColors": "覆盖当前所选颜色主题的颜色。", - "editorColors": "覆盖当前所选颜色主题中的编辑器颜色和字体样式。", "editorColors.comments": "设置注释的颜色和样式", "editorColors.strings": "设置字符串文本的颜色和样式", "editorColors.keywords": "设置关键字的颜色和样式。", @@ -19,5 +18,6 @@ "editorColors.types": "设置类型定义与引用的颜色和样式。", "editorColors.functions": "设置函数定义与引用的颜色和样式。", "editorColors.variables": "设置变量定义和引用的颜色和样式。", - "editorColors.textMateRules": "使用 TextMate 主题规则设置颜色和样式(高级)。" + "editorColors.textMateRules": "使用 TextMate 主题规则设置颜色和样式(高级)。", + "editorColors": "覆盖当前所选颜色主题中的编辑器颜色和字体样式。" } \ No newline at end of file diff --git a/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 11ecec6e1ac..b9142ec415a 100644 --- a/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/chs/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "无法写入工作区配置文件。请打开文件以更正错误或警告,然后重试。", "errorWorkspaceConfigurationFileDirty": "文件已变更,因此无法写入工作区配置文件。请先保存此文件,然后重试。", "openWorkspaceConfigurationFile": "打开工作区配置文件", - "close": "关闭", - "enterWorkspace.close": "关闭", - "enterWorkspace.dontShowAgain": "不再显示", - "enterWorkspace.moreInfo": "详细信息", - "enterWorkspace.prompt": "了解有关在 VS Code 中使用多个文件夹的详细信息。" + "close": "关闭" } \ No newline at end of file diff --git a/i18n/cht/extensions/git/out/autofetch.i18n.json b/i18n/cht/extensions/git/out/autofetch.i18n.json index 78cd65caa1f..a9b802babec 100644 --- a/i18n/cht/extensions/git/out/autofetch.i18n.json +++ b/i18n/cht/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "是", + "read more": "閱讀其他資訊", "no": "否", - "not now": "不是現在", - "suggest auto fetch": "是否啟用 Git 儲存庫的自動擷取?" + "not now": "稍後詢問我", + "suggest auto fetch": "您想要 Code 定期的執行 `git fetch` 嗎?" } \ No newline at end of file diff --git a/i18n/cht/extensions/git/out/commands.i18n.json b/i18n/cht/extensions/git/out/commands.i18n.json index 1ace18f1610..3362f487b3c 100644 --- a/i18n/cht/extensions/git/out/commands.i18n.json +++ b/i18n/cht/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\n這項動作無法復原,您會永久失去目前的工作集。", "yes discard tracked": "捨棄 1 個追蹤的檔案", "yes discard tracked multiple": "捨棄 {0} 個追蹤的檔案", + "unsaved files single": "下列檔案尚未儲存: {0}。\n\n您要在認可之前進行儲存嗎?", + "unsaved files": "有 {0} 個未儲存檔案。\n\n您要在認可之前進行儲存嗎?", + "save and commit": "儲存全部且認可", + "commit": "無論如何仍認可", "no staged changes": "沒有暫存變更進行提交\n\n您希望自動暫存您所有變更並直接提交?", "always": "永遠", "no changes": "沒有任何變更要認可。", @@ -64,12 +68,13 @@ "no remotes to pull": "您的儲存庫未設定要提取的遠端來源。", "pick remote pull repo": "挑選要將分支提取出的遠端", "no remotes to push": "您的儲存庫未設定要推送的遠端目標。", - "push with tags success": "已成功使用標籤推送。", "nobranch": "請簽出分支以推送到遠端。", + "confirm publish branch": "分支 '{0}' 沒有任何上游分支。 您仍想發布這個分支嗎?", + "ok": "確定", + "push with tags success": "已成功使用標籤推送。", "pick remote": "挑選要發行分支 '{0}' 的目標遠端:", "sync is unpredictable": "此動作會將認可發送至 '{0}' 及從中提取認可。", - "ok": "確定", - "never again": "確定不要再顯示", + "never again": "確定,不要再顯示", "no remotes to publish": "您的儲存庫未設定要發行的遠端目標。", "no changes stash": "沒有變更可供隱藏。", "provide stash message": "可選擇提供隱藏訊息", diff --git a/i18n/cht/extensions/git/package.i18n.json b/i18n/cht/extensions/git/package.i18n.json index 5bb3d198bb4..5f9e86aed6c 100644 --- a/i18n/cht/extensions/git/package.i18n.json +++ b/i18n/cht/extensions/git/package.i18n.json @@ -54,12 +54,13 @@ "command.stashPopLatest": "快顯上一次的隱藏", "config.enabled": "是否啟用 GIT", "config.path": "Git 可執行檔的路徑", + "config.autoRepositoryDetection": "是否自動偵測儲存庫", "config.autorefresh": "是否啟用自動重新整理", "config.autofetch": "是否啟用自動擷取", "config.enableLongCommitWarning": "是否發出長認可訊息的警告", "config.confirmSync": "請先確認再同步處理 GIT 存放庫", "config.countBadge": "控制 git 徽章計數器。[全部] 會計算所有變更。[已追蹤] 只會計算追蹤的變更。[關閉] 會將其關閉。", - "config.checkoutType": "控制在執行 [簽出至...] 時,會列出那些類型的分支。[全部] 會顯示所有參考,[本機] 只會顯示本機分支,[標記] 只會顯示標記,[遠端] 只會顯示遠端分支。", + "config.checkoutType": "控制在執行 [簽出至...] 時,會列出哪些類型的分支。[全部] 會顯示所有參考,[本機] 只會顯示本機分支,[標籤] 只會顯示標籤,以及 [遠端] 只會顯示遠端分支。", "config.ignoreLegacyWarning": "略過舊的 Git 警告", "config.ignoreMissingGitWarning": "忽略遺漏 Git 時的警告", "config.ignoreLimitWarning": "當儲存庫中有過多變更時,略過警告。", @@ -72,5 +73,6 @@ "colors.deleted": "刪除資源的顏色", "colors.untracked": "未追蹤資源的顏色。", "colors.ignored": "忽略資源的顏色。", - "colors.conflict": "帶有衝突資源的顏色。" + "colors.conflict": "帶有衝突資源的顏色。", + "colors.submodule": "子模組資源的顏色" } \ No newline at end of file diff --git a/i18n/cht/extensions/typescript/out/commands.i18n.json b/i18n/cht/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..628429984fc --- /dev/null +++ b/i18n/cht/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "請在 VS Code 中開啟資料夾,以使用 TypeScript 或 JavaScript 專案", + "typescript.projectConfigUnsupportedFile": "無法判斷 TypeScript 或 JavaScript 專案。不支援的檔案類型", + "typescript.projectConfigCouldNotGetInfo": "無法判斷 TypeScript 或 JavaScript 專案", + "typescript.noTypeScriptProjectConfig": "檔案不是 TypeScript 專案的一部份", + "typescript.noJavaScriptProjectConfig": "檔案不是 JavaScript 專案的一部份", + "typescript.configureTsconfigQuickPick": "設定 tsconfig.json", + "typescript.configureJsconfigQuickPick": "設定 jsconfig.json", + "typescript.projectConfigLearnMore": "深入了解" +} \ No newline at end of file diff --git a/i18n/cht/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/cht/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..b2cbb689282 --- /dev/null +++ b/i18n/cht/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (檔案中修復全部)" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/cht/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/cht/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/base/node/ps.i18n.json b/i18n/cht/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..8a8bc9149d5 --- /dev/null +++ b/i18n/cht/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "收集 CPU 與記憶體資訊中,可能需要幾秒鐘的時間。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json index 71be40322db..48d79ffbdd2 100644 --- a/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/cht/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "行號以絕對值顯示。", "lineNumbers.relative": "行號以目前游標的相對值顯示。", "lineNumbers.interval": "每 10 行顯示行號。", - "lineNumbers": "控制行號顯示方式。允許設定值包含 'on'、'off' 及 'relative'。", + "lineNumbers": "控制行號的顯示方式。允許的設定值為 'on'、 'off'、'relative' 及 'interval'", "rulers": "在特定的等寬字元數之後轉譯垂直尺規。有多個尺規就使用多個值。若陣列為空,則不繪製任何尺規。", "wordSeparators": "執行文字相關導覽或作業時將作為文字分隔符號的字元", "tabSize": "與 Tab 相等的空格數量。當 `editor.detectIndentation` 已開啟時,會根據檔案內容覆寫此設定。", @@ -40,9 +40,9 @@ "wordWrapColumn": "當 `editor.wordWrap` 為 [wordWrapColumn] 或 [bounded] 時,控制編輯器中的資料行換行。", "wrappingIndent": "控制換行的縮排。可以是 [無]、[相同] 或 [縮排]。", "mouseWheelScrollSensitivity": "滑鼠滾輪捲動事件的 'deltaX' 與 'deltaY' 所使用的乘數", - "multiCursorModifier.ctrlCmd": "對應Windows和Linux的'Control'與對應OSX的'Command'", - "multiCursorModifier.alt": "對應Windows和Linux的'Alt'與對應OSX的'Option'", - "multiCursorModifier": "用於新增多個滑鼠游標的修改程式。`ctrlCmd` 會對應到 Windows 及 Linux 上的 `Control` 以及 OSX 上的 `Command`。[移至定義] 及 [開啟連結] 滑鼠手勢將會適應以避免和 multicursor 修改程式衝突。", + "multiCursorModifier.ctrlCmd": "對應 Windows 和 Linux 的 `Control` 與對應 macOS 的 `Command`", + "multiCursorModifier.alt": "對應 Windows 和 Linux 的 `Alt` 與對應 macOS 的 `Option`", + "multiCursorModifier": "用於新增多個滑鼠游標的修改。 `ctrlCmd` 會對應到 Windows 和 Linux 上的 `Control` 以及 macOS 上的 `Command`。 [移至定義] 及 [開啟連結] 滑鼠手勢將會適應以避免和 multicursor 修改衝突。", "quickSuggestions.strings": "允許在字串內顯示即時建議。", "quickSuggestions.comments": "允許在註解中顯示即時建議。", "quickSuggestions.other": "允許在字串與註解以外之處顯示即時建議。", @@ -72,6 +72,7 @@ "cursorBlinking": "控制游標動畫樣式,可能的值為 'blink'、'smooth'、'phase'、'expand' 和 'solid'", "mouseWheelZoom": "使用滑鼠滾輪並按住 Ctrl 時,縮放編輯器的字型", "cursorStyle": "控制游標樣式。接受的值為 'block'、'block-outline'、'line'、'line-thin'、'underline' 及 'underline-thin'", + "lineCursorWidth": "控制游標寬度,當 editor.cursorStyle 設定為 'line' 時。", "fontLigatures": "啟用連字字型", "hideCursorInOverviewRuler": "控制游標是否應隱藏在概觀尺規中。", "renderWhitespace": "控制編輯器轉譯空白字元的方式,可能為 'none'、'boundary' 及 'all'。'boundary' 選項不會轉譯字組間的單一空格。", diff --git a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json index 85ff9ee951e..ab8fae3d2ec 100644 --- a/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/cht/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "目前游標位置行的反白顯示背景色彩。", "lineHighlightBorderBox": "目前游標位置行之周圍框線的背景色彩。", - "rangeHighlight": "反白顯示範圍的背景色彩,例如快速開啟與尋找功能。", + "rangeHighlight": "突顯顯示範圍的背景顏色,例如快速開啟和尋找功能。不能使用非透明的顏色來隱藏底層的樣式。", "caret": "編輯器游標的色彩。", "editorCursorBackground": "編輯器游標的背景色彩。允許自訂區塊游標重疊的字元色彩。", "editorWhitespaces": "編輯器中空白字元的色彩。", diff --git a/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 9fbf329131b..fcb4645d048 100644 --- a/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "移至下一個錯誤或警告", - "markerAction.previous.label": "移至上一個錯誤或警告", + "markerAction.next.label": "移至下一個問題 (錯誤, 警告, 資訊)", + "markerAction.previous.label": "移至上一個問題 (錯誤, 警告, 資訊)", "editorMarkerNavigationError": "編輯器標記導覽小工具錯誤的色彩。", "editorMarkerNavigationWarning": "編輯器標記導覽小工具警告的色彩。", "editorMarkerNavigationInfo": "編輯器標記導覽小工具資訊的色彩", diff --git a/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 97c113d82f0..600c7e5e3d5 100644 --- a/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/cht/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "讀取存取期間 (例如讀取變數時) 符號的背景色彩。", - "wordHighlightStrong": "寫入存取期間 (例如寫入變數時) 符號的背景色彩。", + "wordHighlight": "讀取存取符號時的背景顏色,如讀取變數。不能使用非透明的顏色來隱藏底層的樣式。", + "wordHighlightStrong": "寫入存取符號時的背景顏色,如寫入變數。不能使用非透明的顏色來隱藏底層的樣式。", "overviewRulerWordHighlightForeground": "符號醒目提示的概觀尺規標記色彩。", "overviewRulerWordHighlightStrongForeground": "寫入權限符號醒目提示的概觀尺規標記色彩。", "wordHighlight.next.label": "移至下一個反白符號", diff --git a/i18n/cht/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/cht/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 3484e0af5e7..f1ab5b8686a 100644 --- a/i18n/cht/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/cht/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}` 不是有效的功能表識別碼", "missing.command": "功能表項目參考了 'commands' 區段中未定義的命令 `{0}`。", "missing.altCommand": "功能表項目參考了 'commands' 區段中未定義的替代命令 `{0}`。", - "dupe.command": "功能表項目參考了與預設相同的命令和替代命令", - "nosupport.altCommand": "很抱歉,目前只有 [編輯器/標題] 功能表的 [導覽] 群組支援替代命令" + "dupe.command": "功能表項目參考了與預設相同的命令和替代命令" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/environment/node/argv.i18n.json b/i18n/cht/src/vs/platform/environment/node/argv.i18n.json index 0874564b4c9..0026dc0d184 100644 --- a/i18n/cht/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/cht/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,36 @@ "diff": "互相比較兩個檔案。", "add": "將資料夾新增至上一個使用中的視窗。", "goto": "在路徑上的指定行與字元位置開啟檔案。", - "locale": "要使用的地區設定 (例如 en-US 或 zh-TW)。", "newWindow": "強制執行 Code 的新執行個體。", - "performance": "在已啟用 'Developer: Startup Performance' 命令的情況下開始。", - "prof-startup": "啟動時執行 CPU 分析工具", - "inspect-extensions": "允許對擴充功能進行除錯和分析。檢查開發工具的連接 uri。", - "inspect-brk-extensions": "允許對擴展主機在啟動後暫停擴充功能進行除錯和分析。檢查開發工具中的連接 uri。", "reuseWindow": "強制在最近使用的視窗中開啟檔案或資料夾。", - "userDataDir": "指定保留使用者資料的目錄,這在以根目錄身分執行時有用。", - "log": "使用的日誌級別。預設為\"訊息\"。允許的值是 \"關鍵\"、\"錯誤\"、\"警告\"、\"訊息\"、\"偵錯\"、\"追蹤\"、\"關閉\"。", - "verbose": "列印詳細資訊輸出 (表示 --wait)。", "wait": "等候檔案在傳回前關閉。", + "locale": "要使用的地區設定 (例如 en-US 或 zh-TW)。", + "userDataDir": "指定保留使用者資料的目錄,這在以根目錄身分執行時有用。", + "version": "列印版本。", + "help": "列印使用方式。", "extensionHomePath": "設定擴充功能的根路徑。", "listExtensions": "列出已安裝的擴充功能。", "showVersions": "使用 --list-extension 時,顯示安裝的擴充功能版本。", "installExtension": "安裝擴充功能。", "uninstallExtension": "解除安裝擴充功能。", "experimentalApis": "為延伸模組啟用建議的 API 功能。", - "disableExtensions": "停用所有已安裝的擴充功能。", - "disableGPU": "停用 GPU 硬體加速。", + "verbose": "列印詳細資訊輸出 (表示 --wait)。", + "log": "使用的日誌級別。預設為\"訊息\"。允許的值是 \"關鍵\"、\"錯誤\"、\"警告\"、\"訊息\"、\"偵錯\"、\"追蹤\"、\"關閉\"。", "status": "列印進程使用方式和診斷資訊。", - "version": "列印版本。", - "help": "列印使用方式。", + "performance": "在已啟用 'Developer: Startup Performance' 命令的情況下開始。", + "prof-startup": "啟動時執行 CPU 分析工具", + "disableExtensions": "停用所有已安裝的擴充功能。", + "inspect-extensions": "允許對擴充功能進行除錯和分析。檢查開發工具的連接 uri。", + "inspect-brk-extensions": "允許對擴展主機在啟動後暫停擴充功能進行除錯和分析。檢查開發工具中的連接 uri。", + "disableGPU": "停用 GPU 硬體加速。", + "uploadLogs": "上傳目前的工作階段紀錄至安全的端點。", + "issue": "回報1個問題", "usage": "使用方式", "options": "選項", "paths": "路徑", - "optionsUpperCase": "選項" + "stdinWindows": "從其他程式讀取輸出並附加 '-' (例: 'echo Hello World | {0} -')", + "stdinUnix": "從 stdin 讀取並附加 '-' (例: 'ps aux | grep code | {0} -')", + "optionsUpperCase": "選項", + "extensionsManagement": "擴充功能管理", + "troubleshooting": "疑難排解" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index bdd6cf53312..09a519ce52e 100644 --- a/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/cht/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "擴充功能無效: package.json 不是 JSON 檔案。", - "restartCodeLocal": "請先重新啟動 Code,再重新安裝 {0}。", + "restartCode": "請先重新啟動 Code,再重新安裝 {0}。", "installingOutdatedExtension": "已安裝此擴充功能的較新版本。是否要使用舊版本覆蓋此項?", "override": "覆寫", "cancel": "取消", - "notFoundCompatible": "無法安裝,因為找不到相容於 VS Code 目前版本 '{1}' 的擴充功能 '{0}'。", - "quitCode": "無法安裝因為有過時的擴充功能仍在運行。請在重新安裝前退出並啟動 VS Code。", - "exitCode": "無法安裝因為有過時的擴充功能仍在運行。請在重新安裝前退出並啟動 VS Code。", + "errorInstallingDependencies": "安裝相依套件時發生錯誤。{0}", + "notFoundCompatible": "無法安裝 '{0}';沒有任何與 VS Code 相容的可用版本 '{1}'。", "notFoundCompatibleDependency": "無法安裝,因為找不到相容於 VS Code 目前版本 '{1}' 的相依擴充功能 '{0}'。", + "quitCode": "無法安裝擴充功能。重新安裝以前請重啟 VS Code。", + "exitCode": "無法安裝擴充功能。重新安裝以前請離開並再次啟動 VS Code。", "uninstallDependeciesConfirmation": "只要將 '{0}' 解除安裝,或要包含其相依性?", "uninstallOnly": "只有", "uninstallAll": "全部", diff --git a/i18n/cht/src/vs/platform/list/browser/listService.i18n.json b/i18n/cht/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..14d649f76d2 --- /dev/null +++ b/i18n/cht/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "工作台", + "multiSelectModifier.ctrlCmd": "對應Windows和Linux的'Control'與對應 macOS 的'Command'。", + "multiSelectModifier.alt": "對應Windows和Linux的'Alt'與對應macOS的'Option'。", + "multiSelectModifier": "用於新增項目至滑鼠多選的修改 (例如在樹狀及列表支援下)。 `ctrlCmd` 會對應到 Windows 和 Linux 上的 `Control` 以及 macOS 上的 `Command`。 [在側邊開啟] 滑鼠手勢若支援,將會適應以避免和 multiselect 修改衝突。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/message/common/message.i18n.json b/i18n/cht/src/vs/platform/message/common/message.i18n.json index 7a9cbb1bf06..f23fb38d418 100644 --- a/i18n/cht/src/vs/platform/message/common/message.i18n.json +++ b/i18n/cht/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "關閉", "later": "稍後", - "cancel": "取消" + "cancel": "取消", + "moreFile": "...另外 1 個檔案未顯示", + "moreFiles": "...另外 {0} 個檔案未顯示" } \ No newline at end of file diff --git a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json index 4868c4bbc6c..b78729f262f 100644 --- a/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/cht/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "編輯器小工具的邊界色彩。小工具選擇擁有邊界或色彩未被小工具覆寫時,才會使用色彩。", "editorSelectionBackground": "編輯器選取範圍的色彩。", "editorSelectionForeground": "為選取的文字顏色高對比化", - "editorInactiveSelection": "非使用中之編輯器選取範圍的色彩。", - "editorSelectionHighlight": "選取時,內容相同之區域的色彩。", + "editorInactiveSelection": "在非使用中的編輯器的選取項目顏色。不能使用非透明的顏色來隱藏底層的樣式。", + "editorSelectionHighlight": "與選取項目相同的區域顏色。不能使用非透明的顏色來隱藏底層的樣式。", "editorFindMatch": "符合目前搜尋的色彩。", - "findMatchHighlight": "符合其他搜尋的色彩。", - "findRangeHighlight": "限制搜尋之範圍的色彩。", - "hoverHighlight": "在顯示了動態顯示的單字下方醒目提示。", + "findMatchHighlight": "符合搜尋條件的其他項目的顏色。不能使用非透明的顏色來隱藏底層的樣式。", + "findRangeHighlight": "為限制搜索的範圍著色。不能使用非透明的顏色來隱藏底層的樣式。", + "hoverHighlight": "突顯懸停顯示的文字。不能使用非透明的顏色來隱藏底層的樣式。", "hoverBackground": "編輯器動態顯示的背景色彩。", "hoverBorder": "編輯器動態顯示的框線色彩。", "activeLinkForeground": "使用中之連結的色彩。", @@ -76,12 +76,12 @@ "diffEditorRemoved": "移除文字的背景色彩。", "diffEditorInsertedOutline": "插入的文字外框色彩。", "diffEditorRemovedOutline": "移除的文字外框色彩。", - "mergeCurrentHeaderBackground": "目前內嵌合併衝突中的深色標題背景。", - "mergeCurrentContentBackground": "目前內嵌合併衝突中的內容背景。", - "mergeIncomingHeaderBackground": "傳入內嵌合併衝突中的深色標題背景。", - "mergeIncomingContentBackground": "傳入內嵌合併衝突中的內容背景。", - "mergeCommonHeaderBackground": "內嵌合併衝突中的共同始祖標題背景", - "mergeCommonContentBackground": "內嵌合併衝突中的共同始祖內容背景。", + "mergeCurrentHeaderBackground": "目前內嵌合併衝突中的深色標題背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeCurrentContentBackground": "目前內嵌合併衝突中的內容背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeIncomingHeaderBackground": "傳入內嵌合併衝突中的深色標題背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeIncomingContentBackground": "傳入內嵌合併衝突中的內容背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeCommonHeaderBackground": "內嵌合併衝突中的共同始祖標題背景。不能使用非透明的顏色來隱藏底層的樣式。", + "mergeCommonContentBackground": "內嵌合併衝突中的共同始祖內容背景。不能使用非透明的顏色來隱藏底層的樣式。", "mergeBorder": "內嵌合併衝突中標頭及分隔器的邊界色彩。", "overviewRulerCurrentContentForeground": "目前內嵌合併衝突的概觀尺規前景。", "overviewRulerIncomingContentForeground": "傳入內嵌合併衝突的概觀尺規前景。", diff --git a/i18n/cht/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/cht/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..1127905705c --- /dev/null +++ b/i18n/cht/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirearray": "在地化資料必須為陣列", + "requirestring": "屬性 '{0}' 為強制項目且必須屬於 `string` 類型", + "optstring": "屬性 `{0}` 可以省略或必須屬於 `string` 類型", + "vscode.extension.contributes.localizations": "提供在地化服務給編輯者", + "vscode.extension.contributes.localizations.languageId": "顯示已翻譯字串的語言 Id", + "vscode.extension.contributes.localizations.languageName": "顯示已翻譯字串的語言名稱", + "vscode.extension.contributes.localizations.translations": "檔案的相對路徑,其中該資料包含夾貢獻語言所有翻譯檔案。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..c98475d49db --- /dev/null +++ b/i18n/cht/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "執行儲存參與者..." +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/cht/src/vs/workbench/api/node/extHostTreeViews.i18n.json index edc32bace6e..1e554271b86 100644 --- a/i18n/cht/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/cht/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "未註冊識別碼為 '{0}' 的樹狀檢視。", - "treeItem.notFound": "找不到識別碼為 '{0}' 的樹狀檢視。", - "treeView.duplicateElement": "元件{0}已被註冊" + "treeView.duplicateElement": "識別碼為 {0} 的元件已被註冊" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/cht/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 08df7a29ce5..ce860535636 100644 --- a/i18n/cht/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "切換提要欄位位置", + "toggleSidebarPosition": "切換提要欄位位置", "view": "檢視" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json index abe1e77c797..f5c23870560 100644 --- a/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "開啟檔案...", "openFolder": "開啟資料夾...", "openFileFolder": "開啟...", - "addFolderToWorkspace": "將資料夾新增到工作區...", - "add": "新增", - "addFolderToWorkspaceTitle": "將資料夾新增到工作區", "globalRemoveFolderFromWorkspace": "將資料夾從工作區移除...", - "removeFolderFromWorkspace": "將資料夾從工作區移除", - "openFolderSettings": "開啟資料夾設定", "saveWorkspaceAsAction": "另存工作區為...", "save": "儲存(&&S)", "saveWorkspace": "儲存工作區", "openWorkspaceAction": "開啟工作區...", "openWorkspaceConfigFile": "開啟工作區組態檔", - "openFolderAsWorkspaceInNewWindow": "在新視窗中開啟資料夾作為工作區", - "workspaceFolderPickerPlaceholder": "選取工作區資料夾" + "openFolderAsWorkspaceInNewWindow": "在新視窗中開啟資料夾作為工作區" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/cht/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..19777945aa7 --- /dev/null +++ b/i18n/cht/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "將資料夾新增到工作區...", + "add": "新增", + "addFolderToWorkspaceTitle": "將資料夾新增到工作區", + "workspaceFolderPickerPlaceholder": "選取工作區資料夾" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index fc25ce13ad0..3e12d7d30b8 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "在第三個群組顯示編輯器", "allEditorsPicker": "顯示所有開啟的編輯器", "view": "檢視", - "file": "檔案" + "file": "檔案", + "close": "關閉", + "closeOthers": "關閉其他", + "closeRight": "關到右側", + "closeAllUnmodified": "關閉未變更的檔案", + "closeAll": "全部關閉", + "keepOpen": "保持開啟", + "toggleInlineView": "切換至內嵌檢視", + "showOpenedEditors": "顯示開啟的編輯器", + "keepEditor": "保留編輯器", + "closeEditorsInGroup": "關閉群組中的所有編輯器", + "closeUnmodifiedEditors": "在群組中關閉未修改的編輯器", + "closeOtherEditors": "關閉其他編輯器", + "closeRightEditors": "將編輯器關到右側" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 6f4e3589f00..6b3df89947b 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "關閉編輯器", "revertAndCloseActiveEditor": "還原並關閉編輯器", "closeEditorsToTheLeft": "將編輯器關到左側", - "closeEditorsToTheRight": "將編輯器關到右側", "closeAllEditors": "關閉所有編輯器", - "closeUnmodifiedEditors": "在群組中關閉未修改的編輯器", "closeEditorsInOtherGroups": "關閉其他群組中的編輯器", - "closeOtherEditorsInGroup": "關閉其他編輯器", - "closeEditorsInGroup": "關閉群組中的所有編輯器", "moveActiveGroupLeft": "將編輯器群組向左移", "moveActiveGroupRight": "將編輯器群組向右移", "minimizeOtherEditorGroups": "將其他編輯器群組最小化", "evenEditorGroups": "均分編輯器群組寬度", "maximizeEditor": "將編輯器群組最大化並隱藏側邊欄", - "keepEditor": "保留編輯器", "openNextEditor": "開啟下一個編輯器", "openPreviousEditor": "開啟上一個編輯器", "nextEditorInGroup": "開啟群組中下一個編輯器", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "在第一個群組顯示編輯器", "showEditorsInSecondGroup": "在第二個群組顯示編輯器", "showEditorsInThirdGroup": "在第三個群組顯示編輯器", - "showEditorsInGroup": "在群組顯示編輯器", "showAllEditors": "顯示所有編輯器", "openPreviousRecentlyUsedEditorInGroup": "開啟群組中上一個最近使用的編輯器", "openNextRecentlyUsedEditorInGroup": "開啟群組中下一個最近使用的編輯器", @@ -54,5 +48,8 @@ "moveEditorLeft": "將編輯器左移", "moveEditorRight": "將編輯器右移", "moveEditorToPreviousGroup": "將編輯器移入上一個群組", - "moveEditorToNextGroup": "將編輯器移入下一個群組" + "moveEditorToNextGroup": "將編輯器移入下一個群組", + "moveEditorToFirstGroup": "將編輯器移動到第一個群組", + "moveEditorToSecondGroup": "將編輯器移動到第二個群組", + "moveEditorToThirdGroup": "將編輯器移動到第三個群組" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index f93bcde4036..043d904547f 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "以 tab 或群組為單位移動使用中的編輯器", "editorCommand.activeEditorMove.arg.name": "使用中編輯器的移動引數", - "editorCommand.activeEditorMove.arg.description": "引數屬性:\n\t* 'to': 提供移動目標位置的字串值。\n\t* 'by': 提供移動單位的字串值。\n\t* 'value': 提供移動單位的字串值。可依索引標籤或群組作為單位。", - "commandDeprecated": "已移除命令 **{0}**。您可以改用 **{1}**", - "openKeybindings": "設定鍵盤快速鍵" + "editorCommand.activeEditorMove.arg.description": "引數屬性:\n\t* 'to': 提供移動目標位置的字串值。\n\t* 'by': 提供移動單位的字串值。\n\t* 'value': 提供移動單位的字串值。可依索引標籤或群組作為單位。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 7071905be9d..b24baa1a2f4 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "文字檔比較編輯器。", "navigate.next.label": "下一個變更", "navigate.prev.label": "上一個變更", - "inlineDiffLabel": "切換至內嵌檢視", - "sideBySideDiffLabel": "切換至並排檢視" + "toggleIgnoreTrimWhitespace.label": "忽略修剪空白字元" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index bfffed93b02..b9bd84d7409 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "關閉", - "closeOthers": "關閉其他", - "closeRight": "關到右側", - "closeAll": "全部關閉", - "closeAllUnmodified": "關閉未變更的檔案", - "keepOpen": "保持開啟", - "showOpenedEditors": "顯示開啟的編輯器", "araLabelEditorActions": "編輯器動作" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 03d11a86fb4..5b3642aebed 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[不支援]", + "userIsAdmin": "[系統管理員]", + "userIsSudo": "[超級使用者]", "devExtensionWindowTitlePrefix": "[Extension Development Host]" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/cht/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index e0fd97c7bae..529cc5594d3 100644 --- a/i18n/cht/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/cht/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "從提要欄位隱藏" + "hideView": "隱藏" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/common/theme.i18n.json b/i18n/cht/src/vs/workbench/common/theme.i18n.json index 6be57ab281c..701339a9f63 100644 --- a/i18n/cht/src/vs/workbench/common/theme.i18n.json +++ b/i18n/cht/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "使用中之索引標籤的背景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", "tabInactiveBackground": "非使用中之索引標籤的背景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", + "tabHoverBackground": "當暫留索引標籤的背景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", + "tabUnfocusedHoverBackground": "當暫留非焦點群組中索引標籤的背景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。 ", "tabBorder": "用以分隔索引標籤彼此的框線。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", "tabActiveBorder": "用以醒目提示使用中索引標籤的框線。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", "tabActiveUnfocusedBorder": "用以在非焦點群組中醒目提示使用中索引標籤的框線。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。 ", + "tabHoverBorder": "用以反白顯示暫留時索引標籤的框線。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", + "tabUnfocusedHoverBorder": "在非焦點群組中反白顯示暫留時索引標籤的框線。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。 ", "tabActiveForeground": "使用中的群組內,使用中之索引標籤的前景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", "tabInactiveForeground": "使用中的群組內,非使用中之索引標籤的前景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", "tabUnfocusedActiveForeground": "非焦點群組中的使用中索引標籤前景色彩。索引標籤是編輯器在編輯器區域中的容器。同一個編輯器群組中的多個索引標籤可以同時開啟。可能會有多個編輯器群組。", @@ -16,7 +20,7 @@ "editorGroupBackground": "編輯器群組的背景色彩。編輯器群組是編輯器的容器。當拖曳編輯器群組時會顯示背景色彩。", "tabsContainerBackground": "當索引標籤啟用的時候編輯器群組標題的背景色彩。編輯器群組是編輯器的容器。", "tabsContainerBorder": "當索引標籤啟用時,編輯器群組標題的框線色彩。編輯器群組是編輯器的容器。", - "editorGroupHeaderBackground": "當索引標籤禁用的時候編輯器群組標題的背景顏色。編輯器群組是編輯器的容器。", + "editorGroupHeaderBackground": "當索引標籤禁用的時候編輯器群組標題的背景顏色 (`\"workbench.editor.showTabs\": false`)。編輯器群組是編輯器的容器。", "editorGroupBorder": "用以分隔多個編輯器群組彼此的色彩。編輯器群組是編輯器的容器。", "editorDragAndDropBackground": "拖拉編輯器時的背景顏色,可設置透明度讓內容穿透顯示.", "panelBackground": "面板的前景色彩。面板會顯示在編輯器區域的下方,其中包含諸如輸出與整合式終端機等檢視。", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "未開啟資料夾時,用以分隔資訊看板與編輯器的狀態列框線色彩。狀態列會顯示在視窗的底部。 ", "statusBarItemActiveBackground": "按下滑鼠按鈕時,狀態列項目的背景色彩。狀態列會顯示在視窗的底部。", "statusBarItemHoverBackground": "動態顯示時,狀態列項目的背景色彩。狀態列會顯示在視窗的底部。", - "statusBarProminentItemBackground": "狀態列突出項目的背景顏色。突出項目比狀態列的其他項目更顯眼,用於表示重要性更高。狀態列會顯示在視窗的底部。", - "statusBarProminentItemHoverBackground": "狀態列突出項目暫留時的背景顏色。突出項目比狀態列的其他項目更顯眼,用於表示重要性更高。狀態列會顯示在視窗的底部。", + "statusBarProminentItemBackground": "狀態列突出項目的背景顏色。突出項目比狀態列的其他項目更顯眼,用於表示重要性更高。從命令選擇區變更模式 `切換 Tab 鍵移動焦點` 來檢視範例。狀態列會顯示在視窗的底部。", + "statusBarProminentItemHoverBackground": "當暫留狀態列突出項目的背景顏色。突出項目比狀態列的其他項目更顯眼,用於表示重要性更高。從命令選擇區變更模式 `切換 Tab 鍵移動焦點` 來檢視範例。狀態列會顯示在視窗的底部。", "activityBarBackground": "活動列背景的色彩。活動列會顯示在最左側或最右側,並可切換不同的提要欄位檢視。", "activityBarForeground": "活動列的前背景色彩(例如用於圖示)。此活動列會顯示在最左側或最右側,讓您可以切換提要欄位的不同檢視。", "activityBarBorder": "用以分隔提要欄位的活動列框線色彩。此活動列會顯示在最左側或最右側,讓您可以切換提要欄位的不同檢視。", diff --git a/i18n/cht/src/vs/workbench/common/views.i18n.json b/i18n/cht/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..b6fbcb12ae3 --- /dev/null +++ b/i18n/cht/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "識別碼為 '{0}' 的檢視已在位置 '{1}' 註冊" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json index daf7e22d21e..8b7032221cc 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "關閉編輯器", "closeWindow": "關閉視窗", "closeWorkspace": "關閉工作區", "noWorkspaceOpened": "此執行個體中目前沒有開啟的工作區可以關閉。", @@ -30,6 +29,7 @@ "openRecent": "開啟最近使用的檔案...", "quickOpenRecent": "快速開啟最近使用的檔案...", "closeMessages": "關閉通知訊息", + "openIssueReporter": "公開問題回報者", "reportIssueInEnglish": "回報問題", "reportPerformanceIssue": "回報效能問題", "keybindingsReference": "鍵盤快速鍵參考", @@ -52,21 +52,5 @@ "displayLanguage": "定義 VSCode 的顯示語言。", "doc": "如需支援的語言清單,請參閱 {0}。", "restart": "改變設定值後需要重新啟動 VSCode.", - "fail.createSettings": "無法建立 '{0}' ({1})。", - "openLogsFolder": "開啟紀錄資料夾", - "showLogs": "顯示紀錄...。", - "mainProcess": "主要", - "sharedProcess": "共用", - "rendererProcess": "轉譯器", - "extensionHost": "延伸主機", - "selectProcess": "選取程序", - "setLogLevel": "設定記錄層級", - "trace": "追蹤", - "debug": "偵錯", - "info": "資訊", - "warn": "警告", - "err": "錯誤", - "critical": "關鍵", - "off": "關閉", - "selectLogLevel": "選擇日誌級別" + "fail.createSettings": "無法建立 '{0}' ({1})。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json index 33e2c22230a..7ed98a41d84 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "檢視", "help": "說明", "file": "檔案", - "developer": "開發人員", "workspaces": "工作區", + "developer": "開發人員", + "workbenchConfigurationTitle": "工作台", "showEditorTabs": "控制已開啟的編輯器是否應顯示在索引標籤中。", "workbench.editor.labelFormat.default": "顯示檔案名稱。當啟用索引標籤,且同一個群組中有兩個檔案同名時,就會新增各個檔案路徑具有識別度的的區段。當停用索引標籤時,若編輯器在使用中,就會顯示與工作區資料夾相關的路徑。", "workbench.editor.labelFormat.short": "顯示檔案的名稱,並在名稱後接著該檔案的目錄名稱。", @@ -20,23 +21,23 @@ "showIcons": "控制開啟的編輯器是否搭配圖示顯示。這需要同時啟用圖示佈景主題。", "enablePreview": "控制已開啟的編輯器是否顯示為預覽。預覽編輯器會重複使用到被保留 (例如按兩下或進行編輯) 並以斜體字型樣式顯示為止。", "enablePreviewFromQuickOpen": "控制透過 Quick Open 所開啟的編輯器是否顯示為預覽。預覽編輯器會重複使用到被保留 (例如按兩下或進行編輯) 為止。", + "closeOnFileDelete": "控制顯示檔案的編輯器是否應在其他處理序刪除或重新命名該檔案時自動關閉。若停用此選項,當發生前述狀況時,編輯器會保持開啟,並呈現已變更的狀態。請注意,從應用程式內刪除一律會關閉編輯器,但已變更的檔案在資料未儲存前一律不會關閉。", "editorOpenPositioning": "控制編輯器的開啟位置。選取 [左] 或 [右] 可在目前使用中的編輯器左方或右方加以開啟。選取 [第一個] 或 [最後一個] 則可從目前使用中的編輯器另外加以開啟。", "revealIfOpen": "控制編輯器是否要在任何顯示的群組開啟時,在其中顯示。若啟用此選項,已經開啟的編輯器將會繼續顯示,而不會在目前使用中的編輯器群組中再開啟一次。請注意,有一些情況會忽略此設定,例如當強制編輯器在特定群組中開啟,或強制編輯器在目前使用中的群組旁開啟等情況。", + "swipeToNavigate": "利用三指水平撥動在開啟的檔案間瀏覽。", "commandHistory": "控制最近使用之命令的數量,以保留命令選擇區的記錄。設為 0 可停用命令列記錄。", "preserveInput": "控制下次開啟命令選擇區時,最後鍵入的輸入是否應該還原。", "closeOnFocusLost": "控制是否在 Quick Open 失去焦點時自動關閉。", "openDefaultSettings": "控制開啟設定時是否也會開啟顯示所有預設設定的編輯器。", "sideBarLocation": "控制項資訊看板的位置。可顯示於 Workbench 的左方或右方。", + "panelDefaultLocation": "控制面板的預設位置。可顯示在 Workbench 的底部或是右方。", "statusBarVisibility": "控制 Workbench 底端狀態列的可視性。", "activityBarVisibility": "控制活動列在 workbench 中的可見度。", - "closeOnFileDelete": "控制顯示檔案的編輯器是否應在其他處理序刪除或重新命名該檔案時自動關閉。若停用此選項,當發生前述狀況時,編輯器會保持開啟,並呈現已變更的狀態。請注意,從應用程式內刪除一律會關閉編輯器,但已變更的檔案在資料未儲存前一律不會關閉。", - "enableNaturalLanguageSettingsSearch": "控制是否啟用自然語言搜尋模式。", "fontAliasing": "在 Workbench 中控制字型鋸齒化的方法。- 預設: 子像素字型平滑處理。在大部分非 Retina 顯示器上會顯示出最銳利的文字- 已消除鋸齒: 相對於子像素,根據像素層級平滑字型。可讓字型整體顯得較細- 無: 停用字型平滑處理。文字會以鋸齒狀的銳邊顯示 ", "workbench.fontAliasing.default": "子像素字型平滑處理。在大部分非 Retina 顯示器上會顯示出最銳利的文字。", "workbench.fontAliasing.antialiased": "相對於子像素,根據像素層級平滑字型。可以讓字型整體顯得較細。", "workbench.fontAliasing.none": "禁用字體平滑.文字將會顯示鋸齒狀與鋒利的邊緣.", - "swipeToNavigate": "利用三指水平撥動在開啟的檔案間瀏覽。", - "workbenchConfigurationTitle": "工作台", + "enableNaturalLanguageSettingsSearch": "控制是否啟用自然語言搜尋模式。", "windowConfigurationTitle": "視窗", "window.openFilesInNewWindow.on": "檔案會在新視窗中開啟", "window.openFilesInNewWindow.off": "檔案會在開啟了檔案資料夾的視窗,或在上一個使用中的視窗中開啟", diff --git a/i18n/cht/src/vs/workbench/electron-browser/window.i18n.json b/i18n/cht/src/vs/workbench/electron-browser/window.i18n.json index 84c2c075664..8db2840ff19 100644 --- a/i18n/cht/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/cht/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "剪下", "copy": "複製", "paste": "貼上", - "selectAll": "全選" + "selectAll": "全選", + "runningAsRoot": "不建議以 root 身分執行 {0}。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index 8bd875c749d..33b7f3d4467 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "偵錯工具列背景色彩。" + "debugToolBarBackground": "偵錯工具列背景色彩。", + "debugToolBarBorder": "偵錯工具列的邊框色彩" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 19f502a82ef..7bccdf99f80 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,8 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "JSON 結構描述組態,用於驗證 'launch.json'。", "vscode.extension.contributes.debuggers.windows": "Windows 特定設定。", "vscode.extension.contributes.debuggers.windows.runtime": "用於 Windows 的執行階段。", - "vscode.extension.contributes.debuggers.osx": "OS X 特定設定。", - "vscode.extension.contributes.debuggers.osx.runtime": "用於 OSX 的執行階段。", + "vscode.extension.contributes.debuggers.osx": "macOS 特定設定。", + "vscode.extension.contributes.debuggers.osx.runtime": "用於 macOS 的執行階段。", "vscode.extension.contributes.debuggers.linux": "Linux 特定設定。", "vscode.extension.contributes.debuggers.linux.runtime": "用於 Linux 的執行階段。", "vscode.extension.contributes.breakpoints": "提供中斷點。", diff --git a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index c16e8f409d6..c127cd12e93 100644 --- a/i18n/cht/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "偵錯項目", - "debug.terminal.not.available.error": "整合式終端機無法使用" + "debug.terminal.title": "偵錯項目" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index cebab2d329a..370fe5dd948 100644 --- a/i18n/cht/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "開啟新的命令提示字元", "globalConsoleActionMacLinux": "開啟新的終端機", "scopedConsoleActionWin": "在命令提示字元中開啟", - "scopedConsoleActionMacLinux": "在終端機中開啟", - "openFolderInIntegratedTerminal": "在終端機中開啟" + "scopedConsoleActionMacLinux": "在終端機中開啟" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 89b01309fa3..f7439bf6054 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "根據您最近開啟的檔案,建議您使用此延伸模組。", + "neverShowAgain": "不要再顯示", + "close": "關閉", "workspaceRecommendation": "根據目前工作區的使用者,建議您使用此延伸模組。", + "fileBasedRecommendation": "根據您最近開啟的檔案,建議您使用此延伸模組。", "exeBasedRecommendation": "因為您已安裝 {0},所以建議您使用此延伸模組。", "reallyRecommended2": "建議對此檔案類型使用 '{0}' 延伸模組。", "reallyRecommendedExtensionPack": "建議對此檔案類型使用 '{0}' 延伸模組套件。", "showRecommendations": "顯示建議", "install": "安裝", - "neverShowAgain": "不要再顯示", - "close": "關閉", + "showLanguageExtensions": "市集有 '.{0}' 個文件的擴充功能可以提供協助", + "searchMarketplace": "搜尋市集", "workspaceRecommended": "此工作區具有擴充功能建議。", "installAll": "全部安裝", "ignoreExtensionRecommendations": "是否略過所有的延伸模組建議?", diff --git a/i18n/cht/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/cht/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index 44a55467fbf..adf7f4b2563 100644 --- a/i18n/cht/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "從 VSIX 安裝擴充功能...", + "installingMarketPlaceExtension": "從市集安裝擴充功能...", + "uninstallingExtension": "解除安裝擴充功能...", "enableDependeciesConfirmation": "啟用 '{0}' 也會啟用其相依性。仍要繼續嗎?", "enable": "是", "doNotEnable": "否", diff --git a/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..6a2ef8c5498 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "工作台", + "feedbackVisibility": "控制工作台底部狀態列中的 Twitter 回饋 (笑臉) 的可見度。" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index 3ae75fe7ef4..50c2a802497 100644 --- a/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "要求遺漏的功能", "tell us why?": "請告訴我們原因", "commentsHeader": "註解", + "showFeedback": "顯示狀態列中的回饋笑臉", "tweet": "推文", "character left": "剩餘字元", "characters left": "剩餘字元", diff --git a/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..e8a6eb4e02c --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "隱藏" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 8edf8023225..fe4146d1ad2 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "檔案", "revealInSideBar": "在提要欄位中顯示", "acceptLocalChanges": "使用您的變更並覆寫磁碟內容 ", - "revertLocalChanges": "捨棄您的變更並還原成磁碟上的內容" + "revertLocalChanges": "捨棄您的變更並還原成磁碟上的內容", + "copyPathOfActive": "複製使用中檔案的路徑", + "saveAllInGroup": "全部儲存在群組中", + "saveFiles": "儲存所有檔案", + "revert": "還原檔案", + "compareActiveWithSaved": "比較使用中的檔案和已儲存的檔案", + "closeEditor": "關閉編輯器", + "view": "檢視", + "openToSide": "開至側邊", + "revealInWindows": "在檔案總管中顯示", + "revealInMac": "在 Finder 中顯示", + "openContainer": "開啟收納資料夾", + "copyPath": "複製路徑", + "saveAll": "全部儲存", + "compareWithSaved": "與已儲存的檔案比較", + "compareWithSelected": "與選取的比較", + "compareSource": "選取用以比較", + "compareSelected": "比較已選取", + "close": "關閉", + "closeOthers": "關閉其他", + "closeUnmodified": "關閉未變更的檔案", + "closeAll": "全部關閉", + "deleteFile": "永久刪除" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index c32641ccebc..3cf9c4c6208 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "重試", - "rename": "重新命名", "newFile": "新增檔案", "newFolder": "新增資料夾", + "rename": "重新命名", + "delete": "刪除", + "copyFile": "複製", + "pasteFile": "貼上", + "retry": "重試", "openFolderFirst": "先開啟資料夾,以在其中建立檔案或資料夾。", "newUntitledFile": "新增未命名檔案", "createNewFile": "新增檔案", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "移至資源回收筒(&&M)", "deleteButtonLabelTrash": "移至垃圾筒(&&M)", "deleteButtonLabel": "刪除(&&D)", + "dirtyMessageFilesDelete": "您要刪除的檔案有未儲存的變更。要繼續嗎?", "dirtyMessageFolderOneDelete": "您要刪除的資料夾中 1 個檔案有未儲存的變更。要繼續嗎?", "dirtyMessageFolderDelete": "您要刪除的資料夾中 {0} 個檔案有未儲存的變更。要繼續嗎?", "dirtyMessageFileDelete": "您要刪除的檔案有未儲存的變更。要繼續嗎?", "dirtyWarning": "如果您不儲存變更,這些變更將會遺失。", + "confirmMoveTrashMessageMultiple": "確定要刪除以下 {0} 個檔案嗎?", "confirmMoveTrashMessageFolder": "您確定要刪除 '{0}' 及其內容嗎?", "confirmMoveTrashMessageFile": "您確定要刪除 '{0}' 嗎?", "undoBin": "您可以從資源回收筒還原。", "undoTrash": "您可以從垃圾筒還原。", "doNotAskAgain": "不要再詢問我", + "confirmDeleteMessageMultiple": "確定要永久地刪除以下 {0} 個檔案嗎?", "confirmDeleteMessageFolder": "您確定要永久刪除 '{0}' 和其中的內容嗎?", "confirmDeleteMessageFile": "您確定要永久刪除 '{0}' 嗎?", "irreversible": "此動作無法回復!", "permDelete": "永久刪除", - "delete": "刪除", "importFiles": "匯入檔案", "confirmOverwrite": "目的資料夾中已有同名的檔案或資料夾。要取代它嗎?", "replaceButtonLabel": "取代(&&R)", - "copyFile": "複製", - "pasteFile": "貼上", + "fileDeleted": "檔案被刪除或移動的同時", + "fileIsAncestor": "要複製的檔案是在目地資料夾的上層 ", "duplicateFile": "複製", - "openToSide": "開至側邊", - "compareSource": "選取用以比較", "globalCompareFile": "使用中檔案的比較對象...", "openFileToCompare": "先開啟檔案以與其他檔案進行比較", - "compareWith": "比較 '{0}' 與 '{1}'", - "compareFiles": "比較檔案", "refresh": "重新整理", - "save": "儲存", - "saveAs": "另存新檔...", - "saveAll": "全部儲存", "saveAllInGroup": "全部儲存在群組中", - "saveFiles": "儲存所有檔案", - "revert": "還原檔案", "focusOpenEditors": "聚焦在 [開放式編輯器] 檢視", "focusFilesExplorer": "將焦點設在檔案總管上", "showInExplorer": "在提要欄位中顯示使用中的檔案", @@ -56,20 +52,11 @@ "refreshExplorer": "重新整理 Explorer", "openFileInNewWindow": "在新視窗中開啟使用中的檔案", "openFileToShowInNewWindow": "先開啟檔案以在新視窗中開啟", - "revealInWindows": "在檔案總管中顯示", - "revealInMac": "在 Finder 中顯示", - "openContainer": "開啟收納資料夾", - "revealActiveFileInWindows": "在 Windows 檔案總管中顯示使用中的檔案", - "revealActiveFileInMac": "在 Finder 中顯示使用中的檔案", - "openActiveFileContainer": "開啟使用中檔案的收納資料夾", "copyPath": "複製路徑", - "copyPathOfActive": "複製使用中檔案的路徑", "emptyFileNameError": "必須提供檔案或資料夾名稱。", "fileNameExistsError": "這個位置已存在檔案或資料夾 **{0}**。請選擇不同的名稱。", "invalidFileNameError": "名稱 **{0}** 不能作為檔案或資料夾名稱。請選擇不同的名稱。", "filePathTooLongError": "名稱 **{0}** 導致路徑太長。請選擇較短的名稱。", - "compareWithSaved": "比較使用中的檔案和已儲存的檔案", - "modifiedLabel": "{0} (在磁碟上) ↔ {1}", "compareWithClipboard": "比較使用中的檔案和剪貼簿的檔案", "clipboardComparisonLabel": "剪貼簿 ↔ {0}" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index 75bdd951541..fabee1658dc 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "先開啟檔案以複製其路徑", - "openFileToReveal": "先開啟檔案以顯示" + "revealInWindows": "在檔案總管中顯示", + "revealInMac": "在 Finder 中顯示", + "openContainer": "開啟收納資料夾", + "saveAs": "另存新檔...", + "save": "儲存", + "saveAll": "全部儲存", + "removeFolderFromWorkspace": "將資料夾從工作區移除", + "genericRevertError": "無法還原 '{0}': {1}", + "modifiedLabel": "{0} (在磁碟上) ↔ {1}", + "openFileToReveal": "先開啟檔案以顯示", + "openFileToCopy": "先開啟檔案以複製其路徑" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 867d603ca56..1d9b4ba3736 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "編輯器", "formatOnSave": "在儲存時設定檔案格式。格式器必須處於可用狀態、檔案不得自動儲存,且編輯器不得關機。", "explorerConfigurationTitle": "檔案總管", - "openEditorsVisible": "[開放式編輯器] 窗格中顯示的編輯器數目。將其設定為 0 以隱藏窗格。", - "dynamicHeight": "控制 [開放式編輯器] 區段的高度是否應依元素數目動態調整。", + "openEditorsVisible": "[開放式編輯器] 窗格中顯示的編輯器數目。", "autoReveal": "控制總管是否在開啟檔案時自動加以顯示及選取。", "enableDragAndDrop": "控制總管是否應該允許透過拖放功能移動檔案和資料夾。", "confirmDragAndDrop": "控制總管是否須要求確認,以透過拖放來移動檔案和資料夾。", diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 7a6f0b075f7..1b0a86e7ea2 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "在右方使用編輯器工具列中的動作來 **復原** 您的變更,或以您的變更 **覆寫** 磁碟上的內容", - "discard": "捨棄", + "overwriteElevated": "以系統管理者身分覆寫...", + "saveElevated": "以系統管理者身分重試", "overwrite": "覆寫", "retry": "重試", - "readonlySaveError": "無法儲存 '{0}': 檔案有防寫保護。請選取 [覆寫] 以移除保護。", + "discard": "捨棄", + "readonlySaveErrorAdmin": "無法儲存 '{0}': 檔案有防寫保護。請選取 [以系統管理者身分覆寫] 來做為系統管理者身分重試。 ", + "readonlySaveError": "無法儲存 '{0}': 檔案有防寫保護。請選取 [覆寫] 以嚐試移除保護。 ", + "permissionDeniedSaveError": "無法儲存 '{0}': 權限不足。請選取 [以系統管理者身分重試] 做為系統管理者身分重試。 ", "genericSaveError": "無法儲存 '{0}': {1}", "staleSaveError": "無法儲存 '{0}': 磁碟上的內容較新。請按一下 [比較],比較您的版本與磁碟上的版本。", "compareChanges": "比較", diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index bc42ca6193f..99aeb2ac46a 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,6 +10,7 @@ "dropFolder": "要在工作區新增資料夾嗎?", "addFolders": "新增資料夾(&A)", "addFolder": "新增資料夾(&A)", + "confirmMultiMove": "確定要移動以下 {0} 個文件嗎?", "confirmMove": "確定要移動 '{0}' 嗎?", "doNotAskAgain": "不要再詢問我", "moveButtonLabel": "移動(&&M)", diff --git a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index b48ed12d518..bc39c809e3d 100644 --- a/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "已開啟的編輯器", "openEditosrSection": "開放式編輯器區段", - "dirtyCounter": "{0} 未儲存", - "saveAll": "全部儲存", - "closeAllUnmodified": "關閉未變更的檔案", - "closeAll": "全部關閉", - "compareWithSaved": "與已儲存的檔案比較", - "close": "關閉", - "closeOthers": "關閉其他" + "dirtyCounter": "{0} 未儲存" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..2049a7686db --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "紀錄 (主要) ", + "sharedLog": "紀錄 (共享) ", + "rendererLog": "紀錄 (視窗)", + "extensionsLog": "紀錄 (延伸主機) ", + "developer": "開發人員" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..ce58da3b756 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "開啟紀錄資料夾", + "showLogs": "顯示紀錄...。", + "mainProcess": "主要", + "sharedProcess": "共享", + "rendererProcess": "視窗", + "extensionHost": "延伸主機", + "selectProcess": "選取程序", + "openLogFile": "開啟紀錄檔案...", + "setLogLevel": "設定記錄層級", + "trace": "追蹤", + "debug": "偵錯", + "info": "資訊", + "warn": "警告", + "err": "錯誤", + "critical": "嚴重", + "off": "關閉", + "selectLogLevel": "選擇紀錄層級" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/cht/src/vs/workbench/parts/markers/common/messages.i18n.json index 7fd5ffaf852..8f07ff5d3b3 100644 --- a/i18n/cht/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "viewCategory": "檢視", - "problems.view.toggle.label": "切換問題", - "problems.view.focus.label": "聚焦問題", + "problems.view.toggle.label": "切換至問題(錯誤, 警告, 資訊)", + "problems.view.focus.label": "聚焦於問題(錯誤, 警告, 資訊)", "problems.panel.configuration.title": "[問題] 檢視", "problems.panel.configuration.autoreveal": "控制 [問題] 檢視是否應自動在開啟檔案時加以顯示", "markers.panel.title.problems": "問題", diff --git a/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..8199db7ebb6 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "輸出", + "logViewer": "紀錄檢視器", + "viewCategory": "檢視", + "clearOutput.label": "清除輸出" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/cht/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..23c47ff24dc --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - 輸出", + "channel": "'{0}' 的輸出通道" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 0db1b09d33b..5c81c87f361 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -17,6 +17,7 @@ "resetLabel": "重設按鍵繫結關係", "showConflictsLabel": "顯示衝突", "copyLabel": "複製", + "copyCommandLabel": "複製命令", "error": "編輯按鍵繫結關係時發生錯誤 '{0}'。請開啟 'keybindings.json' 檔案加以檢查。", "command": "Command", "keybinding": "按鍵繫結關係", diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 1b98a0d9db9..c35a778205c 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 項相符設定", "settingsFound": "{0} 項相符設定", "totalSettingsMessage": "共 {0} 項設定", + "nlpResult": "自然語言結果", + "filterResult": "篩選結果", "defaultSettings": "預設設定", "defaultFolderSettings": "預設資料夾設定", "defaultEditorReadonly": "在右方編輯器中編輯以覆寫預設。", diff --git a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 480c3d2dbc2..5c3acf7c7d6 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "試試自然語言搜尋!", "defaultSettings": "將您的設定放置於右方編輯器中以覆寫。", "noSettingsFound": "找不到任何設定。", "settingsSwitcherBarAriaLabel": "設定切換器", "userSettings": "使用者設定", "workspaceSettings": "工作區設定", - "folderSettings": "資料夾設定", - "enableFuzzySearch": "啟用自然語言搜尋" + "folderSettings": "資料夾設定" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/cht/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 3aed5852085..4a5625894bd 100644 --- a/i18n/cht/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "經常使用的", - "mostRelevant": "最相關的", "defaultKeybindingsHeader": "將按鍵組合放入您的按鍵組合檔案中加以覆寫。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 238b60d7007..6a7eae1ed19 100644 --- a/i18n/cht/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "檢視", "commandsHandlerDescriptionDefault": "顯示並執行命令", "gotoLineDescriptionMac": "移至行", "gotoLineDescriptionWin": "移至行", diff --git a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index c0bccd6864c..5485a14415f 100644 --- a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "顯示 Git", "source control": "原始檔控制", "toggleSCMViewlet": "顯示 SCM", - "view": "檢視" + "view": "檢視", + "scmConfigurationTitle": "原始碼管理 (SCM)", + "alwaysShowProviders": "是否總是顯示原始檔控制提供者區段", + "diffDecorations": "控制差異裝飾於編輯器中", + "inputCounter": "控制何時顯示輸入計數器" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 72f9807aa29..2b766995de4 100644 --- a/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "原始檔控制提供者", "hideRepository": "隱藏", + "commitMessageInfo": "在目前行數有 {0} 個字元", + "commitMessageCountdown": "在目前行數剩餘 {0} 個字元", + "commitMessageWarning": "在目前行數有 {0} 個字元已超過 {1} 個", "installAdditionalSCMProviders": "安裝額外SCM提供者...", "no open repo": "沒有使用中的原始檔控制提供者。", "source control": "原始檔控制", diff --git a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 551008efc78..e52a383a212 100644 --- a/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "顯示上一個搜尋字詞", "showSearchViewlet": "顯示搜尋", "findInFiles": "在檔案中尋找", - "findInFilesWithSelectedText": "在檔案中尋找選取的文字 ", "replaceInFiles": "檔案中取代", - "replaceInFilesWithSelectedText": "在檔案中取代為選取的文字", "RefreshAction.label": "重新整理", "CollapseDeepestExpandedLevelAction.label": "全部摺疊", "ClearSearchResultsAction.label": "清除", diff --git a/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 2737e83ab4e..fa44f03a99c 100644 --- a/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "在資料夾中尋找...", + "findInWorkspace": "在工作區中尋找...", "showTriggerActions": "前往工作區中的符號...", "name": "搜尋", "search": "搜尋", + "showSearchViewlet": "顯示搜尋", "view": "檢視", + "findInFiles": "在檔案中尋找", "openAnythingHandlerDescription": "前往檔案", "openSymbolDescriptionNormal": "前往工作區中的符號", - "searchOutputChannelTitle": "搜尋", "searchConfigurationTitle": "搜尋", "exclude": "設定 Glob 模式,以排除不要搜尋的檔案及資料夾。請從 file.exclude 設定繼承所有的 Glob 模式。", "exclude.boolean": "要符合檔案路徑的 Glob 模式。設為 True 或 False 可啟用或停用模式。", diff --git a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..dfb95035915 --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.scope": "(全域)", + "global.1": "({0})", + "new.global": "新增全域程式碼片段檔案...", + "group.global": "現有程式碼片段", + "new.global.sep": "新增程式碼片段", + "openSnippet.pickLanguage": "選取程式碼片段檔案或建立程式碼片段", + "openSnippet.label": "設定使用者程式碼片段", + "preferences": "喜好設定" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 10abf9bdd4d..115f5980d39 100644 --- a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "為程式碼片段選取語言", - "openSnippet.errorOnCreate": "無法建立 {0}", - "openSnippet.label": "開啟使用者程式碼片段", - "preferences": "喜好設定", "snippetSchema.json.default": "空白程式碼片段", "snippetSchema.json": "使用者程式碼片段組態", "snippetSchema.json.prefix": "在 Intellisense 中選取程式碼片段時要使用的前置詞", diff --git a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..4a43b9b0daf --- /dev/null +++ b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "使用者程式碼片段" +} \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index e7261d392fd..bcbd784bf1c 100644 --- a/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "`contributes.{0}.language` 中的不明語言。提供的值: {1}", "invalid.path.0": "'contributes.{0}.path' 中應有字串。提供的值: {1}", + "invalid.language": "`contributes.{0}.language` 中的不明語言。提供的值: {1}", "invalid.path.1": "擴充功能資料夾 ({2}) 應包含 'contributes.{0}.path' ({1})。這可能會導致擴充功能無法移植。", "vscode.extension.contributes.snippets": "提供程式碼片段。", "vscode.extension.contributes.snippets-language": "要予以提供此程式碼片段的語言識別碼。", "vscode.extension.contributes.snippets-path": "程式碼片段檔案的路徑。此路徑是擴充功能資料夾的相對路徑,而且一般會以 './snippets/' 開頭。", "badVariableUse": "來自延伸模組 '{0}' 的一或多個程式碼片段很可能會混淆程式碼片段變數和程式碼片段預留位置 (如需更多詳細資料,請參閱 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax)", "badFile": "無法讀取程式碼片段檔案 \"{0}\"。", - "source.snippet": "使用者程式碼片段", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0},{1}" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 80abe8bb59c..11d4003e254 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -13,7 +13,9 @@ "terminal.integrated.shellArgs.osx": "在 OS X 終端機要使用的命令列引數。", "terminal.integrated.shell.windows": "終端機在 Windows 上使用的殼層路徑。使用隨附於 Windows 的殼層 (cmd、PowerShell 或 Bash on Ubuntu) 時。", "terminal.integrated.shellArgs.windows": "在 Windows 終端機上時要使用的命令列引數。", + "terminal.integrated.macOptionIsMeta": "將選項鍵視為 macOS 終端機中的 meta 鍵。", "terminal.integrated.rightClickCopyPaste": "如有設定,這會防止在終端機內按滑鼠右鍵時顯示操作功能表,而是在有選取項目時複製、沒有選取項目時貼上。", + "terminal.integrated.copyOnSelection": "當設定時,在終端機中選擇的文字將會被複製至剪貼簿", "terminal.integrated.fontFamily": "控制終端機的字型家族,預設為 editor.fontFamily 的值。", "terminal.integrated.fontSize": "控制終端機的字型大小 (以像素為單位)。", "terminal.integrated.lineHeight": "控制終端機的行高,此數字會乘上終端機字型大小,以取得以像素為單位的實際行高。", @@ -24,10 +26,12 @@ "terminal.integrated.setLocaleVariables": "控制是否在終端機啟動時設定地區設定變數,這在 OS X 上預設為 true,在其他平台則為 false。", "terminal.integrated.cwd": "終端機啟動位置的明確起始路徑,這會用作殼層處理序的目前工作目錄 (cwd)。當根目錄不是方便的 cwd 時,這在工作區設定中特別好用。", "terminal.integrated.confirmOnExit": "當有使用中的終端機工作階段時,是否要在結束時確認。", + "terminal.integrated.enableBell": "是否啟用終端機警告聲。", "terminal.integrated.commandsToSkipShell": "一組命令識別碼,其按鍵繫結關係將不會傳送到殼層,而會一律由 Code 處理。這讓通常由殼層取用的按鍵繫結關係,在使用上與未聚焦於終端機時行為相同,例如 Ctrl+P 可啟動 Quick Open。", "terminal.integrated.env.osx": "OS X 上的終端機要使用之具有將新增至 VS Code 流程之環境變數的物件", "terminal.integrated.env.linux": "Linux 上的終端機要使用之具有將新增至 VS Code 流程之環境變數的物件", "terminal.integrated.env.windows": "Windows 上的終端機要使用之具有將新增至 VS Code 流程之環境變數的物件", + "terminal.integrated.showExitAlert": "當結束代碼非 0,顯示警告訊息 '終端處理序已終止並回傳結束代碼'", "terminalCategory": "終端機", "viewCategory": "檢視" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 40342458179..2fcd49773a9 100644 --- a/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -12,8 +12,11 @@ "workbench.action.terminal.selectAll": "全選", "workbench.action.terminal.deleteWordLeft": "刪除左方文字", "workbench.action.terminal.deleteWordRight": "刪除右方文字", + "workbench.action.terminal.enterLineNavigationMode": "進入螢幕閱讀器導航模式", "workbench.action.terminal.new": "建立新的整合式終端機", "workbench.action.terminal.new.short": "新增終端機", + "workbench.action.terminal.newWorkspacePlaceholder": "為新的終端機選擇目前的工作目錄", + "workbench.action.terminal.newInActiveWorkspace": "建立新的整合式終端機 (於目前工作區)", "workbench.action.terminal.focus": "聚焦終端機", "workbench.action.terminal.focusNext": "聚焦下一個終端機", "workbench.action.terminal.focusPrevious": "聚焦上一個終端機", diff --git a/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json index e043af15328..0090723f9a2 100644 --- a/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/cht/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "命令選擇區...", "settings": "設定", "keyboardShortcuts": "鍵盤快速鍵(&&K)", + "userSnippets": "使用者程式碼片段", "selectTheme.label": "色彩佈景主題", "themes.selectIconTheme.label": "檔案圖示佈景主題", "not available": "無可用更新", diff --git a/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 067f2923a48..106253b1f0c 100644 --- a/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "檔案是目錄", + "fileNotModifiedError": "未修改檔案的時間", "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json index de69c42ba6c..d44f480acd2 100644 --- a/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "檔案太大無法開啟", "fileNotFoundError": "找不到檔案 ({0})", "fileBinaryError": "檔案似乎是二進位檔,因此無法當做文字開啟", + "filePermission": "寫至檔案 ({0}) 的權限遭拒", "fileExists": "要建立的檔案已存在 ({0})", "fileMoveConflict": "無法移動/複製。目的地已存在檔案。", "unableToMoveCopyError": "無法移動/複製。檔案會取代其所在的資料夾。", diff --git a/i18n/cht/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/cht/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index 3d15720ddec..2068790ab0f 100644 --- a/i18n/cht/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "按鍵為使用中時的條件。", "keybindings.json.args": "要傳遞至命令加以執行的引數。", "keyboardConfigurationTitle": "鍵盤", - "dispatch": "控制按下按鍵時的分派邏輯 (使用 'code' (建議使用) 或 'keyCode')。" + "dispatch": "控制按下按鍵時的分派邏輯 (使用 'code' (建議使用) 或 'keyCode')。", + "touchbar.enabled": "啟用鍵盤上的 macOS 觸摸板按鈕 (如果可用)。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/cht/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 5fb9fd9998b..fe4c04e35cd 100644 --- a/i18n/cht/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "要儲存對 {0} 所做的變更嗎?", "saveChangesMessages": "要儲存對下列 {0} 個檔案所做的變更嗎?", - "moreFile": "...另外 1 個檔案未顯示", - "moreFiles": "...另外 {0} 個檔案未顯示", "saveAll": "全部儲存(&&S)", "save": "儲存(&&S)", "dontSave": "不要儲存(&&N)", diff --git a/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 939ead9df9c..8096baf2953 100644 --- a/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "依目前選擇的彩色佈景主題覆寫顏色", - "editorColors": "依目前選取的色彩佈景主題覆寫編輯器色彩與字型樣式。", "editorColors.comments": "設定註解的色彩與樣式", "editorColors.strings": "設定字串常值的色彩與樣式。", "editorColors.keywords": "設定關鍵字的色彩與樣式。", @@ -19,5 +18,6 @@ "editorColors.types": "設定型別宣告與參考的色彩與樣式。", "editorColors.functions": "設定函式宣告與參考的色彩與樣式。", "editorColors.variables": "設定變數宣告與參考的色彩與樣式。", - "editorColors.textMateRules": "使用 TextMate 佈景主題規則設定色彩與樣式 (進階)。" + "editorColors.textMateRules": "使用 TextMate 佈景主題規則設定色彩與樣式 (進階)。", + "editorColors": "依目前選取的色彩佈景主題覆寫編輯器色彩與字型樣式。" } \ No newline at end of file diff --git a/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 283d3809ddb..e0710f14e3f 100644 --- a/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/cht/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "無法寫入工作區組態檔。請開啟檔案更正其中的錯誤/警告,然後再試一次。 ", "errorWorkspaceConfigurationFileDirty": "因為檔案已變更,所以無法寫入工作區組態檔。請將其儲存,然後再試一次。", "openWorkspaceConfigurationFile": "開啟工作區組態檔", - "close": "關閉", - "enterWorkspace.close": "關閉", - "enterWorkspace.dontShowAgain": "不要再顯示", - "enterWorkspace.moreInfo": "詳細資訊", - "enterWorkspace.prompt": "深入了解在 VS Code 中使用多個資料夾。" + "close": "關閉" } \ No newline at end of file diff --git a/i18n/deu/extensions/git/out/autofetch.i18n.json b/i18n/deu/extensions/git/out/autofetch.i18n.json index e1242008fcf..5a1bb589fb2 100644 --- a/i18n/deu/extensions/git/out/autofetch.i18n.json +++ b/i18n/deu/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Ja", + "read more": "Weitere Informationen", "no": "Nein", - "not now": "Nicht jetzt", - "suggest auto fetch": "Möchten Sie das automatische Abrufen von Git-Repositorys aktivieren?" + "not now": "Erneut nachfragen", + "suggest auto fetch": "Möchten Sie Code regelmäßig `git fetch` ausführen lassen?" } \ No newline at end of file diff --git a/i18n/deu/extensions/git/out/commands.i18n.json b/i18n/deu/extensions/git/out/commands.i18n.json index 27787e3b3d4..106aebcff97 100644 --- a/i18n/deu/extensions/git/out/commands.i18n.json +++ b/i18n/deu/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nDies kann NICHT rückgängig gemacht werden, und Ihr aktueller Arbeitssatz geht DAUERHAFT verloren.", "yes discard tracked": "1 verfolgte Datei verwerfen", "yes discard tracked multiple": "{0} verfolgte Dateien verwerfen", + "unsaved files single": "Die folgende Datei ist nicht gespeichert: {0}.\n\nMöchten Sie diese vor dem Committen speichern?", + "unsaved files": "{0} Dateien sind nicht gespeichert.\n\nMöchten Sie diese vor dem Committen speichern?", + "save and commit": "Alles speichern und committen", + "commit": "Trotzdem committen", "no staged changes": "Es sind keine Änderungen bereitgestellt.\n\nMöchten Sie alle Ihre Änderungen automatisch bereitstellen und direkt committen?", "always": "Immer", "no changes": "Keine Änderungen zum Speichern vorhanden.", @@ -64,12 +68,11 @@ "no remotes to pull": "In Ihrem Repository wurden keine Remoteelemente für den Pull konfiguriert.", "pick remote pull repo": "Remoteelement zum Pullen des Branch auswählen", "no remotes to push": "In Ihrem Repository wurden keine Remoteelemente für den Push konfiguriert.", - "push with tags success": "Push mit Tags erfolgreich ausgeführt.", "nobranch": "Wählen Sie ein Branch für den Push zu einem Remoteelement aus.", + "ok": "OK", + "push with tags success": "Push mit Tags erfolgreich ausgeführt.", "pick remote": "Remotespeicherort auswählen, an dem der Branch \"{0}\" veröffentlicht wird:", "sync is unpredictable": "Mit dieser Aktion werden Commits per Push und Pull an und von \"{0}\" übertragen.", - "ok": "OK", - "never again": "OK, nicht mehr anzeigen", "no remotes to publish": "In Ihrem Repository wurden keine Remoteelemente für die Veröffentlichung konfiguriert.", "no changes stash": "Es sind keine Änderungen vorhanden, für die ein Stash ausgeführt werden kann.", "provide stash message": "Geben Sie optional eine Stash-Nachricht ein.", diff --git a/i18n/deu/extensions/git/out/repository.i18n.json b/i18n/deu/extensions/git/out/repository.i18n.json index 9c6af561332..cb3c5c9809f 100644 --- a/i18n/deu/extensions/git/out/repository.i18n.json +++ b/i18n/deu/extensions/git/out/repository.i18n.json @@ -27,6 +27,6 @@ "staged changes": "Bereitgestellte Änderungen", "changes": "Änderungen", "ok": "OK", - "neveragain": "Nie wieder anzeigen", + "neveragain": "Nicht mehr anzeigen", "huge": "Das Git-Repository unter {0} umfasst zu viele aktive Änderungen. Nur ein Teil der Git-Features wird aktiviert." } \ No newline at end of file diff --git a/i18n/deu/extensions/git/package.i18n.json b/i18n/deu/extensions/git/package.i18n.json index de4d841dd21..d9f684ed551 100644 --- a/i18n/deu/extensions/git/package.i18n.json +++ b/i18n/deu/extensions/git/package.i18n.json @@ -49,17 +49,17 @@ "command.showOutput": "Git-Ausgabe anzeigen", "command.ignore": "Datei zu .gitignore hinzufügen", "command.stashIncludeUntracked": "Stash (einschließlich nicht verfolgt)", - "command.stash": " Stash ausführen", + "command.stash": "Stash ausführen", "command.stashPop": "Pop für Stash ausführen...", "command.stashPopLatest": "Pop für letzten Stash ausführen", "config.enabled": "Gibt an, ob Git aktiviert ist.", "config.path": "Der Pfad zur ausführbaren Git-Datei.", + "config.autoRepositoryDetection": "Ob Repositorien automatisch erkannt werden sollen", "config.autorefresh": "Gibt an, ob die automatische Aktualisierung aktiviert ist.", "config.autofetch": "Gibt an, ob automatischer Abruf aktiviert ist.", "config.enableLongCommitWarning": "Gibt an, ob Warnungen zu langen Commitnachrichten erfolgen sollen.", "config.confirmSync": "Vor dem Synchronisieren von Git-Repositorys bestätigen.", "config.countBadge": "Steuert die Git-Badgeanzahl. \"Alle\" zählt alle Änderungen. \"tracked\" (Nachverfolgt) zählt nur die nachverfolgten Änderungen. \"off\" (Aus) deaktiviert dies.", - "config.checkoutType": "Steuert, welcher Branchtyp beim Ausführen von \"Auschecken an...\" aufgelistet wird. \"Alle\" zeigt alle Verweise an, \"Lokal\" nur die lokalen Branches, \"Tags\" zeigt nur Tags an, und \"Remote\" zeigt nur Remotebranches an.", "config.ignoreLegacyWarning": "Ignoriert die Legacy-Git-Warnung.", "config.ignoreMissingGitWarning": "Ignoriert die Warnung, wenn Git fehlt", "config.ignoreLimitWarning": "Ignoriert Warnung bei zu hoher Anzahl von Änderungen in einem Repository", @@ -72,5 +72,6 @@ "colors.deleted": "Farbe für gelöschten Ressourcen.", "colors.untracked": "Farbe für nicht verfolgte Ressourcen.", "colors.ignored": "Farbe für ignorierte Ressourcen.", - "colors.conflict": "Farbe für Ressourcen mit Konflikten." + "colors.conflict": "Farbe für Ressourcen mit Konflikten.", + "colors.submodule": "Farbe für Submodul-Ressourcen." } \ No newline at end of file diff --git a/i18n/deu/extensions/typescript/out/commands.i18n.json b/i18n/deu/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..abb5c164718 --- /dev/null +++ b/i18n/deu/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Öffnen Sie einen Ordner in VS Code, um ein TypeScript- oder JavaScript-Projekt zu verwenden.", + "typescript.projectConfigUnsupportedFile": "TypeScript- oder JavaScript-Projekt konnte nicht ermittelt werden. Nicht unterstützter Dateityp.", + "typescript.projectConfigCouldNotGetInfo": "TypeScript- oder JavaScript-Projekt konnte nicht ermittelt werden.", + "typescript.noTypeScriptProjectConfig": "Datei ist nicht Teil eines TypeScript-Projekts.", + "typescript.noJavaScriptProjectConfig": "Datei ist nicht Teil eines JavaScript-Projekts.", + "typescript.configureTsconfigQuickPick": "tsconfig.json konfigurieren", + "typescript.configureJsconfigQuickPick": "jsconfig.json konfigurieren", + "typescript.projectConfigLearnMore": "Weitere Informationen" +} \ No newline at end of file diff --git a/i18n/deu/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/deu/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/deu/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/deu/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/deu/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/deu/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/base/node/ps.i18n.json b/i18n/deu/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..eb881148d8c --- /dev/null +++ b/i18n/deu/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Sammeln von CPU- und Speicherinformationen. Dies kann einige Sekunden dauern." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json index 42d65e250ff..4fbcab5f91e 100644 --- a/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/deu/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Zeilennummern werden als absolute Zahl dargestellt.", "lineNumbers.relative": "Zeilennummern werden als Abstand in Zeilen an Cursorposition dargestellt.", "lineNumbers.interval": "Zeilennummern werden alle 10 Zeilen dargestellt.", - "lineNumbers": "Steuert die Anzeige von Zeilennummern. Mögliche Werte sind \"Ein\", \"Aus\" und \"Relativ\".", + "lineNumbers": "Steuert die Anzeige von Zeilennummern. Mögliche Werte sind \"on\", \"off\", \"relative\" und \"interval\".", "rulers": "Vertikale Linien nach einer bestimmten Anzahl von Monospace Zeichen zeichnen. Verwenden Sie mehrere Werte für mehrere Linien. Keine Linie wird gezeichnet, wenn das Array leer ist.", "wordSeparators": "Zeichen, die als Worttrennzeichen verwendet werden, wenn wortbezogene Navigationen oder Vorgänge ausgeführt werden.", "tabSize": "Die Anzahl der Leerzeichen, denen ein Tabstopp entspricht. Diese Einstellung wird basierend auf dem Inhalt der Datei überschrieben, wenn \"editor.detectIndentation\" aktiviert ist.", @@ -40,9 +40,6 @@ "wordWrapColumn": "Steuert die Umbruchspalte des Editors, wenn für \"editor.wordWrap\" die Option \"wordWrapColumn\" oder \"bounded\" festgelegt ist.", "wrappingIndent": "Steuert den Einzug der umbrochenen Zeilen. Der Wert kann \"none\", \"same\" oder \"indent\" sein.", "mouseWheelScrollSensitivity": "Ein Multiplikator, der für die Mausrad-Bildlaufereignisse \"deltaX\" und \"deltaY\" verwendet werden soll.", - "multiCursorModifier.ctrlCmd": "Ist unter Windows und Linux der Taste \"STRG\" und unter OSX der Befehlstaste zugeordnet.", - "multiCursorModifier.alt": "Ist unter Windows und Linux der Taste \"Alt\" und unter OSX der Wahltaste zugeordnet. ", - "multiCursorModifier": "Der Modifizierer, der zum Hinzufügen mehrerer Cursor mit der Maus verwendet wird. \"ctrlCmd\" wird unter Windows und Linux der Taste \"STRG\" und unter OSX der Befehlstaste zugeordnet. Die Mausbewegungen \"Gehe zu Definition\" und \"Link öffnen\" werden so angepasst, dass kein Konflikt mit dem Multi-Cursor-Modifizierer entsteht.", "quickSuggestions.strings": "Schnellvorschläge innerhalb von Zeichenfolgen aktivieren.", "quickSuggestions.comments": "Schnellvorschläge innerhalb von Kommentaren aktivieren.", "quickSuggestions.other": "Schnellvorschläge außerhalb von Zeichenfolgen und Kommentaren aktivieren.", @@ -72,6 +69,7 @@ "cursorBlinking": "Steuert den Cursoranimationsstil. Gültige Werte sind \"blink\", \"smooth\", \"phase\", \"expand\" und \"solid\".", "mouseWheelZoom": "Schriftart des Editors vergrößern, wenn das Mausrad verwendet und die STRG-TASTE gedrückt wird", "cursorStyle": "Steuert den Cursorstil. Gültige Werte sind \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" und \"underline-thin\".", + "lineCursorWidth": "Steuert die Breite des Cursors, falls editor.cursorStyle auf \"line\" gestellt ist.", "fontLigatures": "Aktiviert Schriftartligaturen.", "hideCursorInOverviewRuler": "Steuert die Sichtbarkeit des Cursors im Übersichtslineal.", "renderWhitespace": "Steuert, wie der Editor Leerzeichen rendert. Mögliche Optionen: \"none\", \"boundary\" und \"all\". Die Option \"boundary\" rendert keine einzelnen Leerzeichen zwischen Wörtern.", diff --git a/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json index fa37f670425..7c9c0c38962 100644 --- a/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/deu/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "Hintergrundfarbe zur Hervorhebung der Zeile an der Cursorposition.", "lineHighlightBorderBox": "Hintergrundfarbe für den Rahmen um die Zeile an der Cursorposition.", - "rangeHighlight": "Hintergrundfarbe hervorgehobener Bereiche (beispielsweise durch Features wie Quick Open und Suche).", + "rangeHighlight": "Hintergrundfarbe hervorgehobener Bereiche, beispielsweise durch Features wie Quick Open und Suche. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "caret": "Farbe des Cursors im Editor.", "editorCursorBackground": "Hintergrundfarbe vom Editor-Cursor. Erlaubt die Anpassung der Farbe von einem Zeichen, welches von einem Block-Cursor überdeckt wird.", "editorWhitespaces": "Farbe der Leerzeichen im Editor.", diff --git a/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 02553773e89..f0964e09e29 100644 --- a/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Gehe zum nächsten Fehler oder zur nächsten Warnung", - "markerAction.previous.label": "Gehe zum vorherigen Fehler oder zur vorherigen Warnung", + "markerAction.next.label": "Gehe zu nächstem Problem (Fehler, Warnung, Information)", + "markerAction.previous.label": "Gehe zu vorigem Problem (Fehler, Warnung, Information)", "editorMarkerNavigationError": "Editormarkierung: Farbe bei Fehler des Navigationswidgets.", "editorMarkerNavigationWarning": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", "editorMarkerNavigationInfo": "Editormarkierung: Farbe bei Warnung des Navigationswidgets.", diff --git a/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index d706ff2e9b2..494db968f98 100644 --- a/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/deu/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Hintergrundfarbe eines Symbols beim Lesezugriff (beispielsweise beim Lesen einer Variablen).", - "wordHighlightStrong": "Hintergrundfarbe eines Symbols beim Schreibzugriff (beispielsweise beim Schreiben in eine Variable).", + "wordHighlight": "Hintergrundfarbe eines Symbols bei Lesezugriff, beispielsweise dem Lesen einer Variable. Die Farbe muss durchsichtig sein, um nicht dahinterliegende Dekorationen zu verbergen.", + "wordHighlightStrong": "Hintergrundfarbe eines Symbols bei Schreibzugriff, beispielsweise dem Schreiben einer Variable. Die Farbe muss durchsichtig sein, um nicht dahinterliegende Dekorationen zu verbergen.", "overviewRulerWordHighlightForeground": "Übersichtslineal-Markierungsfarbe für Symbolhervorhebungen.", "overviewRulerWordHighlightStrongForeground": "Übersichtslineal-Markierungsfarbe für Schreibzugriffs-Symbolhervorhebungen.", "wordHighlight.next.label": "Gehe zur nächsten Symbolhervorhebungen", diff --git a/i18n/deu/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/deu/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 5cd50df300a..30e3fed7ba6 100644 --- a/i18n/deu/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/deu/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "\"{0}\" ist kein gültiger Menübezeichner.", "missing.command": "Das Menüelement verweist auf einen Befehl \"{0}\", der im Abschnitt \"commands\" nicht definiert ist.", "missing.altCommand": "Das Menüelement verweist auf einen Alternativbefehl \"{0}\", der im Abschnitt \"commands\" nicht definiert ist.", - "dupe.command": "Das Menüelement verweist auf den gleichen Befehl wie der Standard- und der Alternativbefehl.", - "nosupport.altCommand": "Leider unterstützt zurzeit nur die Gruppe \"navigation\" des Menüs \"editor/title\" Alternativbefehle." + "dupe.command": "Das Menüelement verweist auf den gleichen Befehl wie der Standard- und der Alternativbefehl." } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/environment/node/argv.i18n.json b/i18n/deu/src/vs/platform/environment/node/argv.i18n.json index e990ea9bf1e..dac01ef64d6 100644 --- a/i18n/deu/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/deu/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,35 @@ "diff": "Vergleicht zwei Dateien.", "add": "Fügt einen oder mehrere Ordner zum letzten aktiven Fenster hinzu.", "goto": "Öffnet eine Datei im Pfad in der angegebenen Zeile und an der Zeichenposition.", - "locale": "Das zu verwendende Gebietsschema (z. B. en-US oder zh-TW).", "newWindow": "Erzwingt eine neue Instanz des Codes.", - "performance": "Startet mit aktiviertem Befehl \"Developer: Startup Performance\".", - "prof-startup": "CPU-Profiler beim Start ausführen", - "inspect-extensions": "Erlaubt Debugging und Profiling für Erweiterungen. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", - "inspect-brk-extensions": "Erlaubt Debugging und Profiling für Erweiterungen, wobei der Erweiterungs-Host nach dem Starten pausiert wird. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", "reuseWindow": "Erzwingt das Öffnen einer Datei oder eines Ordners im letzten aktiven Fenster.", - "userDataDir": "Gibt das Verzeichnis an, in dem Benutzerdaten gespeichert werden. Nützlich, wenn die Ausführung als \"root\" erfolgt.", - "log": "Log-Level zu verwenden. Standardwert ist \"Info\". Zulässige Werte sind \"kritisch\", \"Fehler\", \"warnen\", \"Info\", \"debug\", \"verfolgen\", \"aus\".", - "verbose": "Ausführliche Ausgabe (impliziert \"-wait\").", "wait": "Warten Sie, bis die Dateien geschlossen sind, bevor Sie zurück gehen können.", + "locale": "Das zu verwendende Gebietsschema (z. B. en-US oder zh-TW).", + "userDataDir": "Gibt das Verzeichnis an, in dem Benutzerdaten gespeichert werden. Nützlich, wenn die Ausführung als \"root\" erfolgt.", + "version": "Gibt die Version aus.", + "help": "Gibt die Syntax aus.", "extensionHomePath": "Legen Sie den Stammpfad für Extensions fest.", "listExtensions": "Listet die installierten Extensions auf.", "showVersions": "Zeigt Versionen der installierten Erweiterungen an, wenn \"--list-extension\" verwendet wird.", "installExtension": "Installiert eine Extension.", "uninstallExtension": "Deinstalliert eine Extension.", "experimentalApis": "Aktiviert vorgeschlagene API-Features für eine Erweiterung.", - "disableExtensions": "Deaktiviert alle installierten Extensions.", - "disableGPU": "Deaktiviert die GPU-Hardwarebeschleunigung.", + "verbose": "Ausführliche Ausgabe (impliziert \"-wait\").", + "log": "Log-Level zu verwenden. Standardwert ist \"Info\". Zulässige Werte sind \"kritisch\", \"Fehler\", \"warnen\", \"Info\", \"debug\", \"verfolgen\", \"aus\".", "status": "Prozessnutzungs- und Diagnose-Informationen ausgeben.", - "version": "Gibt die Version aus.", - "help": "Gibt die Syntax aus.", + "performance": "Startet mit aktiviertem Befehl \"Developer: Startup Performance\".", + "prof-startup": "CPU-Profiler beim Start ausführen", + "disableExtensions": "Deaktiviert alle installierten Extensions.", + "inspect-extensions": "Erlaubt Debugging und Profiling für Erweiterungen. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", + "inspect-brk-extensions": "Erlaubt Debugging und Profiling für Erweiterungen, wobei der Erweiterungs-Host nach dem Starten pausiert wird. Überprüfen Sie die Entwicklertools für die Verbindungs-URI.", + "disableGPU": "Deaktiviert die GPU-Hardwarebeschleunigung.", + "uploadLogs": "Lädt die Logs der aktuellen Sitzung an einem sicheren Endpunkt hoch.", "usage": "Verwendung", "options": "Optionen", "paths": "Pfade", - "optionsUpperCase": "Optionen" + "stdinWindows": "Zum Einlesen von Ausgaben eines anderen Programms hängen Sie '-' an (z.B. 'echo Hello World | {0} -')", + "stdinUnix": "Zum Einlesen von stdin hängen Sie '-' an (z.B. 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Optionen", + "extensionsManagement": "Erweiterungsverwaltung", + "troubleshooting": "Problembehandlung" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 256756a3fdd..bd3552bcdfe 100644 --- a/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/deu/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Die Erweiterung ist ungültig: \"package.json\" ist keine JSON-Datei.", - "restartCodeLocal": "Bitte starten Sie Code vor der Neuinstallation von {0} neu.", + "restartCode": "Bitte starten Sie Code vor der Neuinstallation von {0} neu.", "installingOutdatedExtension": "Eine neuere Version dieser Erweiterung ist bereits installiert. Möchten Sie diese mit der älteren Version überschreiben?", "override": "Überschreiben", "cancel": "Abbrechen", - "notFoundCompatible": "Kann nicht installiert werden, da die Erweiterung '{0}', die mit der aktuellen Version '{1}' von VS Code kompatibel ist, nicht gefunden werden kann.", - "quitCode": "Kann nicht installiert werden, da noch eine veraltete Instanz der Erweiterung ausgeführt wird. Bitte beenden und VS Code neu starten vor der Neuinstallation.", - "exitCode": "Kann nicht installiert werden, da noch eine veraltete Instanz der Erweiterung ausgeführt wird. Bitte beenden und VS Code neu starten vor der Neuinstallation.", + "errorInstallingDependencies": "Fehler während Installation der Abhängigkeiten. {0}", + "notFoundCompatible": "'{0}' kann nicht installiert werden: Es gibt keine mit VS Code '{1}' kompatible Version.", "notFoundCompatibleDependency": "Kann nicht installiert werden, da die abhängige Erweiterung '{0}', die mit der aktuellen VS Code Version '{1}' kompatibel ist, nicht gefunden werden kann. ", + "quitCode": "Fehler bei der Installation der Erweiterung. Beenden und starten Sie VS Code vor der erneuten Installation neu.", + "exitCode": "Fehler bei der Installation der Erweiterung. Beenden und starten Sie VS Code vor der erneuten Installation neu.", "uninstallDependeciesConfirmation": "Möchten Sie nur \"{0}\" oder auch die zugehörigen Abhängigkeiten deinstallieren?", "uninstallOnly": "Nur", "uninstallAll": "Alle", diff --git a/i18n/deu/src/vs/platform/list/browser/listService.i18n.json b/i18n/deu/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..b9d7e353c74 --- /dev/null +++ b/i18n/deu/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Workbench" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/message/common/message.i18n.json b/i18n/deu/src/vs/platform/message/common/message.i18n.json index f4286f9eb78..774ad662835 100644 --- a/i18n/deu/src/vs/platform/message/common/message.i18n.json +++ b/i18n/deu/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Schließen", "later": "Später", - "cancel": "Abbrechen" + "cancel": "Abbrechen", + "moreFile": "...1 weitere Datei wird nicht angezeigt", + "moreFiles": "...{0} weitere Dateien werden nicht angezeigt" } \ No newline at end of file diff --git a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json index 93785571085..9159f1402da 100644 --- a/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/deu/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,10 @@ "editorWidgetBorder": "Rahmenfarbe von Editorwigdets. Die Farbe wird nur verwendet, wenn für das Widget ein Rahmen verwendet wird und die Farbe nicht von einem Widget überschrieben wird.", "editorSelectionBackground": "Farbe der Editor-Auswahl.", "editorSelectionForeground": "Farbe des gewählten Text für einen hohen Kontrast", - "editorInactiveSelection": "Farbe der Auswahl in einem inaktiven Editor.", - "editorSelectionHighlight": "Farbe für Bereiche, deren Inhalt der Auswahl entspricht.", + "editorInactiveSelection": "Farbe der Auswahl in einem inaktiven Editor. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "editorSelectionHighlight": "Farbe für Bereiche, deren Inhalt der Auswahl entspricht. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", "editorFindMatch": "Farbe des aktuellen Suchergebnisses.", - "findMatchHighlight": "Farbe der anderen Suchtreffer.", - "findRangeHighlight": "Farbe des Bereichs zur Einschränkung der Suche.", - "hoverHighlight": "Hervorhebung eines Worts, unter dem ein Mauszeiger angezeigt wird.", + "findMatchHighlight": "Farbe der anderen Suchergebnisse. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "hoverBackground": "Background color of the editor hover.", "hoverBorder": "Rahmenfarbe des Editor-Mauszeigers.", "activeLinkForeground": "Farbe der aktiven Links.", @@ -76,12 +74,10 @@ "diffEditorRemoved": "Hintergrundfarbe für entfernten Text.", "diffEditorInsertedOutline": "Konturfarbe für eingefügten Text.", "diffEditorRemovedOutline": "Konturfarbe für entfernten Text.", - "mergeCurrentHeaderBackground": "Aktueller Kopfzeilenhintergrund in Inline-Mergingkonflikten.", - "mergeCurrentContentBackground": "Aktueller Inhaltshintergrund in Inline-Mergingkonflikten.", - "mergeIncomingHeaderBackground": "Eingehender Kopfzeilenhintergrund in Inline-Mergingkonflikten. ", - "mergeIncomingContentBackground": "Eingehender Inhaltshintergrund in Inline-Mergingkonflikten.", - "mergeCommonHeaderBackground": "Kopfzeilenhintergrund des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten. ", - "mergeCommonContentBackground": "Inhaltshintergrund des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten.", + "mergeCurrentHeaderBackground": "Aktueller Kopfzeilenhintergrund in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen.", + "mergeCurrentContentBackground": "Aktueller Inhaltshintergrund in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "mergeIncomingHeaderBackground": "Hintergrund für eingehende Kopfzeile in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", + "mergeIncomingContentBackground": "Hintergrund für eingehenden Inhalt in Inline-Mergingkonflikten. Die Farbe muss durchsichtig sein, um dahinterliegende Dekorationen nicht zu verbergen. ", "mergeBorder": "Rahmenfarbe für Kopfzeilen und die Aufteilung in Inline-Mergingkonflikten.", "overviewRulerCurrentContentForeground": "Aktueller Übersichtslineal-Vordergrund für Inline-Mergingkonflikte.", "overviewRulerIncomingContentForeground": "Eingehender Übersichtslineal-Vordergrund für Inline-Mergingkonflikte. ", diff --git a/i18n/deu/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/deu/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..92a29050896 --- /dev/null +++ b/i18n/deu/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "Die Eigenschaft \"{0}\" ist erforderlich. Sie muss vom Typ \"string\" sein.", + "optstring": "Die Eigenschaft \"{0}\" kann ausgelassen werden oder muss vom Typ \"string\" sein." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/deu/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/deu/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 76a36688913..d76ac6f1642 100644 --- a/i18n/deu/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/deu/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -4,7 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "treeView.notRegistered": "Kein Treeviw mit der id '{0}' registriert.", - "treeItem.notFound": "Kein Tree-Eintrag mit der id '{0}' gefunden.", - "treeView.duplicateElement": "Element {0} ist bereit registriert." + "treeView.notRegistered": "Kein Treeviw mit der id '{0}' registriert." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/deu/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index c676a1ca340..c0039e0b445 100644 --- a/i18n/deu/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Position der Seitenleiste wechseln", "view": "Anzeigen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 174408464b6..79911f9a8b9 100644 --- a/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Datei öffnen...", "openFolder": "Ordner öffnen...", "openFileFolder": "Öffnen...", - "addFolderToWorkspace": "Ordner zum Arbeitsbereich hinzufügen...", - "add": "&&Hinzufügen", - "addFolderToWorkspaceTitle": "Ordner zum Arbeitsbereich hinzufügen", "globalRemoveFolderFromWorkspace": "Ordner aus dem Arbeitsbereich entfernen...", - "removeFolderFromWorkspace": "Ordner aus dem Arbeitsbereich entfernen", - "openFolderSettings": "Ordnereinstellungen öffnen", "saveWorkspaceAsAction": "Arbeitsbereich speichern unter...", "save": "&&Speichern", "saveWorkspace": "Arbeitsbereich speichern", "openWorkspaceAction": "Arbeitsbereich öffnen...", "openWorkspaceConfigFile": "Konfigurationsdatei des Arbeitsbereichs öffnen", - "openFolderAsWorkspaceInNewWindow": "Ordner als Arbeitsbereich in neuem Fenster öffnen", - "workspaceFolderPickerPlaceholder": "Arbeitsbereichsordner auswählen" + "openFolderAsWorkspaceInNewWindow": "Ordner als Arbeitsbereich in neuem Fenster öffnen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/deu/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..60a543c8bba --- /dev/null +++ b/i18n/deu/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Ordner zum Arbeitsbereich hinzufügen...", + "add": "&&Hinzufügen", + "addFolderToWorkspaceTitle": "Ordner zum Arbeitsbereich hinzufügen", + "workspaceFolderPickerPlaceholder": "Arbeitsbereichsordner auswählen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 0812b9299a4..95de712113e 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,17 @@ "groupThreePicker": "Editoren in dritter Gruppe anzeigen", "allEditorsPicker": "Alle geöffneten Editoren anzeigen", "view": "Anzeigen", - "file": "Datei" + "file": "Datei", + "close": "Schließen", + "closeOthers": "Andere schließen", + "closeRight": "Rechts schließen", + "closeAllUnmodified": "Nicht geänderte schließen", + "closeAll": "Alle schließen", + "keepOpen": "Geöffnet lassen", + "showOpenedEditors": "Geöffnete Editoren anzeigen", + "keepEditor": "Editor beibehalten", + "closeEditorsInGroup": "Alle Editoren in der Gruppe schließen", + "closeUnmodifiedEditors": "Nicht geänderte Editoren in der Gruppe schließen", + "closeOtherEditors": "Andere Editoren schließen", + "closeRightEditors": "Editoren rechts schließen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index eea7eefe298..f94ad3ec09a 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Editor schließen", "revertAndCloseActiveEditor": "Wiederherstellen und Editor schließen", "closeEditorsToTheLeft": "Editoren links schließen", - "closeEditorsToTheRight": "Editoren rechts schließen", "closeAllEditors": "Alle Editoren schließen", - "closeUnmodifiedEditors": "Nicht geänderte Editoren in der Gruppe schließen", "closeEditorsInOtherGroups": "Editoren in anderen Gruppen schließen", - "closeOtherEditorsInGroup": "Andere Editoren schließen", - "closeEditorsInGroup": "Alle Editoren in der Gruppe schließen", "moveActiveGroupLeft": "Editor-Gruppe nach links verschieben", "moveActiveGroupRight": "Editor-Gruppe nach rechts verschieben", "minimizeOtherEditorGroups": "Andere Editor-Gruppen minimieren", "evenEditorGroups": "Gleichmäßige Breite der Editor-Gruppe", "maximizeEditor": "Editor-Gruppe maximieren und Randleiste ausblenden", - "keepEditor": "Editor beibehalten", "openNextEditor": "Nächsten Editor öffnen", "openPreviousEditor": "Vorherigen Editor öffnen", "nextEditorInGroup": "Nächsten Editor in der Gruppe öffnen", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Editoren in erster Gruppe anzeigen", "showEditorsInSecondGroup": "Editoren in zweiter Gruppe anzeigen", "showEditorsInThirdGroup": "Editoren in dritter Gruppe anzeigen", - "showEditorsInGroup": "Editoren in der Gruppe anzeigen", "showAllEditors": "Alle Editoren anzeigen", "openPreviousRecentlyUsedEditorInGroup": "Vorherigen zuletzt verwendeten Editor in der Gruppe öffnen", "openNextRecentlyUsedEditorInGroup": "Nächsten zuletzt verwendeten Editor in der Gruppe öffnen", diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 2b4ef55801b..9080d3ad0fb 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Aktiven Editor nach Tabstopps oder Gruppen verschieben", "editorCommand.activeEditorMove.arg.name": "Argument zum Verschieben des aktiven Editors", - "editorCommand.activeEditorMove.arg.description": "Argumenteigenschaften:\n\t* \"to\": Ein Zeichenfolgenwert, der das Ziel des Verschiebungsvorgangs angibt.\n\t* \"by\": Ein Zeichenfolgenwert, der die Einheit für die Verschiebung angibt (nach Registerkarte oder nach Gruppe).\n\t* \"value\": Ein Zahlenwert, der angibt, um wie viele Positionen verschoben wird. Es kann auch die absolute Position für die Verschiebung angegeben werden.\n", - "commandDeprecated": "Der Befehl **{0}** wurde entfernt. Sie können stattdessen **{1}** verwenden.", - "openKeybindings": "Tastenkombinationen konfigurieren" + "editorCommand.activeEditorMove.arg.description": "Argumenteigenschaften:\n\t* \"to\": Ein Zeichenfolgenwert, der das Ziel des Verschiebungsvorgangs angibt.\n\t* \"by\": Ein Zeichenfolgenwert, der die Einheit für die Verschiebung angibt (nach Registerkarte oder nach Gruppe).\n\t* \"value\": Ein Zahlenwert, der angibt, um wie viele Positionen verschoben wird. Es kann auch die absolute Position für die Verschiebung angegeben werden.\n" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index f5bb0f97396..c46090d7419 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Textdateivergleichs-Editor", "navigate.next.label": "Nächste Änderung", "navigate.prev.label": "Vorherige Änderung", - "inlineDiffLabel": "Zur Inlineansicht wechseln", - "sideBySideDiffLabel": "Zur Parallelansicht wechseln" + "toggleIgnoreTrimWhitespace.label": "Keine Leerzeichen entfernen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 33a0388a647..4b868884b77 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Schließen", - "closeOthers": "Andere schließen", - "closeRight": "Rechts schließen", - "closeAll": "Alle schließen", - "closeAllUnmodified": "Nicht geänderte schließen", - "keepOpen": "Geöffnet lassen", - "showOpenedEditors": "Geöffnete Editoren anzeigen", "araLabelEditorActions": "Editor-Aktionen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 5618ae8213a..4697a7de886 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Nicht unterstützt]", + "userIsAdmin": "[Administrator]", + "userIsSudo": "[Superuser]", "devExtensionWindowTitlePrefix": "[Erweiterungsentwicklungshost]" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/deu/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index 147a1680ae9..8b6ad71cd4e 100644 --- a/i18n/deu/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/deu/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -3,6 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. -{ - "hideView": "Auf Randleiste ausblenden" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/common/theme.i18n.json b/i18n/deu/src/vs/workbench/common/theme.i18n.json index 4336f732bee..56819e7b1df 100644 --- a/i18n/deu/src/vs/workbench/common/theme.i18n.json +++ b/i18n/deu/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "Hintergrundfarbe der aktiven Registerkarte. Registerkarten sind die Container für Editors im Editorbereich. In einer Editorgruppe können mehrere Registerkarten geöffnet werden. Mehrere Editorgruppen können vorhanden sein.", "tabInactiveBackground": "Hintergrundfarbe der inaktiven Registerkarte. Registerkarten sind die Container für Editors im Editorbereich. In einer Editorgruppe können mehrere Registerkarten geöffnet werden. Mehrere Editorgruppen können vorhanden sein.", + "tabHoverBackground": "Hintergrundfarbe der Registerkarte beim Daraufzeigen. Registerkarten sind die Container für Editoren im Editorbereich. In einer Editorgruppe können mehrere Registerkarten geöffnet werden. Mehrere Editorgruppen können vorhanden sein.", + "tabUnfocusedHoverBackground": "Hintergrundfarbe für Registerkarten in einer unfokussierten Gruppe beim Daraufzeigen. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", "tabBorder": "Rahmen zum Trennen von Registerkarten. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", "tabActiveBorder": "Rahmen zum Hervorheben aktiver Registerkarten. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", "tabActiveUnfocusedBorder": "Rahmen zum Hervorheben aktiver Registerkarten in einer unfokussierten Gruppe. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", + "tabHoverBorder": "Rahmen zum Hervorheben von Registerkarten beim Daraufzeigen. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", + "tabUnfocusedHoverBorder": "Rahmen zum Hervorheben von Registerkarten in einer unfokussierten Gruppe beim Daraufzeigen. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", "tabActiveForeground": "Vordergrundfarbe der aktiven Registerkarte in einer aktiven Gruppe. Registerkarten sind die Container für Editors im Editorbereich. In einer Editorgruppe können mehrere Registerkarten geöffnet werden. Mehrere Editorgruppen können vorhanden sein.", "tabInactiveForeground": "Vordergrundfarbe der inaktiven Registerkarte in einer aktiven Gruppe. Registerkarten sind die Container für Editors im Editorbereich. In einer Editorgruppe können mehrere Registerkarten geöffnet werden. Mehrere Editorgruppen können vorhanden sein.", "tabUnfocusedActiveForeground": "Vordergrundfarbe für aktive Registerkarten in einer unfokussierten Gruppe. Registerkarten sind die Container für Editoren im Editor-Bereich. In einer Editor-Gruppe können mehrere Registerkarten geöffnet werden. Mehrere Editor-Gruppen sind möglich.", @@ -16,7 +20,7 @@ "editorGroupBackground": "Hintergrundfarbe einer Editor-Gruppe. Editor-Gruppen sind die Container der Editoren. Die Hintergrundfarbe wird beim Ziehen von Editoren angezeigt.", "tabsContainerBackground": "Hintergrundfarbe der Titelüberschrift der Editor-Gruppe, wenn die Registerkarten deaktiviert sind. Editor-Gruppen sind die Container der Editoren.", "tabsContainerBorder": "Rahmenfarbe der Titelüberschrift der Editor-Gruppe, wenn die Registerkarten deaktiviert sind. Editor-Gruppen sind die Container der Editoren.", - "editorGroupHeaderBackground": "Hintergrundfarbe der Titelüberschrift des Editors, wenn die Registerkarten deaktiviert sind. Editor-Gruppen sind die Container der Editoren.", + "editorGroupHeaderBackground": "Hintergrundfarbe der Editorgruppen-Titelüberschrift, wenn Registerkarten deaktiviert sind (`\"workbench.editor.showTabs\": false`). Editor-Gruppen sind die Container für Editoren.", "editorGroupBorder": "Farbe zum Trennen mehrerer Editor-Gruppen. Editor-Gruppen sind die Container der Editoren.", "editorDragAndDropBackground": " Hintergrundfarbe beim Ziehen von Editoren. Die Farbe muss transparent sein, damit der Editor-Inhalt noch sichtbar sind.", "panelBackground": "Hintergrundfarbe des Panels. Panels werden unter dem Editorbereich angezeigt und enthalten Ansichten wie die Ausgabe und das integrierte Terminal.", @@ -33,8 +37,6 @@ "statusBarNoFolderBorder": "Rahmenfarbe der Statusleiste zur Abtrennung von der Randleiste und dem Editor, wenn kein Ordner geöffnet ist. Die Statusleiste wird unten im Fenster angezeigt.", "statusBarItemActiveBackground": "Hintergrundfarbe für Statusleistenelemente beim Klicken. Die Statusleiste wird am unteren Rand des Fensters angezeigt.", "statusBarItemHoverBackground": "Hintergrundfarbe der Statusleistenelemente beim Daraufzeigen. Die Statusleiste wird am unteren Seitenrand angezeigt.", - "statusBarProminentItemBackground": "Hintergrundfarbe für markante Elemente der Statusleiste. Markante Elemente sind im Vergleich zu anderen Statusleisteneinträgen hervorgehoben, um auf ihre Bedeutung hinzuweisen. Die Statusleiste wird unten im Fenster angezeigt.", - "statusBarProminentItemHoverBackground": "Hintergrundfarbe für markante Elemente der Statusleiste, wenn auf diese gezeigt wird. Markante Elemente sind im Vergleich zu anderen Statusleisteneinträgen hervorgehoben, um auf ihre Bedeutung hinzuweisen. Die Statusleiste wird unten im Fenster angezeigt.", "activityBarBackground": "Hintergrundfarbe der Aktivitätsleiste. Die Aktivitätsleiste wird ganz links oder rechts angezeigt und ermöglicht das Wechseln zwischen verschiedenen Ansichten der Seitenleiste.", "activityBarForeground": "Vordergrundfarbe der Aktivitätsleiste (z. B. für Symbole). Die Aktivitätsleiste wird ganz links oder rechts angezeigt und ermöglicht das Wechseln zwischen verschiedenen Ansichten der Seitenleiste.", "activityBarBorder": "Rahmenfarbe der Aktivitätsleiste für die Abtrennung von der Seitenleiste. Die Aktivitätsleiste wird ganz links oder rechts angezeigt und ermöglicht das Wechseln zwischen verschiedenen Ansichten der Seitenleiste.", diff --git a/i18n/deu/src/vs/workbench/common/views.i18n.json b/i18n/deu/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..a36d97eb0e0 --- /dev/null +++ b/i18n/deu/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Eine Ansicht mit der ID \"{0}\" ist am Speicherort \"{1}\" bereits registriert." +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json index 7331216a594..4f7255a9d91 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Editor schließen", "closeWindow": "Fenster schließen", "closeWorkspace": "Arbeitsbereich schließen", "noWorkspaceOpened": "Zurzeit ist kein Arbeitsbereich in dieser Instanz geöffnet, der geschlossen werden kann.", @@ -52,21 +51,5 @@ "displayLanguage": "Definiert die Anzeigesprache von VSCode.", "doc": "Unter {0} finden Sie eine Liste der unterstützten Sprachen.", "restart": "Das Ändern dieses Wertes erfordert einen Neustart von VSCode.", - "fail.createSettings": "{0} ({1}) kann nicht erstellt werden.", - "openLogsFolder": "Protokollordner öffnen", - "showLogs": "Protokolle anzeigen...", - "mainProcess": "Main", - "sharedProcess": "Geteilt", - "rendererProcess": "Renderer", - "extensionHost": "Erweiterungshost", - "selectProcess": "Prozess auswählen", - "setLogLevel": "Protokollstufe festlegen", - "trace": "Spur", - "debug": "Debuggen", - "info": "Info", - "warn": "Warnung", - "err": "Fehler", - "critical": "Kritisch", - "off": "Aus", - "selectLogLevel": "Protokollstufe auswählen" + "fail.createSettings": "{0} ({1}) kann nicht erstellt werden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json index 2a2af0f320b..aba53ab9214 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Anzeigen", "help": "Hilfe", "file": "Datei", - "developer": "Entwickler", "workspaces": "Arbeitsbereiche", + "developer": "Entwickler", + "workbenchConfigurationTitle": "Workbench", "showEditorTabs": "Steuert, ob geöffnete Editoren auf Registerkarten angezeigt werden sollen.", "workbench.editor.labelFormat.default": "Zeigt den Namen der Datei. Wenn Registerkarten aktiviert sind und zwei Dateien in einer Gruppe den gleichen Namen haben, werden die unterscheidenden Abschnitte der Pfade jeder Datei hinzugefügt. Wenn die Registerkarten deaktiviert sind, wird der Pfad relativ zum Arbeitsbereich-Ordner angezeigt, wenn der Editor aktiv ist. ", "workbench.editor.labelFormat.short": "Den Namen der Datei anzeigen, gefolgt von dessen Verzeichnisnamen.", @@ -20,23 +21,23 @@ "showIcons": "Steuert, ob geöffnete Editoren mit einem Symbol angezeigt werden sollen. Hierzu muss auch ein Symboldesign aktiviert werden.", "enablePreview": "Steuert, ob geöffnete Editoren als Vorschau angezeigt werden. Vorschau-Editoren werden wiederverwendet, bis sie gespeichert werden (z. B. über Doppelklicken oder Bearbeiten), und sie werden mit kursivem Schriftschnitt angezeigt.", "enablePreviewFromQuickOpen": "Steuert, ob geöffnete Editoren aus Quick Open als Vorschau angezeigt werden. Vorschau-Editoren werden wiederverwendet, bis sie gespeichert werden (z. B. über Doppelklicken oder Bearbeiten).", + "closeOnFileDelete": "Steuert, ob Editoren, die eine Datei anzeigen, automatisch geschlossen werden sollen, wenn die Datei von einem anderen Prozess umbenannt oder gelöscht wird. Wenn Sie diese Option deaktivieren, bleibt der Editor bei einem solchen Ereignis als geändert offen. Bei Löschvorgängen innerhalb der Anwendung wird der Editor immer geschlossen, und geänderte Dateien werden nie geschlossen, damit Ihre Daten nicht verloren gehen.", "editorOpenPositioning": "Steuert, wo Editoren geöffnet werden. Wählen Sie \"links\" oder \"rechts\", um Editoren links oder rechts neben dem derzeit aktiven Editor zu öffnen. Wählen Sie \"erster\" oder \"letzter\", um Editoren unabhängig vom derzeit aktiven Editor zu öffnen.", "revealIfOpen": "Steuert, ob ein geöffneter Editor in einer der sichtbaren Gruppen angezeigt wird. Ist diese Option deaktiviert, wird ein Editor vorzugsweise in der aktuell aktiven Editorgruppe geöffnet. Ist diese Option aktiviert, wird ein bereits geöffneter Editor angezeigt und nicht in der aktuell aktiven Editorgruppe erneut geöffnet. In einigen Fällen wird diese Einstellung ignoriert, z. B. wenn das Öffnen eines Editors in einer bestimmten Gruppe oder neben der aktuell aktiven Gruppe erzwungen wird.", + "swipeToNavigate": "Hiermit navigieren Sie per waagrechtem Wischen mit drei Fingen zwischen geöffneten Dateien.", "commandHistory": "Steuert, ob die Anzahl zuletzt verwendeter Befehle im Verlauf für die Befehlspalette gespeichert wird. Legen Sie diese Option auf 0 fest, um den Befehlsverlauf zu deaktivieren.", "preserveInput": "Steuert, ob die letzte typisierte Eingabe in die Befehlspalette beim nächsten Öffnen wiederhergestellt wird.", "closeOnFocusLost": "Steuert, ob Quick Open automatisch geschlossen werden soll, sobald das Feature den Fokus verliert.", "openDefaultSettings": "Steuert, ob beim Öffnen der Einstellungen auch ein Editor geöffnet wird, der alle Standardeinstellungen anzeigt.", "sideBarLocation": "Steuert die Position der Seitenleiste. Diese kann entweder links oder rechts von der Workbench angezeigt werden.", + "panelDefaultLocation": "Steuert die Standardposition des Panels. Dieses kann entweder unterhalb oder rechts von der Workbench angezeigt werden.", "statusBarVisibility": "Steuert die Sichtbarkeit der Statusleiste im unteren Bereich der Workbench.", "activityBarVisibility": "Steuert die Sichtbarkeit der Aktivitätsleiste in der Workbench.", - "closeOnFileDelete": "Steuert, ob Editoren, die eine Datei anzeigen, automatisch geschlossen werden sollen, wenn die Datei von einem anderen Prozess umbenannt oder gelöscht wird. Wenn Sie diese Option deaktivieren, bleibt der Editor bei einem solchen Ereignis als geändert offen. Bei Löschvorgängen innerhalb der Anwendung wird der Editor immer geschlossen, und geänderte Dateien werden nie geschlossen, damit Ihre Daten nicht verloren gehen.", - "enableNaturalLanguageSettingsSearch": "Steuert, ob der Suchmodus mit natürlicher Sprache für die Einstellungen aktiviert werden soll.", "fontAliasing": "Steuert die Schriftartaliasingmethode in der Workbench.\n- default: Subpixel-Schriftartglättung. Auf den meisten Nicht-Retina-Displays wird Text bei dieser Einstellung am schärfsten dargestellt.\n- antialiased: Glättet die Schriftart auf der Pixelebene (im Gegensatz zur Subpixelebene). Bei dieser Einstellung kann die Schriftart insgesamt heller wirken.\n- none: Deaktiviert die Schriftartglättung. Text wird mit gezackten scharfen Kanten dargestellt.\n", "workbench.fontAliasing.default": "Subpixel-Schriftartglättung. Auf den meisten Nicht-Retina-Displays wird Text bei dieser Einstellung am schärfsten dargestellt.", "workbench.fontAliasing.antialiased": "Glättet die Schriftart auf der Pixelebene (im Gegensatz zur Subpixelebene). Bei dieser Einstellung kann die Schriftart insgesamt heller wirken.", "workbench.fontAliasing.none": "Deaktiviert die Schriftartglättung. Text wird mit gezackten scharfen Kanten dargestellt.", - "swipeToNavigate": "Hiermit navigieren Sie per waagrechtem Wischen mit drei Fingen zwischen geöffneten Dateien.", - "workbenchConfigurationTitle": "Workbench", + "enableNaturalLanguageSettingsSearch": "Steuert, ob der Suchmodus mit natürlicher Sprache für die Einstellungen aktiviert werden soll.", "windowConfigurationTitle": "Fenster", "window.openFilesInNewWindow.on": "Dateien werden in einem neuen Fenster geöffnet.", "window.openFilesInNewWindow.off": "Dateien werden im Fenster mit dem geöffneten Dateiordner oder im letzten aktiven Fenster geöffnet.", diff --git a/i18n/deu/src/vs/workbench/electron-browser/window.i18n.json b/i18n/deu/src/vs/workbench/electron-browser/window.i18n.json index dac54eb81af..ea9b198df1d 100644 --- a/i18n/deu/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/deu/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Ausschneiden", "copy": "Kopieren", "paste": "Einfügen", - "selectAll": "Alles auswählen" + "selectAll": "Alles auswählen", + "runningAsRoot": "Es wird nicht empfohlen, {0} als Root-Benutzer auszuführen." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index e3b17702d86..adbe0beedd6 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "Hintergrundfarbe der Debug-Symbolleiste." + "debugToolBarBackground": "Hintergrundfarbe der Debug-Symbolleiste.", + "debugToolBarBorder": "Rahmenfarbe der Debug-Symbolleiste." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 1c098b69622..6cfd4e91479 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "JSON-Schemakonfigurationen zum Überprüfen von \"launch.json\".", "vscode.extension.contributes.debuggers.windows": "Windows-spezifische Einstellungen.", "vscode.extension.contributes.debuggers.windows.runtime": "Die für Windows verwendete Laufzeit.", - "vscode.extension.contributes.debuggers.osx": "OS X-spezifische Einstellungen.", - "vscode.extension.contributes.debuggers.osx.runtime": "Die für OS X verwendete Laufzeit.", "vscode.extension.contributes.debuggers.linux": "Linux-spezifische Einstellungen.", "vscode.extension.contributes.debuggers.linux.runtime": "Die für Linux verwendete Laufzeit.", "vscode.extension.contributes.breakpoints": "Trägt Haltepunkte bei.", diff --git a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 3352485c42b..23af77e5fa7 100644 --- a/i18n/deu/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "Zu debuggende Komponente", - "debug.terminal.not.available.error": "Integriertes Terminal nicht verfügbar" + "debug.terminal.title": "Zu debuggende Komponente" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 0b10a031064..6e06fdbca61 100644 --- a/i18n/deu/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Neue Eingabeaufforderung öffnen", "globalConsoleActionMacLinux": "Neues Terminal öffnen", "scopedConsoleActionWin": "In Eingabeaufforderung öffnen", - "scopedConsoleActionMacLinux": "In Terminal öffnen", - "openFolderInIntegratedTerminal": "In Terminal öffnen" + "scopedConsoleActionMacLinux": "In Terminal öffnen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 9cde3634e76..8ece38ff002 100644 --- a/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Ausgehend von den kürzlich geöffneten Dateien wird diese Erweiterung empfohlen.", + "neverShowAgain": "Nicht mehr anzeigen", + "close": "Schließen", "workspaceRecommendation": "Diese Erweiterung wird von Benutzern des aktuellen Arbeitsbereichs empfohlen.", + "fileBasedRecommendation": "Ausgehend von den kürzlich geöffneten Dateien wird diese Erweiterung empfohlen.", "exeBasedRecommendation": "Diese Erweiterung wird empfohlen, da Sie {0} installiert haben.", "reallyRecommended2": "Für diesen Dateityp wird die Erweiterung \"{0}\" empfohlen.", "reallyRecommendedExtensionPack": "Für diesen Dateityp wird das Erweiterungspaket \"{0}\" empfohlen.", "showRecommendations": "Empfehlungen anzeigen", "install": "Installieren", - "neverShowAgain": "Nicht mehr anzeigen", - "close": "Schließen", "workspaceRecommended": "Für diesen Arbeitsbereich sind Erweiterungsempfehlungen verfügbar.", "installAll": "Alle installieren", "ignoreExtensionRecommendations": "Möchten Sie alle Erweiterungsempfehlungen ignorieren?", diff --git a/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..b9d7e353c74 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Workbench" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 46de1e8541a..f77129048a6 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,25 @@ "filesCategory": "Datei", "revealInSideBar": "In Seitenleiste anzeigen", "acceptLocalChanges": "Änderungen verwenden und Datenträgerinhalte überschreiben", - "revertLocalChanges": "Änderungen verwerfen und Datenträgerinhalte wiederherstellen" + "revertLocalChanges": "Änderungen verwerfen und Datenträgerinhalte wiederherstellen", + "copyPathOfActive": "Pfad der aktiven Datei kopieren", + "saveAllInGroup": "Alle in der Gruppe speichern", + "saveFiles": "Alle Dateien speichern", + "revert": "Datei wiederherstellen", + "compareActiveWithSaved": "Aktive Datei mit gespeicherter Datei vergleichen", + "closeEditor": "Editor schließen", + "view": "Anzeigen", + "openToSide": "Zur Seite öffnen", + "revealInWindows": "Im Explorer anzeigen", + "revealInMac": "Im Finder anzeigen", + "openContainer": "Enthaltenden Ordner öffnen", + "copyPath": "Pfad kopieren", + "saveAll": "Alle speichern", + "compareWithSaved": "Mit gespeicherter Datei vergleichen", + "compareSource": "Für Vergleich auswählen", + "close": "Schließen", + "closeOthers": "Andere schließen", + "closeUnmodified": "Nicht geänderte schließen", + "closeAll": "Alle schließen", + "deleteFile": "Endgültig löschen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 4d300a15634..3e34e541dce 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Wiederholen", - "rename": "Umbenennen", "newFile": "Neue Datei", "newFolder": "Neuer Ordner", + "rename": "Umbenennen", + "delete": "Löschen", + "copyFile": "Kopieren", + "pasteFile": "Einfügen", + "retry": "Wiederholen", "openFolderFirst": "Öffnet zuerst einen Ordner, in dem Dateien oder Ordner erstellt werden.", "newUntitledFile": "Neue unbenannte Datei", "createNewFile": "Neue Datei", @@ -28,26 +31,14 @@ "confirmDeleteMessageFile": "Möchten Sie \"{0}\" wirklich endgültig löschen?", "irreversible": "Diese Aktion kann nicht rückgängig gemacht werden.", "permDelete": "Endgültig löschen", - "delete": "Löschen", "importFiles": "Dateien importieren", "confirmOverwrite": "Im Zielordner ist bereits eine Datei oder ein Ordner mit dem gleichen Namen vorhanden. Möchten Sie sie bzw. ihn ersetzen?", "replaceButtonLabel": "&&Ersetzen", - "copyFile": "Kopieren", - "pasteFile": "Einfügen", "duplicateFile": "Duplikat", - "openToSide": "Zur Seite öffnen", - "compareSource": "Für Vergleich auswählen", "globalCompareFile": "Aktive Datei vergleichen mit...", "openFileToCompare": "Zuerst eine Datei öffnen, um diese mit einer anderen Datei zu vergleichen", - "compareWith": "'{0}' mit '{1}' vergleichen", - "compareFiles": "Dateien vergleichen", "refresh": "Aktualisieren", - "save": "Speichern", - "saveAs": "Speichern unter...", - "saveAll": "Alle speichern", "saveAllInGroup": "Alle in der Gruppe speichern", - "saveFiles": "Alle Dateien speichern", - "revert": "Datei wiederherstellen", "focusOpenEditors": "Fokus auf Ansicht \"Geöffnete Editoren\"", "focusFilesExplorer": "Fokus auf Datei-Explorer", "showInExplorer": "Aktive Datei in Seitenleiste anzeigen", @@ -56,20 +47,11 @@ "refreshExplorer": "Explorer aktualisieren", "openFileInNewWindow": "Aktive Datei in neuem Fenster öffnen", "openFileToShowInNewWindow": "Datei zuerst öffnen, um sie in einem neuen Fenster zu öffnen", - "revealInWindows": "Im Explorer anzeigen", - "revealInMac": "Im Finder anzeigen", - "openContainer": "Enthaltenden Ordner öffnen", - "revealActiveFileInWindows": "Aktive Datei im Windows-Explorer anzeigen", - "revealActiveFileInMac": "Aktive Datei im Finder anzeigen", - "openActiveFileContainer": "Enthaltenden Ordner der aktiven Datei öffnen", "copyPath": "Pfad kopieren", - "copyPathOfActive": "Pfad der aktiven Datei kopieren", "emptyFileNameError": "Es muss ein Datei- oder Ordnername angegeben werden.", "fileNameExistsError": "Eine Datei oder ein Ordner **{0}** ist an diesem Ort bereits vorhanden. Wählen Sie einen anderen Namen.", "invalidFileNameError": "Der Name **{0}** ist als Datei- oder Ordnername ungültig. Bitte wählen Sie einen anderen Namen aus.", "filePathTooLongError": "Der Name **{0}** führt zu einem Pfad, der zu lang ist. Wählen Sie einen kürzeren Namen.", - "compareWithSaved": "Aktive Datei mit gespeicherter Datei vergleichen", - "modifiedLabel": "{0} (auf Datenträger) ↔ {1}", "compareWithClipboard": "Aktive Datei mit Zwischenablage vergleichen", "clipboardComparisonLabel": "Zwischenablage ↔ {0}" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index c248ffc5682..4113e1a3018 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Datei zuerst öffnen, um ihren Pfad zu kopieren", - "openFileToReveal": "Datei zuerst öffnen, um sie anzuzeigen" + "revealInWindows": "Im Explorer anzeigen", + "revealInMac": "Im Finder anzeigen", + "openContainer": "Enthaltenden Ordner öffnen", + "saveAs": "Speichern unter...", + "save": "Speichern", + "saveAll": "Alle speichern", + "removeFolderFromWorkspace": "Ordner aus dem Arbeitsbereich entfernen", + "genericRevertError": "Fehler beim Zurücksetzen von '{0}': {1}", + "modifiedLabel": "{0} (auf Datenträger) ↔ {1}", + "openFileToReveal": "Datei zuerst öffnen, um sie anzuzeigen", + "openFileToCopy": "Datei zuerst öffnen, um ihren Pfad zu kopieren" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 00a2164ceaa..2ddf50e3ffc 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "Editor", "formatOnSave": "Hiermit wird eine Datei beim Speichern formatiert. Es muss ein Formatierer vorhanden sein, die Datei darf nicht automatisch gespeichert werden, und der Editor darf nicht geschlossen werden.", "explorerConfigurationTitle": "Datei-Explorer", - "openEditorsVisible": "Die Anzahl der Editoren, die im Bereich \"Geöffnete Editoren\" angezeigt werden. Legen Sie diesen Wert auf 0 fest, um den Bereich auszublenden.", - "dynamicHeight": "Steuert, ob sich die Höhe des Abschnitts \"Geöffnete Editoren\" dynamisch an die Anzahl der Elemente anpassen soll.", "autoReveal": "Steuert, ob der Explorer Dateien beim Öffnen automatisch anzeigen und auswählen soll.", "enableDragAndDrop": "Steuert, ob der Explorer das Verschieben von Dateien und Ordnern mithilfe von Drag Drop zulassen soll.", "confirmDragAndDrop": "Steuert, ob der Explorer um Bestätigung bittet, um Dateien und Ordner per Drag & Drop zu verschieben.", diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 55ed6344bee..25a34e50d39 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Verwenden Sie die Aktionen auf der Editor-Symbolleiste auf der rechten Seite, um Ihre Änderungen **rückgängig zu machen** oder den Inhalt auf dem Datenträger mit Ihren Änderungen zu **überschreiben**.", - "discard": "Verwerfen", + "overwriteElevated": "Als Admin überschreiben...", + "saveElevated": "Als Admin wiederholen...", "overwrite": "Überschreiben", "retry": "Wiederholen", - "readonlySaveError": "Fehler beim Speichern von \"{0}\": Die Datei ist schreibgeschützt. Wählen Sie 'Überschreiben' aus, um den Schutz aufzuheben.", + "discard": "Verwerfen", + "readonlySaveErrorAdmin": "Fehler beim Speichern von '{0}': Datei ist schreibgeschützt. 'Als Admin überschreiben' auswählen, um den Vorgang als Administrator zu wiederholen. ", + "readonlySaveError": "Fehler beim Speichern von '{0}': Datei ist schreibgeschützt. Wählen Sie 'Überschreiben' aus, um den Schutz aufzuheben.", + "permissionDeniedSaveError": "Fehler beim Speichern von '{0}': Unzureichende Zugriffsrechte. Wählen Sie 'Als Admin wiederholen' aus, um den Vorgang als Admin zu wiederholen.", "genericSaveError": "Fehler beim Speichern von \"{0}\": {1}.", "staleSaveError": "Fehler beim Speichern von \"{0}\": Der Inhalt auf dem Datenträger ist neuer. Klicken Sie auf **Vergleichen**, um Ihre Version mit der Version auf dem Datenträger zu vergleichen.", "compareChanges": "Vergleichen", diff --git a/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index a5003c84539..41368e44e5a 100644 --- a/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Geöffnete Editoren", "openEditosrSection": "Abschnitt \"Geöffnete Editoren\"", - "dirtyCounter": "{0} nicht gespeichert", - "saveAll": "Alle speichern", - "closeAllUnmodified": "Nicht geänderte schließen", - "closeAll": "Alle schließen", - "compareWithSaved": "Mit gespeicherter Datei vergleichen", - "close": "Schließen", - "closeOthers": "Andere schließen" + "dirtyCounter": "{0} nicht gespeichert" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..9ef6f12276a --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "developer": "Entwickler" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..2a19c259b0d --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Protokollordner öffnen", + "showLogs": "Protokolle anzeigen...", + "rendererProcess": "Fenster", + "extensionHost": "Erweiterungshost", + "setLogLevel": "Protokollstufe festlegen", + "debug": "Debuggen", + "info": "Info", + "warn": "Warnung", + "err": "Fehler", + "critical": "Kritisch", + "off": "Aus", + "selectLogLevel": "Protokollstufe auswählen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/deu/src/vs/workbench/parts/markers/common/messages.i18n.json index f9df98f6f17..4fe33d4fdf6 100644 --- a/i18n/deu/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Anzeigen", - "problems.view.toggle.label": "Probleme umschalten", - "problems.view.focus.label": "Probleme fokussieren", "problems.panel.configuration.title": "Ansicht \"Probleme\"", "problems.panel.configuration.autoreveal": "Steuert, ob die Ansicht \"Probleme\" automatisch Dateien anzeigen sollte, wenn diese geöffnet werden.", "markers.panel.title.problems": "Probleme", diff --git a/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..a49f4a37242 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Ausgabe", + "viewCategory": "Anzeigen", + "clearOutput.label": "Ausgabe löschen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/deu/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..95b7cc617b7 --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - Ausgabe", + "channel": "Ausgabekanal für '{0}'" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 26e5d28d658..fb9b2bd366a 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Testen Sie das Suchen mit natürlicher Sprache!", "defaultSettings": "Platzieren Sie Ihre Einstellungen zum Überschreiben im Editor auf der rechten Seite.", "noSettingsFound": "Keine Einstellungen gefunden.", "settingsSwitcherBarAriaLabel": "Einstellungsumschaltung", "userSettings": "Benutzereinstellungen", "workspaceSettings": "Arbeitsbereichseinstellungen", - "folderSettings": "Ordnereinstellungen", - "enableFuzzySearch": "Suchen mit natürlicher Sprache aktivieren" + "folderSettings": "Ordnereinstellungen" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/deu/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 74ffcdff9a1..f93cea2858c 100644 --- a/i18n/deu/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Am häufigsten verwendet", - "mostRelevant": "Relevantesten", "defaultKeybindingsHeader": "Überschreiben Sie Tastenzuordnungen, indem Sie sie in die Tastenzuordnungsdatei einfügen." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index f5e2daabe29..2ca5c08b0a9 100644 --- a/i18n/deu/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Anzeigen", "commandsHandlerDescriptionDefault": "Befehle anzeigen und ausführen", "gotoLineDescriptionMac": "Gehe zu Zeile", "gotoLineDescriptionWin": "Gehe zu Zeile", diff --git a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index cfb59dde790..114466fcfbf 100644 --- a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,8 @@ "toggleGitViewlet": "Git anzeigen", "source control": "Quellcodeverwaltung", "toggleSCMViewlet": "SCM anzeigen", - "view": "Anzeigen" + "view": "Anzeigen", + "scmConfigurationTitle": "SCM", + "alwaysShowProviders": "Ob der Quellcodeverwaltungsanbieter-Abschnitt immer angezeigt wird.", + "inputCounter": "Steuert die Anzeige des Eingabezählers." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 6119d2359c6..faa904ce1ab 100644 --- a/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,8 @@ { "scm providers": "Quellcodeanbieter", "hideRepository": "Ausblenden", + "commitMessageInfo": "{0} Zeichen in aktueller Zeile", + "commitMessageCountdown": "{0} Zeichen in der aktuellen Zeile verbleibend", "installAdditionalSCMProviders": "Installiere weiter SCM Provider...", "no open repo": "Es gibt keine aktiven Quellcodeanbieter.", "source control": "Quellcodeverwaltung", diff --git a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json index f4671bfc3a8..365328f0126 100644 --- a/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Vorherigen Suchbegriff anzeigen", "showSearchViewlet": "Suche anzeigen", "findInFiles": "In Dateien suchen", - "findInFilesWithSelectedText": "In Dateien mit ausgewähltem Text suchen", "replaceInFiles": "In Dateien ersetzen", - "replaceInFilesWithSelectedText": "In Dateien mit ausgewähltem Text ersetzen", "RefreshAction.label": "Aktualisieren", "CollapseDeepestExpandedLevelAction.label": "Alle zuklappen", "ClearSearchResultsAction.label": "Löschen", diff --git a/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index a765a1ac06f..0816ad37e8d 100644 --- a/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "In Ordner suchen...", + "findInWorkspace": "In Arbeitsbereich suchen...", "showTriggerActions": "Zu Symbol im Arbeitsbereich wechseln...", "name": "Suchen", "search": "Suchen", + "showSearchViewlet": "Suche anzeigen", "view": "Anzeigen", + "findInFiles": "In Dateien suchen", "openAnythingHandlerDescription": "Zu Datei wechseln", "openSymbolDescriptionNormal": "Zu Symbol im Arbeitsbereich wechseln", - "searchOutputChannelTitle": "Suchen", "searchConfigurationTitle": "Suchen", "exclude": "Konfigurieren Sie Globmuster zum Ausschließen von Dateien und Ordnern in Suchvorgängen. Alle Globmuster werden von der files.exclude-Einstellung geerbt.", "exclude.boolean": "Das Globmuster, mit dem Dateipfade verglichen werden sollen. Legen Sie diesen Wert auf \"true\" oder \"false\" fest, um das Muster zu aktivieren bzw. zu deaktivieren.", diff --git a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..fa89fddbd1a --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "Einstellungen" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 7a1c949566e..6d4c86fa94f 100644 --- a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Sprache für Codeausschnitt auswählen", - "openSnippet.errorOnCreate": "\"{0}\" kann nicht erstellt werden.", - "openSnippet.label": "Benutzercodeausschnitte öffnen", - "preferences": "Einstellungen", "snippetSchema.json.default": "Leerer Codeausschnitt", "snippetSchema.json": "Benutzerkonfiguration des Codeausschnitts", "snippetSchema.json.prefix": "Das Präfix, das beim Auswählen des Codeausschnitts in IntelliSense verwendet werden soll.", diff --git a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..3daae2bbcbd --- /dev/null +++ b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Benutzercodeausschnitt" +} \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index e67d5f89a93..f989f6698dc 100644 --- a/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Unbekannte Sprache in \"contributes.{0}.language\". Bereitgestellter Wert: {1}", "invalid.path.0": "Expected string in `contributes.{0}.path`. Provided value: {1}", + "invalid.language": "Unbekannte Sprache in \"contributes.{0}.language\". Bereitgestellter Wert: {1}", "invalid.path.1": "Es wurde erwartet, dass \"contributes.{0}.path\" ({1}) im Ordner ({2}) der Erweiterung enthalten ist. Dies führt ggf. dazu, dass die Erweiterung nicht portierbar ist.", "vscode.extension.contributes.snippets": "Trägt Codeausschnitte bei.", "vscode.extension.contributes.snippets-language": "Der Sprachbezeichner, für den dieser Codeausschnitt beigetragen wird.", "vscode.extension.contributes.snippets-path": "Der Pfad der Codeausschnittdatei. Der Pfad ist relativ zum Erweiterungsordner und beginnt normalerweise mit \". /snippets/\".", "badVariableUse": "Bei mindestens einem Ausschnitt von der Erweiterung \"{0}\" sind Ausschnittsvariablen und Ausschnittsplatzhalter vertauscht (weitere Informationen finden Sie unter https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax).", "badFile": "Die Ausschnittsdatei \"{0}\" konnte nicht gelesen werden.", - "source.snippet": "Benutzercodeausschnitt", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index bc6dee18ad0..e6464f3ff18 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -14,6 +14,7 @@ "terminal.integrated.shell.windows": "Der Pfad der Shell, den das Terminal unter Windows verwendet, wenn in Windows enthaltene Terminals verwendet werden (cmd, PowerShell oder Bash unter Ubuntu).", "terminal.integrated.shellArgs.windows": "Die Befehlszeilenargumente, die im Windows-Terminal verwendet werden sollen.", "terminal.integrated.rightClickCopyPaste": "Wenn dies festgelegt ist, erscheint das Kontextmenü bei einem Rechtsklick im Terminal nicht mehr. Stattdessen erfolgen die Vorgänge Kopieren, wenn eine Auswahl vorgenommen wurde, sowie Einfügen, wenn keine Auswahl vorgenommen wurde.", + "terminal.integrated.copyOnSelection": "Wenn gesetzt, wird der im Terminal ausgewählte Text in die Zwischenablage kopiert.", "terminal.integrated.fontFamily": "Steuert die Schriftartfamilie des Terminals. Der Standardwert ist \"editor.fontFamily\".", "terminal.integrated.fontSize": "Steuert den Schriftgrad des Terminals in Pixeln.", "terminal.integrated.lineHeight": "Steuert die Zeilenhöhe für das Terminal. Dieser Wert wird mit dem Schriftgrad des Terminals multipliziert, um die tatsächliche Zeilenhöhe in Pixeln zu erhalten.", diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 93a8b04286a..edacb0183b5 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -14,6 +14,8 @@ "workbench.action.terminal.deleteWordRight": "Wort rechts löschen", "workbench.action.terminal.new": "Neues integriertes Terminal erstellen", "workbench.action.terminal.new.short": "Neues Terminal", + "workbench.action.terminal.newWorkspacePlaceholder": "Aktuelles Arbeitsverzeichnis für neues Terminal auswählen", + "workbench.action.terminal.newInActiveWorkspace": "Neues integriertes Terminal erstellen (in aktivem Arbeitsbereich)", "workbench.action.terminal.focus": "Fokus im Terminal", "workbench.action.terminal.focusNext": "Fokus im nächsten Terminal", "workbench.action.terminal.focusPrevious": "Fokus im vorherigen Terminal", diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index 76d17079ae8..35f0add77c1 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "Die Vordergrundfarbe des Terminal.", "terminalCursor.foreground": "Die Vordergrundfarbe des Terminalcursors.", "terminalCursor.background": "Die Hintergrundfarbe des Terminalcursors. Ermöglicht das Anpassen der Farbe eines Zeichens, das von einem Blockcursor überdeckt wird.", - "terminal.selectionBackground": "Die Auswahlvordergrundfarbe des Terminals.", - "terminal.ansiColor": "\"{0}\": ANSI-Farbe im Terminal" + "terminal.selectionBackground": "Die Auswahlvordergrundfarbe des Terminals." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index ac6f1dfc78c..a768c43ba81 100644 --- a/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "Sie können die Standardterminalshell über die Schaltfläche \"Anpassen\" ändern.", "customize": "Anpassen", "cancel": "Abbrechen", - "never again": "OK, nicht mehr anzeigen", "terminal.integrated.chooseWindowsShell": "Wählen Sie Ihre bevorzugte Terminalshell. Sie können diese später in Ihren Einstellungen ändern.", "terminalService.terminalCloseConfirmationSingular": "Eine aktive Terminalsitzung ist vorhanden. Möchten Sie sie beenden?", "terminalService.terminalCloseConfirmationPlural": "{0} aktive Terminalsitzungen sind vorhanden. Möchten Sie sie beenden?" diff --git a/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 7c24ef226ba..58c22d0ae12 100644 --- a/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/deu/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -13,7 +13,7 @@ "read the release notes": "Willkommen bei {0} v{1}! Möchten Sie die Hinweise zu dieser Version lesen?", "licenseChanged": "Unsere Lizenzbedingungen haben sich geändert. Bitte lesen Sie die neuen Bedingungen.", "license": "Lizenz lesen", - "neveragain": "Nie wieder anzeigen", + "neveragain": "Nicht mehr anzeigen", "64bitisavailable": "{0} für 64-Bit-Windows ist jetzt verfügbar!", "learn more": "Weitere Informationen", "updateIsReady": "Neues {0}-Update verfügbar.", @@ -23,6 +23,7 @@ "commandPalette": "Befehlspalette...", "settings": "Einstellungen", "keyboardShortcuts": "Tastenkombinationen", + "userSnippets": "Benutzercodeausschnitte", "selectTheme.label": "Farbdesign", "themes.selectIconTheme.label": "Dateisymboldesign", "not available": "Aktualisierungen nicht verfügbar", diff --git a/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index ed6cda9de2a..bf366f305f3 100644 --- a/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "Die Datei ist ein Verzeichnis", + "fileNotModifiedError": "Datei nicht geändert seit", "fileBinaryError": "Die Datei scheint eine Binärdatei zu sein und kann nicht als Text geöffnet werden." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/deu/src/vs/workbench/services/files/node/fileService.i18n.json index c16b29bce92..7f863867abd 100644 --- a/i18n/deu/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "Die Datei ist zu groß, um sie zu öffnen.", "fileNotFoundError": "Die Datei wurde nicht gefunden ({0}).", "fileBinaryError": "Die Datei scheint eine Binärdatei zu sein und kann nicht als Text geöffnet werden.", + "filePermission": "Schreibzugriff auf Datei ({0}) verweigert", "fileExists": "Die zu erstellende Datei ist bereits vorhanden ({0}). ", "fileMoveConflict": "Verschieben/Kopieren kann nicht ausgeführt werden. Die Datei ist am Ziel bereits vorhanden.", "unableToMoveCopyError": "Der Verschiebe-/Kopiervorgang kann nicht ausgeführt werden. Die Datei würde den Ordner ersetzen, in dem sie enthalten ist.", diff --git a/i18n/deu/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/deu/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index 32304e03cea..2fb3a8af237 100644 --- a/i18n/deu/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "Die Bedingung, wann der Schlüssel aktiv ist.", "keybindings.json.args": "Argumente, die an den auszuführenden Befehl übergeben werden sollen.", "keyboardConfigurationTitle": "Tastatur", - "dispatch": "Steuert die Abgangslogik, sodass bei einem Tastendruck entweder \"code\" (empfohlen) oder \"keyCode\" verwendet wird." + "dispatch": "Steuert die Abgangslogik, sodass bei einem Tastendruck entweder \"code\" (empfohlen) oder \"keyCode\" verwendet wird.", + "touchbar.enabled": "Aktiviert die macOS-Touchbar-Schaltflächen der Tastatur, sofern verfügbar." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/deu/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 1e2d38883dc..f953949ef00 100644 --- a/i18n/deu/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Möchten Sie die Änderungen speichern, die Sie an \"{0}\" vorgenommen haben?", "saveChangesMessages": "Möchten Sie die an den folgenden {0}-Dateien vorgenommenen Änderungen speichern?", - "moreFile": "...1 weitere Datei wird nicht angezeigt", - "moreFiles": "...{0} weitere Dateien werden nicht angezeigt", "saveAll": "&&Alle speichern", "save": "&&Speichern", "dontSave": "&&Nicht speichern", diff --git a/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 7d1b7fccbe0..957e2448664 100644 --- a/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Überschreibt Farben aus dem derzeit ausgewählte Farbdesign.", - "editorColors": "Überschreibt Editorfarben und den Schriftschnitt aus dem momentan ausgewählten Farbdesign.", "editorColors.comments": "Legt die Farben und Stile für Kommentare fest.", "editorColors.strings": "Legt die Farben und Stile für Zeichenfolgenliterale fest.", "editorColors.keywords": "Legt die Farben und Stile für Schlüsselwörter fest.", @@ -19,5 +18,6 @@ "editorColors.types": "Legt die Farben und Stile für Typdeklarationen und Verweise fest.", "editorColors.functions": "Legt die Farben und Stile für Funktionsdeklarationen und Verweise fest.", "editorColors.variables": "Legt die Farben und Stile für Variablendeklarationen und Verweise fest.", - "editorColors.textMateRules": "Legt Farben und Stile mithilfe von Textmate-Designregeln fest (erweitert)." + "editorColors.textMateRules": "Legt Farben und Stile mithilfe von Textmate-Designregeln fest (erweitert).", + "editorColors": "Überschreibt Editorfarben und den Schriftschnitt aus dem momentan ausgewählten Farbdesign." } \ No newline at end of file diff --git a/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 67d01f0f0d4..ded36282a85 100644 --- a/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/deu/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "In die Konfigurationsdatei des Arbeitsbereichs kann nicht geschrieben werden. Öffnen Sie die Datei, um Fehler/Warnungen darin zu beheben, und versuchen Sie es noch mal.", "errorWorkspaceConfigurationFileDirty": "In die Konfigurationsdatei des Arbeitsbereichs kann nicht geschrieben werden, weil sie geändert wurde. Speichern Sie die Datei, und versuchen Sie es noch mal.", "openWorkspaceConfigurationFile": "Konfigurationsdatei des Arbeitsbereichs öffnen", - "close": "Schließen", - "enterWorkspace.close": "Schließen", - "enterWorkspace.dontShowAgain": "Nicht mehr anzeigen", - "enterWorkspace.moreInfo": "Weitere Informationen", - "enterWorkspace.prompt": "Weitere Informationen zum Arbeiten mit mehreren Ordnern in VS Code." + "close": "Schließen" } \ No newline at end of file diff --git a/i18n/esn/extensions/git/out/autofetch.i18n.json b/i18n/esn/extensions/git/out/autofetch.i18n.json index 270030fe345..2e2bb63e461 100644 --- a/i18n/esn/extensions/git/out/autofetch.i18n.json +++ b/i18n/esn/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Sí", + "read more": "Leer más", "no": "No", - "not now": "Ahora No", - "suggest auto fetch": "¿Desea habilitar la búsqueda automática de repositorios de Git?" + "not now": "Preguntarme luego", + "suggest auto fetch": "Te gustaría que Code ejecute `git fetch` periódicamente?" } \ No newline at end of file diff --git a/i18n/esn/extensions/git/out/commands.i18n.json b/i18n/esn/extensions/git/out/commands.i18n.json index 2258e175547..9a3ea98e470 100644 --- a/i18n/esn/extensions/git/out/commands.i18n.json +++ b/i18n/esn/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nEsta acción es IRREVERSIBLE. Su espacio de trabajo actual SE PERDERÁ PARA SIEMPRE.", "yes discard tracked": "Descartar un archivo con seguimiento", "yes discard tracked multiple": "Descartar {0} archivos con seguimiento", + "unsaved files single": "El siguiente archivo no está guardado: {0}.\n¿Desea guardarlo antes de confirmarlo? ", + "unsaved files": "Hay {0} archivos sin guardar.\n¿Desea guardarlos antes de confirmar?", + "save and commit": "Guardar todo y confirmar", + "commit": "Confirmar de todas formas", "no staged changes": "No hay elementos almacenados provisionalmente.\n\n¿Desea almacenar de forma provisional todos sus cambios y confirmarlos directamente?", "always": "Siempre", "no changes": "No hay cambios para confirmar.", @@ -64,12 +68,12 @@ "no remotes to pull": "El repositorio no tiene remotos configurados de los que extraer.", "pick remote pull repo": "Seleccione un origen remoto desde el que extraer la rama", "no remotes to push": "El repositorio no tiene remotos configurados en los que insertar.", - "push with tags success": "Insertado con etiquetas correctamente.", "nobranch": "Extraiga del repositorio una rama para insertar un remoto.", + "ok": "Aceptar", + "push with tags success": "Insertado con etiquetas correctamente.", "pick remote": "Seleccionar un elemento remoto para publicar la rama '{0}':", "sync is unpredictable": "Esta acción insertará y extraerá confirmaciones en '{0}'.", - "ok": "Aceptar", - "never again": "De acuerdo, no volver a mostrar este mensaje.", + "never again": "No volver a mostrar", "no remotes to publish": "El repositorio no tiene remotos configurados en los que publicar.", "no changes stash": "No existen cambios para el guardado provisional.", "provide stash message": "Opcionalmente, proporcionar un mensaje para el guardado provisional", diff --git a/i18n/esn/extensions/git/package.i18n.json b/i18n/esn/extensions/git/package.i18n.json index c0bb492d13e..71eed7035ea 100644 --- a/i18n/esn/extensions/git/package.i18n.json +++ b/i18n/esn/extensions/git/package.i18n.json @@ -54,6 +54,7 @@ "command.stashPopLatest": "Aplicar y quitar últimos cambios guardados provisionalmente...", "config.enabled": "Si GIT está habilitado", "config.path": "Ruta de acceso del ejecutable de GIT", + "config.autoRepositoryDetection": "Si se deben detectar automáticamente los repositories ", "config.autorefresh": "Indica si la actualización automática está habilitada", "config.autofetch": "Si la búsqueda automática está habilitada", "config.enableLongCommitWarning": "Si se debe advertir sobre los mensajes de confirmación largos", @@ -72,5 +73,6 @@ "colors.deleted": "Color para los recursos eliminados.", "colors.untracked": "Color para los recursos a los que no se les hace seguimiento.", "colors.ignored": "Color para los recursos ignorados.", - "colors.conflict": "Color para los recursos con conflictos." + "colors.conflict": "Color para los recursos con conflictos.", + "colors.submodule": "Color para los recursos de submódulos." } \ No newline at end of file diff --git a/i18n/esn/extensions/typescript/out/commands.i18n.json b/i18n/esn/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..cfccf2b7bf9 --- /dev/null +++ b/i18n/esn/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Abra una carpeta en VS Code para usar un proyecto de TypeScript o JavaScript", + "typescript.projectConfigUnsupportedFile": "No se pudo determinar el proyecto de TypeScript o JavaScript. Tipo de archivo no compatible", + "typescript.projectConfigCouldNotGetInfo": "No se pudo determinar el proyecto de TypeScript o JavaScript", + "typescript.noTypeScriptProjectConfig": "El archivo no forma parte de un proyecto de TypeScript", + "typescript.noJavaScriptProjectConfig": "El archivo no forma parte de un proyecto de JavaScript", + "typescript.configureTsconfigQuickPick": "Configurar tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurar jsconfig.json", + "typescript.projectConfigLearnMore": "Más información" +} \ No newline at end of file diff --git a/i18n/esn/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/esn/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..37a369cc83b --- /dev/null +++ b/i18n/esn/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (Corregir todo en el archivo)" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/esn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/esn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/base/node/ps.i18n.json b/i18n/esn/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..a4dbd804fb4 --- /dev/null +++ b/i18n/esn/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Recopilando información de memoria y CPU. Esto puede tardar unos segundos. " +} \ No newline at end of file diff --git a/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json index 582dfe7c78f..dae6488ccb2 100644 --- a/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/esn/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Los números de línea se muestran como un número absoluto.", "lineNumbers.relative": "Los números de línea se muestran como distancia en líneas a la posición del cursor.", "lineNumbers.interval": "Los números de línea se muestran cada 10 líneas.", - "lineNumbers": "Controla la visualización de números de línea. Los valores posibles son 'on', 'off' y 'relative'.", + "lineNumbers": "Controla la visualización de números de línea. Los valores posibles son 'on', 'off', 'relative' e 'interval'.", "rulers": "Representar reglas verticales después de un cierto número de caracteres monoespacio. Usar multiples valores para multiples reglas. No se dibuja ninguna regla si la matriz esta vacía.", "wordSeparators": "Caracteres que se usarán como separadores de palabras al realizar operaciones o navegaciones relacionadas con palabras.", "tabSize": "El número de espacios a los que equivale una tabulación. Este valor se invalida según el contenido del archivo cuando `editor.detectIndentation` está activado.", @@ -40,9 +40,9 @@ "wordWrapColumn": "Controls the wrapping column of the editor when `editor.wordWrap` is 'wordWrapColumn' or 'bounded'.", "wrappingIndent": "Controla el sangrado de las líneas ajustadas. Puede ser uno los valores 'none', 'same' o 'indent'.", "mouseWheelScrollSensitivity": "Se utilizará un multiplicador en los eventos de desplazamiento de la rueda del mouse `deltaX` y `deltaY`", - "multiCursorModifier.ctrlCmd": "Se asigna a \"Control\" en Windows y Linux y a \"Comando\" en OSX.", - "multiCursorModifier.alt": "Se asigna a \"Alt\" en Windows y Linux y a \"Opción\" en OSX.", - "multiCursorModifier": "El modificador que se usará para agregar varios cursores con el mouse. \"ctrlCmd\" se asigna a \"Control\" en Windows y Linux y a \"Comando\" en OSX. Los gestos del mouse Ir a la definición y Abrir vínculo se adaptarán de modo que no entren en conflicto con el modificador multicursor.", + "multiCursorModifier.ctrlCmd": "Se asigna a \"Control\" en Windows y Linux y a \"Comando\" en macOS.", + "multiCursorModifier.alt": "Se asigna a \"Alt\" en Windows y Linux y a \"Opción\" en macOS.", + "multiCursorModifier": "El modificador que se usará para agregar varios cursores con el mouse. \"ctrlCmd\" se asigna a \"Control\" en Windows y Linux y a \"Comando\" en macOS. Los gestos del mouse \"Ir a la definición\" y \"Abrir vínculo\" se adaptarán de modo que no entren en conflicto con el modificador multicurso", "quickSuggestions.strings": "Habilita sugerencias rápidas en las cadenas.", "quickSuggestions.comments": "Habilita sugerencias rápidas en los comentarios.", "quickSuggestions.other": "Habilita sugerencias rápidas fuera de las cadenas y los comentarios.", @@ -72,6 +72,7 @@ "cursorBlinking": "Controlar el estilo de animación del cursor. Los valores posibles son \"blink\", \"smooth\", \"phase\", \"expand\" y \"solid\".", "mouseWheelZoom": "Ampliar la fuente del editor cuando se use la rueda del mouse mientras se presiona Ctrl", "cursorStyle": "Controla el estilo del cursor. Los valores aceptados son \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" y \"underline-thin\"", + "lineCursorWidth": "Controla el ancho del cursor cuando editor.cursorStyle se establece a 'line'", "fontLigatures": "Habilita las ligaduras tipográficas.", "hideCursorInOverviewRuler": "Controla si el cursor debe ocultarse en la regla de visión general.", "renderWhitespace": "Controla cómo debe representar el editor los espacios en blanco. Las posibilidades son \"none\", \"boundary\" y \"all\". La opción \"boundary\" no representa los espacios individuales entre palabras.", diff --git a/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json index 9cd43302e16..240fd1d7416 100644 --- a/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/esn/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "Color de fondo del resaltado de línea en la posición del cursor.", "lineHighlightBorderBox": "Color de fondo del borde alrededor de la línea en la posición del cursor.", - "rangeHighlight": "Color de fondo de los intervalos resaltados; por ejemplo, para Apertura Rápida y Buscar.", + "rangeHighlight": "Color de fondo de los rangos resaltados, como por ejemplo las características de abrir rápidamente y encontrar. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "caret": "Color del cursor del editor.", "editorCursorBackground": "Color de fondo del cursor de edición. Permite personalizar el color del carácter solapado por el bloque del cursor.", "editorWhitespaces": "Color de los caracteres de espacio en blanco del editor.", diff --git a/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json index a46ce2aad76..19b5ca523e8 100644 --- a/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Ir al error o la advertencia siguiente", - "markerAction.previous.label": "Ir al error o la advertencia anterior", + "markerAction.next.label": "Ir al siguiente problema (Error, Advertencia, Información)", + "markerAction.previous.label": "Ir al problema anterior (Error, Advertencia, Información)", "editorMarkerNavigationError": "Color de los errores del widget de navegación de marcadores del editor.", "editorMarkerNavigationWarning": "Color de las advertencias del widget de navegación de marcadores del editor.", "editorMarkerNavigationInfo": "Color del widget informativo marcador de navegación en el editor.", diff --git a/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index ce1db0c57f2..700a3162a41 100644 --- a/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/esn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Color de fondo de un símbolo durante el acceso de lectura; por ejemplo, cuando se lee una variable.", - "wordHighlightStrong": "Color de fondo de un símbolo durante el acceso de escritura; por ejemplo, cuando se escribe una variable.", + "wordHighlight": "Color de fondo de un símbolo durante el acceso de lectura, como leer una variable. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", + "wordHighlightStrong": "Color de fondo de un símbolo durante el acceso de escritura, como escribir en una variable. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "overviewRulerWordHighlightForeground": "Color de marcador de regla de información general para símbolos resaltados.", "overviewRulerWordHighlightStrongForeground": "Color de marcador de regla de información general para símbolos de acceso de escritura resaltados. ", "wordHighlight.next.label": "Ir al siguiente símbolo destacado", diff --git a/i18n/esn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/esn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index fc4e80ef3e4..660d6b834cb 100644 --- a/i18n/esn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/esn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}` no es un identificador de menú válido", "missing.command": "El elemento de menú hace referencia a un comando `{0}` que no está definido en la sección 'commands'.", "missing.altCommand": "El elemento de menú hace referencia a un comando alternativo `{0}` que no está definido en la sección 'commands'.", - "dupe.command": "El elemento de menú hace referencia al mismo comando que el comando predeterminado y el comando alternativo", - "nosupport.altCommand": "Actualmente, solo el grupo 'navigation' del menú 'editor/title' es compatible con los comandos alternativos" + "dupe.command": "El elemento de menú hace referencia al mismo comando que el comando predeterminado y el comando alternativo" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/environment/node/argv.i18n.json b/i18n/esn/src/vs/platform/environment/node/argv.i18n.json index 37027504432..ab77c62ca8d 100644 --- a/i18n/esn/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/esn/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,33 @@ "diff": "Comparar dos archivos entre sí.", "add": "Agregar carpetas a la última ventana activa.", "goto": "Abrir un archivo en la ruta de acceso de la línea y posición de carácter especificadas.", - "locale": "La configuración regional que se usará (por ejemplo, en-US o zh-TW).", "newWindow": "Fuerce una nueva instancia de Code.", - "performance": "Comience con el comando 'Developer: Startup Performance' habilitado.", - "prof-startup": "Ejecutar generador de perfiles de CPU durante el inicio", - "inspect-extensions": "Permitir la depuración y el perfil de las extensiones. Revisar las herramientas de desarrollador para la conexión uri.", - "inspect-brk-extensions": "Permitir la depuración y el perfil de las extensiones con el host de la extensión pausado después del inicio. Revisar las herramientas de desarrollador para la conexión uri.", "reuseWindow": "Fuerce la apertura de un archivo o carpeta en la última ventana activa.", - "userDataDir": "Especifica el directorio en que se conservan los datos de usuario; es útil cuando se ejecuta como raíz.", - "log": "Nivel de registro a utilizar. Por defecto es 'info'. Los valores permitidos son 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", - "verbose": "Imprima salidas detalladas (implica --wait).", "wait": "Espere a que los archivos sean cerrados antes de volver.", + "locale": "La configuración regional que se usará (por ejemplo, en-US o zh-TW).", + "userDataDir": "Especifica el directorio en que se conservan los datos de usuario; es útil cuando se ejecuta como raíz.", + "version": "Versión de impresión.", + "help": "Imprima el uso.", "extensionHomePath": "Establezca la ruta de acceso raíz para las extensiones.", "listExtensions": "Enumere las extensiones instaladas.", "showVersions": "Muestra las versiones de las extensiones instaladas cuando se usa --list-extension.", "installExtension": "Instala una extensión.", "uninstallExtension": "Desinstala una extensión.", "experimentalApis": "Habilita características de API propuestas para una extensión.", - "disableExtensions": "Deshabilite todas las extensiones instaladas.", - "disableGPU": "Deshabilita la aceleración de hardware de GPU.", + "verbose": "Imprima salidas detalladas (implica --wait).", + "log": "Nivel de registro a utilizar. Por defecto es 'info'. Los valores permitidos son 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Imprimir el uso del proceso y la información de diagnóstico.", - "version": "Versión de impresión.", - "help": "Imprima el uso.", + "performance": "Comience con el comando 'Developer: Startup Performance' habilitado.", + "prof-startup": "Ejecutar generador de perfiles de CPU durante el inicio", + "disableExtensions": "Deshabilite todas las extensiones instaladas.", + "inspect-extensions": "Permitir la depuración y el perfil de las extensiones. Revisar las herramientas de desarrollador para la conexión uri.", + "inspect-brk-extensions": "Permitir la depuración y el perfil de las extensiones con el host de la extensión pausado después del inicio. Revisar las herramientas de desarrollador para la conexión uri.", + "disableGPU": "Deshabilita la aceleración de hardware de GPU.", + "issue": "Notificar un problema. ", "usage": "Uso", "options": "opciones", "paths": "rutas de acceso", - "optionsUpperCase": "Opciones" + "optionsUpperCase": "Opciones", + "extensionsManagement": "Gestión de extensiones", + "troubleshooting": "Solución de problemas" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 645d8566a96..77d52783b53 100644 --- a/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/esn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Extensión no válida: package.json no es un archivo JSON.", - "restartCodeLocal": "Reinicie Code antes de volver a instalar {0}.", + "restartCode": "Reinicie Code antes de volver a instalar {0}.", "installingOutdatedExtension": "Una versión más nueva de esta extensión ya está instalada. ¿Desea anular esto con la versión anterior?", "override": "Anular", "cancel": "Cancelar", - "notFoundCompatible": "No se puede instalar porque no se encuentra la extensión '{0}' compatible con la versión actual '{1}' del VS Code.", - "quitCode": "No se puede instalar porque todavía se está ejecutando una instancia obsoleta de la extensión. Por favor, salga e inicie el VS Code antes de volver a instalarlo.\n", - "exitCode": "No se puede instalar porque todavía se está ejecutando una instancia obsoleta de la extensión. Por favor, salga e inicie VS Code antes de volver a instalarlo.", + "errorInstallingDependencies": "Error instalando dependencias. {0}", + "notFoundCompatible": "No se pueden instalar '{0}'; no hay ninguna versión disponible compatible con VS Code '{1}'. ", "notFoundCompatibleDependency": "No se puede instalar porque no se encuentra la extensión dependiente '{0}' compatible con la versión actual '{1}' del VS Code.", + "quitCode": "No se puede instalar la extensión. Por favor, salga e inicie VS Code antes de reinstalarlo. ", + "exitCode": "No se puede instalar la extensión. Por favor, salga e inicie VS Code antes de reinstalarlo. ", "uninstallDependeciesConfirmation": "¿Quiere desinstalar solo '{0}' o también sus dependencias?", "uninstallOnly": "Solo", "uninstallAll": "Todo", diff --git a/i18n/esn/src/vs/platform/list/browser/listService.i18n.json b/i18n/esn/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..f2af41d4337 --- /dev/null +++ b/i18n/esn/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Área de trabajo", + "multiSelectModifier.ctrlCmd": "Se asigna a \"Control\" en Windows y Linux y a \"Comando\" en macOS.", + "multiSelectModifier.alt": "Se asigna a \"Alt\" en Windows y Linux y a \"Opción\" en macOS." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/message/common/message.i18n.json b/i18n/esn/src/vs/platform/message/common/message.i18n.json index 9058cce900d..8e3765bff6e 100644 --- a/i18n/esn/src/vs/platform/message/common/message.i18n.json +++ b/i18n/esn/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Cerrar", "later": "Más tarde", - "cancel": "Cancelar" + "cancel": "Cancelar", + "moreFile": "...1 archivo más que no se muestra", + "moreFiles": "...{0} archivos más que no se muestran" } \ No newline at end of file diff --git a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json index 9f8669717f0..139c4515643 100644 --- a/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/esn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,8 @@ "editorWidgetBorder": "Color de borde de los widgets del editor. El color solo se usa si el widget elige tener un borde y no invalida el color.", "editorSelectionBackground": "Color de la selección del editor.", "editorSelectionForeground": "Color del texto seleccionado para alto contraste.", - "editorInactiveSelection": "Color de la selección en un editor inactivo.", - "editorSelectionHighlight": "Color de las regiones con el mismo contenido que la selección.", + "editorInactiveSelection": "Color de la selección en un editor inactivo. El color no debe ser opaco para no ocultar las decoraciones subyacentes.", "editorFindMatch": "Color de la coincidencia de búsqueda actual.", - "findMatchHighlight": "Color de las demás coincidencias de búsqueda.", - "findRangeHighlight": "Color del intervalo que limita la búsqueda.", - "hoverHighlight": "Resaltado debajo de la palabra para la que se muestra un recuadro al mantener el puntero.", "hoverBackground": "Color de fondo al mantener el puntero en el editor.", "hoverBorder": "Color del borde al mantener el puntero en el editor.", "activeLinkForeground": "Color de los vínculos activos.", @@ -76,12 +72,6 @@ "diffEditorRemoved": "Color de fondo para el texto quitado.", "diffEditorInsertedOutline": "Color de contorno para el texto insertado.", "diffEditorRemovedOutline": "Color de contorno para el texto quitado.", - "mergeCurrentHeaderBackground": "Fondo del encabezado actual en conflictos de combinación alineados.", - "mergeCurrentContentBackground": "Fondo del contenido actual en conflictos de combinación alineados.", - "mergeIncomingHeaderBackground": "Fondo del encabezado de entrada en conflictos de combinación alineados.", - "mergeIncomingContentBackground": "Fondo del contenido de entrada en conflcitos de combinación alineados.", - "mergeCommonHeaderBackground": "Fondo del encabezado de ancestros comunes en conflictos de combinación alineados.", - "mergeCommonContentBackground": "Fondo del contenido de ancestros comunes en conflictos de combinación alineados.", "mergeBorder": "Color del borde en los encabezados y el divisor en conflictos de combinación alineados.", "overviewRulerCurrentContentForeground": "Primer plano de la regla de visión general actual para conflictos de combinación alineados.", "overviewRulerIncomingContentForeground": "Primer plano de regla de visión general de entrada para conflictos de combinación alineados.", diff --git a/i18n/esn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/esn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..ab1f8a53027 --- /dev/null +++ b/i18n/esn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirearray": "las localizaciones deben ser una matriz", + "requirestring": "la propiedad `{0}` es obligatoria y debe ser de tipo \"string\"", + "optstring": "la propiedad `{0}` se puede omitir o debe ser de tipo \"string\"", + "vscode.extension.contributes.localizations.languageName": "Nombre del idioma en el que se traducen las cadenas visualizadas." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..a0da8956de3 --- /dev/null +++ b/i18n/esn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Ejecutando Guardar Participantes..." +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/esn/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 1127a4ec4f8..12c9dbb13d3 100644 --- a/i18n/esn/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/esn/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "No se ha registrado ninga vista del árbol con id '{0}'.", - "treeItem.notFound": "No se encontró ningún item del árbol con id '{0}'.", - "treeView.duplicateElement": "El elemento '{0}' ya está registrado" + "treeView.duplicateElement": "El elemento con id {0} está ya registrado" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/esn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 9caf1c7c012..ac538fe6a5b 100644 --- a/i18n/esn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Alternar la ubicación de la barra lateral", "view": "Ver" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 1e2b99a1870..9f92beb9392 100644 --- a/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Abrir archivo...", "openFolder": "Abrir carpeta...", "openFileFolder": "Abrir...", - "addFolderToWorkspace": "Agregar carpeta al área de trabajo...", - "add": "&& Agregar", - "addFolderToWorkspaceTitle": "Agregar carpeta al área de trabajo", "globalRemoveFolderFromWorkspace": "Quitar carpeta del Área de trabajo...", - "removeFolderFromWorkspace": "Quitar carpeta del área de trabajo", - "openFolderSettings": "Abrir Configuración de carpeta", "saveWorkspaceAsAction": "Guardar área de trabajo como...", "save": "&&Guardar", "saveWorkspace": "Guardar área de trabajo", "openWorkspaceAction": "Abrir área de trabajo...", "openWorkspaceConfigFile": "Abrir archivo de configuración del área de trabajo", - "openFolderAsWorkspaceInNewWindow": "Abrir carpeta como Área de trabajo en una Nueva Ventana", - "workspaceFolderPickerPlaceholder": "Seleccionar la carpeta del área de trabajo" + "openFolderAsWorkspaceInNewWindow": "Abrir carpeta como Área de trabajo en una Nueva Ventana" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/esn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..e1642a76137 --- /dev/null +++ b/i18n/esn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Agregar carpeta al área de trabajo...", + "add": "&&Añadir", + "addFolderToWorkspaceTitle": "Agregar carpeta al área de trabajo", + "workspaceFolderPickerPlaceholder": "Seleccionar la carpeta del área de trabajo" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index ae6d0079e4c..5d49307d15f 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "Mostrar editores del tercer grupo", "allEditorsPicker": "Mostrar todos los editores abiertos", "view": "Ver", - "file": "Archivo" + "file": "Archivo", + "close": "Cerrar", + "closeOthers": "Cerrar otros", + "closeRight": "Cerrar a la derecha", + "closeAllUnmodified": "Cerrar los que no se han modificado", + "closeAll": "Cerrar todo", + "keepOpen": "Mantener abierto", + "toggleInlineView": "Cambiar vista en línea", + "showOpenedEditors": "Mostrar editores abiertos", + "keepEditor": "Mantener editor", + "closeEditorsInGroup": "Cerrar todos los editores del grupo", + "closeUnmodifiedEditors": "Cerrar los editores en el grupo sin modificar", + "closeOtherEditors": "Cerrar otros editores", + "closeRightEditors": "Cerrar los editores a la derecha" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index f88c82cd9df..0063a5e42f9 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Cerrar editor", "revertAndCloseActiveEditor": "Revertir y cerrar el editor", "closeEditorsToTheLeft": "Cerrar los editores a la izquierda", - "closeEditorsToTheRight": "Cerrar los editores a la derecha", "closeAllEditors": "Cerrar todos los editores", - "closeUnmodifiedEditors": "Cerrar los editores en el grupo sin modificar", "closeEditorsInOtherGroups": "Cerrar los editores de otros grupos", - "closeOtherEditorsInGroup": "Cerrar otros editores", - "closeEditorsInGroup": "Cerrar todos los editores del grupo", "moveActiveGroupLeft": "Mover el grupo de editores a la izquierda", "moveActiveGroupRight": "Mover el grupo de editores a la derecha", "minimizeOtherEditorGroups": "Minimizar otros grupos de editores", "evenEditorGroups": "Uniformar anchos del grupo de editores", "maximizeEditor": "Maximizar el grupo de editores y ocultar la barra lateral", - "keepEditor": "Mantener editor", "openNextEditor": "Abrir el editor siguiente", "openPreviousEditor": "Abrir el editor anterior", "nextEditorInGroup": "Abrir el siguiente editor del grupo", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Mostrar editores del primer grupo", "showEditorsInSecondGroup": "Mostrar editores del segundo grupo", "showEditorsInThirdGroup": "Mostrar editores del tercer grupo", - "showEditorsInGroup": "Mostrar los editores del grupo", "showAllEditors": "Mostrar todos los editores", "openPreviousRecentlyUsedEditorInGroup": "Abrir el editor recientemente usado anterior en el grupo", "openNextRecentlyUsedEditorInGroup": "Abrir el siguiente editor recientemente usado en el grupo", @@ -54,5 +48,8 @@ "moveEditorLeft": "Mover el editor a la izquierda", "moveEditorRight": "Mover el editor a la derecha", "moveEditorToPreviousGroup": "Mover editor al grupo anterior", - "moveEditorToNextGroup": "Mover editor al grupo siguiente" + "moveEditorToNextGroup": "Mover editor al grupo siguiente", + "moveEditorToFirstGroup": "Mover el Editor al Primer Grupo", + "moveEditorToSecondGroup": "Mover el Editor al Segundo Grupo", + "moveEditorToThirdGroup": "Mover el Editor al Tercer Grupo" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index a44acd1dea7..441fc68d0e6 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Mover el editor activo por tabulaciones o grupos", "editorCommand.activeEditorMove.arg.name": "Argumento para mover el editor activo", - "editorCommand.activeEditorMove.arg.description": "Propiedades del argumento:\n * 'to': cadena de valor que proporciona dónde moverse.\n\t* 'by': cadena de valor que proporciona la unidad de medida para moverse. Por pestaña o por grupo.\n\t* 'value': valor numérico que proporciona cuantas posiciones o una posición absoluta para mover.", - "commandDeprecated": "El comando **{0}** se ha quitado. Puede usar en su lugar **{1}**", - "openKeybindings": "Configurar métodos abreviados de teclado" + "editorCommand.activeEditorMove.arg.description": "Propiedades del argumento:\n * 'to': cadena de valor que proporciona dónde moverse.\n\t* 'by': cadena de valor que proporciona la unidad de medida para moverse. Por pestaña o por grupo.\n\t* 'value': valor numérico que proporciona cuantas posiciones o una posición absoluta para mover." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index d1ec23e2db6..ce242cd2e74 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Editor de comparación de archivos de texto.", "navigate.next.label": "Cambio siguiente", "navigate.prev.label": "Cambio anterior", - "inlineDiffLabel": "Cambiar a vista alineada", - "sideBySideDiffLabel": "Cambiar a vista en paralelo" + "toggleIgnoreTrimWhitespace.label": "Ignorar espacios en blanco al principio y final" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 49c85dbc052..d7236689da9 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Cerrar", - "closeOthers": "Cerrar otros", - "closeRight": "Cerrar a la derecha", - "closeAll": "Cerrar todo", - "closeAllUnmodified": "Cerrar los no modificados", - "keepOpen": "Mantener abierto", - "showOpenedEditors": "Mostrar editores abiertos", "araLabelEditorActions": "Acciones del editor" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/esn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index e4776f8c605..e40ee5163a0 100644 --- a/i18n/esn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/esn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "Ocultar en la barra lateral" + "hideView": "Ocultar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/common/theme.i18n.json b/i18n/esn/src/vs/workbench/common/theme.i18n.json index 323cb6d934f..1f48fa2867d 100644 --- a/i18n/esn/src/vs/workbench/common/theme.i18n.json +++ b/i18n/esn/src/vs/workbench/common/theme.i18n.json @@ -16,7 +16,6 @@ "editorGroupBackground": "Color de fondo de un grupo de editores. Los grupos de editores son los contenedores de los editores. El color de fondo se ve cuando se mueven arrastrando los grupos de editores.", "tabsContainerBackground": "Color de fondo del encabezado del título del grupo de editores cuando las fichas están habilitadas. Los grupos de editores son contenedores de editores.", "tabsContainerBorder": "Color de borde del encabezado del título del grupo de editores cuando las fichas están habilitadas. Los grupos de editores son contenedores de editores.", - "editorGroupHeaderBackground": "Color de fondo del encabezado del título del grupo de editores cuando las fichas están deshabilitadas. Los grupos de editores son contenedores de editores.", "editorGroupBorder": "Color para separar varios grupos de editores entre sí. Los grupos de editores son los contenedores de los editores.", "editorDragAndDropBackground": "Color de fondo cuando se arrastran los editores. El color debería tener transparencia para que el contenido del editor pueda brillar a su través.", "panelBackground": "Color de fondo del panel. Los paneles se muestran debajo del área de editores y contienen vistas, como Salida y Terminal integrado.", @@ -33,8 +32,6 @@ "statusBarNoFolderBorder": "Color de borde de la barra de estado que separa la barra lateral y el editor cuando no hay ninguna carpeta abierta. La barra de estado se muestra en la parte inferior de la ventana.", "statusBarItemActiveBackground": "Color de fondo de un elemento de la barra de estado al hacer clic. La barra de estado se muestra en la parte inferior de la ventana.", "statusBarItemHoverBackground": "Color de fondo de un elemento de la barra de estado al mantener el puntero. La barra de estado se muestra en la parte inferior de la ventana.", - "statusBarProminentItemBackground": "Color de fondo de los elementos destacados en la barra de estado. Estos elementos sobresalen para indicar importancia. La barra de estado está ubicada en la parte inferior de la ventana.", - "statusBarProminentItemHoverBackground": "Color de fondo de los elementos destacados en la barra de estado cuando se mantiene el mouse sobre estos elementos. Estos elementos sobresalen para indicar importancia. La barra de estado está ubicada en la parte inferior de la ventana.", "activityBarBackground": "Color de fondo de la barra de actividad, que se muestra en el lado izquierdo o derecho y que permite cambiar entre diferentes vistas de la barra lateral.", "activityBarForeground": "Color de fondo de la barra de actividad (por ejemplo utilizado por los iconos). La barra de actividad muestra en el lado izquierdo o derecho y permite cambiar entre diferentes vistas de la barra lateral.", "activityBarBorder": "Color de borde de la barra de actividad que separa la barra lateral. La barra de actividad se muestra en el extremo derecho o izquierdo y permite cambiar entre las vistas de la barra lateral.", diff --git a/i18n/esn/src/vs/workbench/common/views.i18n.json b/i18n/esn/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..f22e31a7e45 --- /dev/null +++ b/i18n/esn/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Ya existe una vista registrada con el identificador '{0}' en la ubicación '{1}'" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json index 81432663720..27010729e22 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Cerrar editor", "closeWindow": "Cerrar ventana", "closeWorkspace": "Cerrar área de trabajo", "noWorkspaceOpened": "No hay ninguna área de trabajo abierta en esta instancia para cerrarla.", @@ -30,6 +29,7 @@ "openRecent": "Abrir Reciente...", "quickOpenRecent": "Abrir Reciente Rapidamente...", "closeMessages": "Cerrar mensajes de notificación", + "openIssueReporter": "Abrir Reportador de Problemas", "reportIssueInEnglish": "Notificar problema", "reportPerformanceIssue": "Notificar problema de rendimiento", "keybindingsReference": "Referencia de métodos abreviados de teclado", @@ -52,21 +52,5 @@ "displayLanguage": "Define el lenguaje para mostrar de VSCode.", "doc": "Consulte {0} para obtener una lista de idiomas compatibles.", "restart": "Al cambiar el valor se requiere reiniciar VSCode.", - "fail.createSettings": "No se puede crear '{0}' ({1}).", - "openLogsFolder": "Abrir carpeta de registros", - "showLogs": "Mostrar registros...", - "mainProcess": "Principal", - "sharedProcess": "Compartido", - "rendererProcess": "Renderizador", - "extensionHost": "Host de extensión", - "selectProcess": "Seleccionar proceso", - "setLogLevel": "Establecer nivel de registro", - "trace": "Seguimiento", - "debug": "Depurar", - "info": "Información", - "warn": "Advertencia", - "err": "Error", - "critical": "Crítico", - "off": "Apagado", - "selectLogLevel": "Seleccione el nivel de registro" + "fail.createSettings": "No se puede crear '{0}' ({1})." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json index f2abdd8deaf..dd5456c4e0f 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Ver", "help": "Ayuda", "file": "Archivo", - "developer": "Desarrollador", "workspaces": "Áreas de trabajo", + "developer": "Desarrollador", + "workbenchConfigurationTitle": "Área de trabajo", "showEditorTabs": "Controla si los editores abiertos se deben mostrar o no en pestañas.", "workbench.editor.labelFormat.default": "Mostrar el nombre del archivo. Cuando están habilitadas las pestañas y dos archivos tienen el mismo nombre en un grupo se agregan las secciones de distinguinshing de ruta de cada archivo. Cuando se desactivan las pestañas, se muestra la ruta de acceso relativa a la carpeta de trabajo si el editor está activo.", "workbench.editor.labelFormat.short": "Mostrar el nombre del archivo seguido de su nombre de directorio.", @@ -20,8 +21,10 @@ "showIcons": "Controla si los editores abiertos deben mostrarse o no con un icono. Requiere que también se habilite un tema de icono.", "enablePreview": "Controla si los editores abiertos se muestran en vista previa. Los editores en vista previa se reutilizan hasta que se guardan (por ejemplo, mediante doble clic o editándolos) y se muestran en cursiva.", "enablePreviewFromQuickOpen": "Controla si los editores abiertos mediante Quick Open se muestran en modo de vista previa. Los editores en modo de vista previa se reutilizan hasta que se conservan (por ejemplo, mediante doble clic o editándolos).", + "closeOnFileDelete": "Controla si los editores que muestran un archivo deben cerrarse automáticamente cuando otro proceso elimina el archivo o le cambia el nombre. Si se deshabilita esta opción y se da alguna de estas circunstancias, se mantiene el editor abierto con modificaciones. Tenga en cuenta que, cuando se eliminan archivos desde la aplicación, siempre se cierra el editor y que los archivos con modificaciones no se cierran nunca para preservar los datos.", "editorOpenPositioning": "Controla dónde se abren los editores. Seleccione 'izquierda' o 'derecha' para abrir los editores situados a la izquierda o la derecha del que está actualmente activo. Seleccione 'primero' o 'último' para abrir los editores con independencia del que esté actualmente activo. ", "revealIfOpen": "Controla si un editor se muestra en alguno de los grupos visibles cuando se abre. Si se deshabilita esta opción, un editor preferirá abrirse en el grupo de editores activo en ese momento. Si se habilita, un editor ya abierto se mostrará en lugar de volver a abrirse en el grupo de editores activo. Tenga en cuenta que hay casos en los que esta opción se omite; por ejemplo, cuando se fuerza la apertura de un editor en un grupo específico o junto al grupo activo actual.", + "swipeToNavigate": "Navegar entre achivos abiertos utlizando la pulsación de tres dedos para deslizar horizontalmante.", "commandHistory": "Controla el número de comandos utilizados recientemente que se mantendrán en el historial de la paleta de comandos. Establezca el valor a 0 para desactivar el historial de comandos.", "preserveInput": "Controla si la última entrada introducida en la paleta de comandos debería ser restaurada cuando sea abierta la próxima vez.", "closeOnFocusLost": "Controla si Quick Open debe cerrarse automáticamente cuando pierde el foco.", @@ -29,14 +32,11 @@ "sideBarLocation": "Controla la ubicación de la barra lateral. Puede mostrarse a la izquierda o a la derecha del área de trabajo.", "statusBarVisibility": "Controla la visibilidad de la barra de estado en la parte inferior del área de trabajo.", "activityBarVisibility": "Controla la visibilidad de la barra de actividades en el área de trabajo.", - "closeOnFileDelete": "Controla si los editores que muestran un archivo deben cerrarse automáticamente cuando otro proceso elimina el archivo o le cambia el nombre. Si se deshabilita esta opción y se da alguna de estas circunstancias, se mantiene el editor abierto con modificaciones. Tenga en cuenta que, cuando se eliminan archivos desde la aplicación, siempre se cierra el editor y que los archivos con modificaciones no se cierran nunca para preservar los datos.", - "enableNaturalLanguageSettingsSearch": "Controla si habilita el modo de búsqueda de lenguaje natural para la configuración.", "fontAliasing": "Controla el método de suavizado de fuentes en el área de trabajo.\n- default: suavizado de fuentes en subpíxeles. En la mayoría de las pantallas que no son Retina, esta opción muestra el texto más nítido.\n- antialiased: suaviza las fuentes en píxeles, en lugar de subpíxeles. Puede hacer que las fuentes se vean más claras en general\n- none: deshabilita el suavizado de fuentes. El texto se muestra con bordes nítidos irregulares.", "workbench.fontAliasing.default": "Suavizado de fuentes en subpíxeles. En la mayoría de las pantallas que no son Retina, esta opción muestra el texto más nítido.", "workbench.fontAliasing.antialiased": "Suaviza las fuentes en píxeles, en lugar de subpíxeles. Puede hacer que las fuentes se vean más claras en general.", "workbench.fontAliasing.none": "Deshabilita el suavizado de fuentes. El texto se muestra con bordes nítidos irregulares.", - "swipeToNavigate": "Navegar entre achivos abiertos utlizando la pulsación de tres dedos para deslizar horizontalmante.", - "workbenchConfigurationTitle": "Área de trabajo", + "enableNaturalLanguageSettingsSearch": "Controla si habilita el modo de búsqueda de lenguaje natural para la configuración.", "windowConfigurationTitle": "Ventana", "window.openFilesInNewWindow.on": "Los archivos se abrirán en una nueva ventana", "window.openFilesInNewWindow.off": "Los archivos se abrirán en la ventana con la carpeta de archivos abierta o en la última ventana activa", diff --git a/i18n/esn/src/vs/workbench/electron-browser/window.i18n.json b/i18n/esn/src/vs/workbench/electron-browser/window.i18n.json index 5ceee829d26..bf0f301897f 100644 --- a/i18n/esn/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/esn/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Cortar", "copy": "Copiar", "paste": "Pegar", - "selectAll": "Seleccionar todo" + "selectAll": "Seleccionar todo", + "runningAsRoot": "No se recomienda ejecutar {0} como usuario root." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 28c7690312b..59239289a53 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "Configuraciones de esquema JSON para validar \"launch.json\".", "vscode.extension.contributes.debuggers.windows": "Configuración específica de Windows.", "vscode.extension.contributes.debuggers.windows.runtime": "Entorno de ejecución que se usa para Windows.", - "vscode.extension.contributes.debuggers.osx": "Configuración específica de OS X.", - "vscode.extension.contributes.debuggers.osx.runtime": "Entorno de ejecución que se usa para OSX.", "vscode.extension.contributes.debuggers.linux": "Configuración específica de Linux.", "vscode.extension.contributes.debuggers.linux.runtime": "Entorno de ejecución que se usa para Linux.", "vscode.extension.contributes.breakpoints": "Aporta puntos de interrupción.", diff --git a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 0f8291c0572..68ea94e5a20 100644 --- a/i18n/esn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "depurado", - "debug.terminal.not.available.error": "Terminal integrado no disponible" + "debug.terminal.title": "depurado" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 1ba4ecd59bf..c01e0004e65 100644 --- a/i18n/esn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Abrir nuevo símbolo del sistema", "globalConsoleActionMacLinux": "Abrir nuevo terminal", "scopedConsoleActionWin": "Abrir en símbolo del sistema", - "scopedConsoleActionMacLinux": "Abrir en terminal", - "openFolderInIntegratedTerminal": "Abrir en terminal" + "scopedConsoleActionMacLinux": "Abrir en terminal" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 3335907cc3e..90cb60f6caf 100644 --- a/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Esta extensión se recomienda basado en los archivos que abrió recientemente.", + "neverShowAgain": "No volver a mostrar", + "close": "Cerrar", "workspaceRecommendation": "Esta extensión es recomendada por los usuarios del espacio de trabajo actual.", + "fileBasedRecommendation": "Esta extensión se recomienda basado en los archivos que abrió recientemente.", "exeBasedRecommendation": "Se recomienda esta extensión porque tiene instalado {0} . ", "reallyRecommended2": "La extension recomendada para este tipo de archivo es {0}", "reallyRecommendedExtensionPack": "Para este tipo de fichero, se recomienda el paquete de extensión '{0}'.", "showRecommendations": "Mostrar recomendaciones", "install": "Instalar", - "neverShowAgain": "No volver a mostrar", - "close": "Cerrar", "workspaceRecommended": "Esta área de trabajo tiene recomendaciones de extensión.", "installAll": "Instalar todo", "ignoreExtensionRecommendations": "¿Desea ignorar todas las recomendaciones de la extensión?", diff --git a/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..eff0be207f1 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Área de trabajo" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 5b4f1d9a867..a73d898f487 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,25 @@ "filesCategory": "Archivo", "revealInSideBar": "Mostrar en barra lateral", "acceptLocalChanges": "Usar los cambios y sobrescribir el contenido del disco", - "revertLocalChanges": "Descartar los cambios y volver al contenido del disco" + "revertLocalChanges": "Descartar los cambios y volver al contenido del disco", + "copyPathOfActive": "Copiar ruta del archivo activo", + "saveAllInGroup": "Guardar todo en el grupo", + "saveFiles": "Guardar todos los archivos", + "revert": "Revertir archivo", + "compareActiveWithSaved": "Comparar el archivo activo con el guardado", + "closeEditor": "Cerrar editor", + "view": "Ver", + "openToSide": "Abrir en el lateral", + "revealInWindows": "Mostrar en el Explorador", + "revealInMac": "Mostrar en Finder", + "openContainer": "Abrir carpeta contenedora", + "copyPath": "Copiar ruta de acceso", + "saveAll": "Guardar todos", + "compareWithSaved": "Comparar con el guardado", + "compareSource": "Seleccionar para comparar", + "close": "Cerrar", + "closeOthers": "Cerrar otros", + "closeUnmodified": "Cerrar los que no se han modificado", + "closeAll": "Cerrar todo", + "deleteFile": "Eliminar permanentemente" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 849c94fa0c7..a96cb97676f 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Reintentar", - "rename": "Cambiar nombre", "newFile": "Nuevo archivo", "newFolder": "Nueva carpeta", + "rename": "Cambiar nombre", + "delete": "Eliminar", + "copyFile": "Copiar", + "pasteFile": "Pegar", + "retry": "Reintentar", "openFolderFirst": "Abra primero una carpeta para crear archivos o carpetas en ella.", "newUntitledFile": "Nuevo archivo sin título", "createNewFile": "Nuevo archivo", @@ -28,26 +31,14 @@ "confirmDeleteMessageFile": "¿Está seguro de que desea eliminar '{0}' de forma permanente?", "irreversible": "Esta acción es irreversible.", "permDelete": "Eliminar permanentemente", - "delete": "Eliminar", "importFiles": "Importar archivos", "confirmOverwrite": "Ya existe un archivo o carpeta con el mismo nombre en la carpeta de destino. ¿Quiere reemplazarlo?", "replaceButtonLabel": "&&Reemplazar", - "copyFile": "Copiar", - "pasteFile": "Pegar", "duplicateFile": "Duplicado", - "openToSide": "Abrir en el lateral", - "compareSource": "Seleccionar para comparar", "globalCompareFile": "Comparar archivo activo con...", "openFileToCompare": "Abrir un archivo antes para compararlo con otro archivo.", - "compareWith": "Comparar \"{0}\" con \"{1}\"", - "compareFiles": "Comparar archivos", "refresh": "Actualizar", - "save": "Guardar", - "saveAs": "Guardar como...", - "saveAll": "Guardar todos", "saveAllInGroup": "Guardar todo en el grupo", - "saveFiles": "Guardar todos los archivos", - "revert": "Revertir archivo", "focusOpenEditors": "Foco sobre la vista de editores abiertos", "focusFilesExplorer": "Enfocar Explorador de archivos", "showInExplorer": "Mostrar el archivo activo en la barra lateral", @@ -56,20 +47,11 @@ "refreshExplorer": "Actualizar Explorador", "openFileInNewWindow": "Abrir archivo activo en nueva ventana", "openFileToShowInNewWindow": "Abrir un archivo antes para abrirlo en una nueva ventana", - "revealInWindows": "Mostrar en el Explorador", - "revealInMac": "Mostrar en Finder", - "openContainer": "Abrir carpeta contenedora", - "revealActiveFileInWindows": "Mostrar archivo activo en el Explorador de Windows", - "revealActiveFileInMac": "Mostrar archivo activo en Finder", - "openActiveFileContainer": "Abrir carpeta contenedora del archivo activo", "copyPath": "Copiar ruta de acceso", - "copyPathOfActive": "Copiar ruta del archivo activo", "emptyFileNameError": "Debe especificarse un nombre de archivo o carpeta.", "fileNameExistsError": "Ya existe el archivo o carpeta **{0}** en esta ubicación. Elija un nombre diferente.", "invalidFileNameError": "El nombre **{0}** no es válido para el archivo o la carpeta. Elija un nombre diferente.", "filePathTooLongError": "El nombre **{0}** da como resultado una ruta de acceso demasiado larga. Elija un nombre más corto.", - "compareWithSaved": "Comparar el archivo activo con el guardado", - "modifiedLabel": "{0} (en el disco) ↔ {1}", "compareWithClipboard": "Comparar archivo activo con portapapeles", "clipboardComparisonLabel": "Clipboard ↔ {0}" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index f417c4b11aa..2228202fde4 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Abrir un archivo antes para copiar su ruta de acceso", - "openFileToReveal": "Abrir un archivo antes para mostrarlo" + "revealInWindows": "Mostrar en el Explorador", + "revealInMac": "Mostrar en Finder", + "openContainer": "Abrir carpeta contenedora", + "saveAs": "Guardar como...", + "save": "Guardar", + "saveAll": "Guardar todos", + "removeFolderFromWorkspace": "Quitar carpeta del área de trabajo", + "modifiedLabel": "{0} (en el disco) ↔ {1}", + "openFileToReveal": "Abrir un archivo antes para mostrarlo", + "openFileToCopy": "Abrir un archivo antes para copiar su ruta de acceso" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 6b7926d2bf7..34df999607b 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "Editor", "formatOnSave": "Formatea un archivo al guardarlo. Debe haber un formateador disponible, el archivo no debe guardarse automáticamente y el editor no debe estar cerrándose.", "explorerConfigurationTitle": "Explorador de archivos", - "openEditorsVisible": "Número de editores mostrados en el panel Editores abiertos. Establezca este valor en 0 para ocultar el panel.", - "dynamicHeight": "Controla si la altura de la sección de editores abiertos debería adaptarse o no de forma dinámica al número de elementos.", "autoReveal": "Controla si el explorador debe mostrar y seleccionar automáticamente los archivos al abrirlos.", "enableDragAndDrop": "Controla si el explorador debe permitir mover archivos y carpetas mediante la función arrastrar y colocar.", "confirmDragAndDrop": "Controla si el explorador debe pedir la confirmación al reubicar archivos o carpetas a través de arrastrar y soltar.", diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 186f5cdaa42..b8d86411047 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Use las acciones de la barra de herramientas del editor situada a la derecha para **deshacer** los cambios o **sobrescribir** el contenido del disco con sus cambios", - "discard": "Descartar", + "overwriteElevated": "Sobrescribir como Admin...", + "saveElevated": "Reintentar como Admin...", "overwrite": "Sobrescribir", "retry": "Reintentar", - "readonlySaveError": "No se pudo guardar '{0}': El archivo está protegido contra escritura. Seleccione \"Sobrescribir\" para quitar la protección.", + "discard": "Descartar", + "readonlySaveErrorAdmin": "No se pudo guardar '{0}': El archivo está protegido contra escritura. Seleccione 'Sobrescribir como Admin' para volverlo a intentar como administrador.", + "readonlySaveError": "No se pudo guardar '{0}': El archivo está protegido contra escritura. Seleccione 'Sobrescribir' para intentar quitar la protección.", + "permissionDeniedSaveError": "No se pudo guardar '{0}': Permisos insuficientes. Seleccione 'Reintentar como Admin' para volverlo a intentar como administrador.", "genericSaveError": "No se pudo guardar '{0}': {1}", "staleSaveError": "No se pudo guardar '{0}': El contenido del disco es más reciente. Haga clic en **Comparar** para comparar su versión con la que hay en el disco.", "compareChanges": "Comparar", diff --git a/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index b4bad361098..f5060aef05b 100644 --- a/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Editores abiertos", "openEditosrSection": "Sección Editores abiertos", - "dirtyCounter": "{0} sin guardar", - "saveAll": "Guardar todos", - "closeAllUnmodified": "Cerrar los que no se han modificado", - "closeAll": "Cerrar todo", - "compareWithSaved": "Comparar con el guardado", - "close": "Cerrar", - "closeOthers": "Cerrar otros" + "dirtyCounter": "{0} sin guardar" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..29b8033be98 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "Log (Principal)", + "sharedLog": "Log (Compartido)", + "rendererLog": "Log (Ventana)", + "extensionsLog": "Log (Extensión del Host)", + "developer": "Desarrollador" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..850ca48cdd2 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Abrir carpeta de registros", + "showLogs": "Mostrar registros...", + "mainProcess": "Principal", + "sharedProcess": "Compartido", + "rendererProcess": "Ventana", + "extensionHost": "Host de extensión", + "selectProcess": "Seleccionar proceso", + "openLogFile": "Abrir archivo de log...", + "setLogLevel": "Establecer nivel de registro", + "trace": "Seguimiento", + "debug": "Depurar", + "info": "Información", + "warn": "Advertencia", + "err": "Error", + "critical": "Crítico", + "off": "Apagado", + "selectLogLevel": "Seleccionar nivel de log" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/esn/src/vs/workbench/parts/markers/common/messages.i18n.json index a028050eafb..b28c9ca3342 100644 --- a/i18n/esn/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Ver", - "problems.view.toggle.label": "Alternar Problemas ", - "problems.view.focus.label": "Problemas de enfoque", "problems.panel.configuration.title": "Vista Problemas", "problems.panel.configuration.autoreveal": "Controla si la vista Problemas debe revelar automáticamente los archivos cuando los abre", "markers.panel.title.problems": "Problemas", diff --git a/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..c75638715f9 --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Salida", + "viewCategory": "Ver", + "clearOutput.label": "Borrar salida" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/esn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index b720c2b8a57..7f4ed8494b7 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "¡Intentar la búsqueda del lenguaje natural!", "defaultSettings": "Colocar la configuración en el editor de lado de mano derecha para anular.", "noSettingsFound": "No se encontró ninguna configuración.", "settingsSwitcherBarAriaLabel": "Conmutador de configuración", "userSettings": "Configuración de usuario", "workspaceSettings": "Configuración de área de trabajo", - "folderSettings": "Configuración de Carpeta", - "enableFuzzySearch": "Habilitar búsqueda en lenguaje natural" + "folderSettings": "Configuración de Carpeta" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/esn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 575bc61fdb4..2ae85dc2ac1 100644 --- a/i18n/esn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Más utilizada", - "mostRelevant": "Más relevante", "defaultKeybindingsHeader": "Coloque los enlaces de teclado en el archivo de enlaces de teclado para sobrescribirlos." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 3a50ec52260..6e19797b529 100644 --- a/i18n/esn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Ver", "commandsHandlerDescriptionDefault": "Mostrar y ejecutar comandos", "gotoLineDescriptionMac": "Ir a la línea", "gotoLineDescriptionWin": "Ir a la línea", diff --git a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 2d44f58d514..45352bad122 100644 --- a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,7 @@ "toggleGitViewlet": "Mostrar GIT", "source control": "Control de código fuente", "toggleSCMViewlet": "Mostrar SCM", - "view": "Ver" + "view": "Ver", + "scmConfigurationTitle": "SCM", + "inputCounter": "Controla cuándo mostrar el contador de entradas." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 7f679305c9e..812f048c02f 100644 --- a/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,8 @@ { "scm providers": "Proveedores de Control de Código fuente", "hideRepository": "Ocultar", + "commitMessageInfo": "{0} caracteres en la línea actual", + "commitMessageCountdown": "quedan {0} caracteres en la línea actual", "installAdditionalSCMProviders": "Instalar proveedores adicionales de SCM...", "no open repo": "No hay proveedores de control de código fuente activos.", "source control": "Control de código fuente", diff --git a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index bcfc62d1906..5357b8b610a 100644 --- a/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Mostrar anterior término de búsqueda", "showSearchViewlet": "Mostrar búsqueda", "findInFiles": "Buscar en archivos", - "findInFilesWithSelectedText": "Buscar en ficheros de texto seleccionado", "replaceInFiles": "Reemplazar en archivos", - "replaceInFilesWithSelectedText": "Reemplazar en archivos con el texto seleccionado", "RefreshAction.label": "Actualizar", "CollapseDeepestExpandedLevelAction.label": "Contraer todo", "ClearSearchResultsAction.label": "Borrar", diff --git a/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index fe7e74dbe33..3b7e2d3cd41 100644 --- a/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Buscar en carpeta...", + "findInWorkspace": "Buscar en área de trabajo...", "showTriggerActions": "Ir al símbolo en el área de trabajo...", "name": "Buscar", "search": "Buscar", + "showSearchViewlet": "Mostrar búsqueda", "view": "Ver", + "findInFiles": "Buscar en archivos", "openAnythingHandlerDescription": "Ir al archivo", "openSymbolDescriptionNormal": "Ir al símbolo en el área de trabajo", - "searchOutputChannelTitle": "Buscar", "searchConfigurationTitle": "Buscar", "exclude": "Configure patrones globales para excluir archivos y carpetas de las búsquedas. Hereda todos los patrones globales de la configuración files.exclude.", "exclude.boolean": "El patrón global con el que se harán coincidir las rutas de acceso de los archivos. Establézcalo en true o false para habilitarlo o deshabilitarlo.", diff --git a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..9675a4f182c --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "Preferencias" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index c49e1beb60b..5fb6638f35b 100644 --- a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Seleccione lenguaje para el fragmento", - "openSnippet.errorOnCreate": "No se puede crear {0}", - "openSnippet.label": "Abrir fragmentos de código del usuario", - "preferences": "Preferencias", "snippetSchema.json.default": "Fragmento de código vacío", "snippetSchema.json": "Configuración de fragmento de código del usuario", "snippetSchema.json.prefix": "El prefijo que se debe usar al seleccionar el fragmento de código en Intellisense", diff --git a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..8c806f2935a --- /dev/null +++ b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Fragmento de código del usuario" +} \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index ecf3b81fb81..34d3cff577c 100644 --- a/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Lenguaje desconocido en \"contributes.{0}.language\". Valor proporcionado: {1}", "invalid.path.0": "Se esperaba una cadena en \"contributes.{0}.path\". Valor proporcionado: {1}", + "invalid.language": "Lenguaje desconocido en \"contributes.{0}.language\". Valor proporcionado: {1}", "invalid.path.1": "Se esperaba que \"contributes.{0}.path\" ({1}) se incluyera en la carpeta de la extensión ({2}). Esto puede hacer que la extensión no sea portátil.", "vscode.extension.contributes.snippets": "Aporta fragmentos de código.", "vscode.extension.contributes.snippets-language": "Identificador del lenguaje al que se aporta este fragmento de código.", "vscode.extension.contributes.snippets-path": "Ruta de acceso del archivo de fragmentos de código. La ruta es relativa a la carpeta de extensión y normalmente empieza por \"./snippets/\".", "badVariableUse": "Uno o más fragmentos de la extensión '{0}' muy probable confunden variables de fragmento y fragmento-marcadores de posición (véase https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax para más detalles)", "badFile": "No se pudo leer el archivo del fragmento \"{0}\".", - "source.snippet": "Fragmento de código del usuario", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index b41adfc8dd9..f8bbe6f41b9 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "El color de primer plano del terminal.", "terminalCursor.foreground": "Color de primer plano del cursor del terminal.", "terminalCursor.background": "Color de fondo del cursor del terminal. Permite personalizar el color de un carácter solapado por un cursor de bloque.", - "terminal.selectionBackground": "Color de fondo de selección del terminal.", - "terminal.ansiColor": "Color ANSI \"{0}\" en el terminal." + "terminal.selectionBackground": "Color de fondo de selección del terminal." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 1a5374df014..d5f5c068b5f 100644 --- a/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/esn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "Para cambiar el shell de terminal predeterminado, seleccione el botón Personalizar.", "customize": "Personalizar", "cancel": "Cancelar", - "never again": "De acuerdo, no volver a mostrar este mensaje", "terminal.integrated.chooseWindowsShell": "Seleccione el shell de terminal que desee, puede cambiarlo más adelante en la configuración", "terminalService.terminalCloseConfirmationSingular": "Hay una sesión de terminal activa, ¿quiere terminarla?", "terminalService.terminalCloseConfirmationPlural": "Hay {0} sesiones de terminal activas, ¿quiere terminarlas?" diff --git a/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 1d8632efe35..45b01f69897 100644 --- a/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileNotModifiedError": "Archivo no modificado desde", "fileBinaryError": "El archivo parece ser binario y no se puede abrir como texto" } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/esn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index e49927e3bdf..caa8ce6bf00 100644 --- a/i18n/esn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "¿Quiere guardar los cambios efectuados en {0}?", "saveChangesMessages": "¿Desea guardar los cambios en los siguientes {0} archivos?", - "moreFile": "...1 archivo más que no se muestra", - "moreFiles": "...{0} archivos más que no se muestran", "saveAll": "&&Guardar todo", "save": "Guardar", "dontSave": "&&No guardar", diff --git a/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 302c7ed170b..410c2efcbcb 100644 --- a/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Reemplaza los colores del tema de color actual", - "editorColors": "Reemplaza los colores y el estilo de fuente del editor del tema de color seleccionado.", "editorColors.comments": "Establece los colores y estilos para los comentarios", "editorColors.strings": "Establece los colores y estilos para los literales de cadena.", "editorColors.keywords": "Establece los colores y estilos para las palabras clave.", @@ -19,5 +18,6 @@ "editorColors.types": "Establece los colores y estilos para las declaraciones y referencias de tipos.", "editorColors.functions": "Establece los colores y estilos para las declaraciones y referencias de funciones.", "editorColors.variables": "Establece los colores y estilos para las declaraciones y referencias de variables.", - "editorColors.textMateRules": "Establece colores y estilos utilizando las reglas de la tematización de textmate (avanzadas)." + "editorColors.textMateRules": "Establece colores y estilos utilizando las reglas de la tematización de textmate (avanzadas).", + "editorColors": "Reemplaza los colores y el estilo de fuente del editor del tema de color seleccionado." } \ No newline at end of file diff --git a/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 83604230ec4..e7f9d116f01 100644 --- a/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/esn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "No se puede escribir en el archivo de configuración del espacio de trabajo. Por favor, abra el archivo para corregir sus errores/advertencias e inténtelo de nuevo.", "errorWorkspaceConfigurationFileDirty": "No se puede escribir en el archivo de configuración de espacio de trabajo porque el archivo ha sido modificado. Por favor, guárdelo y vuelva a intentarlo.", "openWorkspaceConfigurationFile": "Abrir archivo de configuración del área de trabajo", - "close": "Cerrar", - "enterWorkspace.close": "Cerrar", - "enterWorkspace.dontShowAgain": "No volver a mostrar", - "enterWorkspace.moreInfo": "Más información", - "enterWorkspace.prompt": "Obtenga más información acerca de cómo trabajar con varias carpetas en VS Code. " + "close": "Cerrar" } \ No newline at end of file diff --git a/i18n/fra/extensions/git/out/autofetch.i18n.json b/i18n/fra/extensions/git/out/autofetch.i18n.json index c7e1b61f3ec..e5a3f00f716 100644 --- a/i18n/fra/extensions/git/out/autofetch.i18n.json +++ b/i18n/fra/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Oui", + "read more": "Lire la suite", "no": "Non", - "not now": "Pas maintenant", - "suggest auto fetch": "Voulez-vous activer la rappatriement automatique des dépôts Git ?" + "not now": "Me demander plus tard", + "suggest auto fetch": "Voulez-vous que Code exécute périodiquement `git fetch` ?" } \ No newline at end of file diff --git a/i18n/fra/extensions/git/out/commands.i18n.json b/i18n/fra/extensions/git/out/commands.i18n.json index ec8efb3f0d7..0ab84d9bc6f 100644 --- a/i18n/fra/extensions/git/out/commands.i18n.json +++ b/i18n/fra/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nCette opération est IRRÉVERSIBLE, votre plage de travail actuelle sera DÉFINITIVEMENT PERDUE.", "yes discard tracked": "Ignorer 1 fichier suivi", "yes discard tracked multiple": "Ignorer {0} fichiers suivis", + "unsaved files single": "Le fichier suivant n'est pas enregistré : {0}.\n\nVoulez-vous l'enregistrer avant d'effectuer le commit ?", + "unsaved files": "Il y a {0} fichiers non enregistrés.\n\nVoulez-vous l'enregistrer avant d'effectuer le commit ?", + "save and commit": "Tout enregistrer et Effectuer le commit", + "commit": "Effectuer le commit quand même", "no staged changes": "Aucune modification en attente à valider.\n\nVoulez-vous automatiquement mettre en attente toutes vos modifications et les valider directement ?", "always": "Toujours", "no changes": "Il n'existe aucun changement à valider.", @@ -64,12 +68,13 @@ "no remotes to pull": "Votre dépôt n'a aucun dépôt distant configuré pour un Pull.", "pick remote pull repo": "Choisir un dépôt distant duquel extraire la branche", "no remotes to push": "Votre dépôt n'a aucun dépôt distant configuré pour un Push.", - "push with tags success": "Envoyé (push) avec des balises.", "nobranch": "Vous devez extraire une branche dont vous souhaitez effectuer le Push vers un emplacement distant.", + "confirm publish branch": "La branche '{0}' n'a pas de branche en amont. Voulez-vous publier cette branche ?", + "ok": "OK", + "push with tags success": "Envoyé (push) avec des balises.", "pick remote": "Choisissez un dépôt distant où publier la branche '{0}' :", "sync is unpredictable": "Cette action effectue un transfert (Push) et un tirage (Pull) des validations à destination et en provenance de '{0}'.", - "ok": "OK", - "never again": "OK, ne plus afficher", + "never again": "OK, Ne plus afficher", "no remotes to publish": "Votre dépôt n'a aucun dépôt distant configuré pour une publication.", "no changes stash": "Aucune modification à remiser (stash).", "provide stash message": "Spécifier éventuellement un message pour la remise (stash)", diff --git a/i18n/fra/extensions/git/package.i18n.json b/i18n/fra/extensions/git/package.i18n.json index 188e2b5ba4a..a1ed0d37d5d 100644 --- a/i18n/fra/extensions/git/package.i18n.json +++ b/i18n/fra/extensions/git/package.i18n.json @@ -54,12 +54,13 @@ "command.stashPopLatest": "Appliquer et supprimer la dernière remise", "config.enabled": "Indique si git est activé", "config.path": "Chemin d'accès à l'exécutable git", + "config.autoRepositoryDetection": "Si les dépôts doivent être détectés automatiquement", "config.autorefresh": "Indique si l'actualisation automatique est activée", "config.autofetch": "Indique si la récupération automatique est activée", "config.enableLongCommitWarning": "Indique si les longs messages de validation doivent faire l'objet d'un avertissement", "config.confirmSync": "Confirmer avant de synchroniser des dépôts git", "config.countBadge": "Contrôle le compteur de badges Git. La valeur 'toutes' compte toutes les modifications. La valeur 'suivies' compte uniquement les modifications suivies. La valeur 'désactivé' désactive le compteur.", - "config.checkoutType": "Contrôle le type des branches répertoriées pendant l'exécution de 'Extraire vers...'. La valeur 'toutes' montre toutes les références, la valeur 'locales' montre uniquement les branches locales, la valeur 'balises' montre uniquement les balises et la valeur 'distantes' montre uniquement les branches distantes.", + "config.checkoutType": "Contrôle quel type de branches sont répertoriées pendant l'exécution de 'Extraire vers...'. `all` affiche toutes les références, `local` affiche uniquement les branches locales, `tags` affiche uniquement les balises et la valeur `remote` montre uniquement les branches distantes.", "config.ignoreLegacyWarning": "Ignore l'avertissement Git hérité", "config.ignoreMissingGitWarning": "Ignore l'avertissement quand Git est manquant", "config.ignoreLimitWarning": "Ignore l'avertissement quand il y a trop de modifications dans un dépôt", @@ -72,5 +73,6 @@ "colors.deleted": "Couleur pour les ressources supprimées.", "colors.untracked": "Couleur pour les ressources non tracées.", "colors.ignored": "Couleur des ressources ignorées.", - "colors.conflict": "Couleur pour les ressources avec des conflits." + "colors.conflict": "Couleur pour les ressources avec des conflits.", + "colors.submodule": "Couleur pour les ressources de sous-module." } \ No newline at end of file diff --git a/i18n/fra/extensions/typescript/out/commands.i18n.json b/i18n/fra/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..6c1e268636a --- /dev/null +++ b/i18n/fra/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Ouvrez un dossier dans VS Code pour utiliser un projet TypeScript ou JavaScript", + "typescript.projectConfigUnsupportedFile": "Impossible de déterminer le projet TypeScript ou JavaScript. Type de fichier non pris en charge", + "typescript.projectConfigCouldNotGetInfo": "Impossible de déterminer le projet TypeScript ou JavaScript", + "typescript.noTypeScriptProjectConfig": "Le fichier ne fait pas partie d'un projet TypeScript", + "typescript.noJavaScriptProjectConfig": "Le fichier ne fait pas partie d'un projet JavaScript", + "typescript.configureTsconfigQuickPick": "Configurer tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurer jsconfig.json", + "typescript.projectConfigLearnMore": "En savoir plus" +} \ No newline at end of file diff --git a/i18n/fra/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/fra/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/fra/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/fra/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/fra/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/fra/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/base/node/ps.i18n.json b/i18n/fra/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..a67aa7a91d1 --- /dev/null +++ b/i18n/fra/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Récupération des informations processeur et mémoire. Cela peut prendre quelques secondes." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json index dd19016cb45..76111fb62b0 100644 --- a/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/fra/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Les numéros de ligne sont affichés en nombre absolu.", "lineNumbers.relative": "Les numéros de ligne sont affichés sous la forme de distance en lignes à la position du curseur.", "lineNumbers.interval": "Les numéros de ligne sont affichés toutes les 10 lignes.", - "lineNumbers": "Contrôle l’affichage des numéros de ligne. Les valeurs possibles sont 'on', 'off', et 'relative'.", + "lineNumbers": "Contrôle l’affichage des numéros de ligne. Les valeurs possibles sont 'on', 'off', 'relative' et 'interval'.", "rulers": "Afficher les règles verticales après un certain nombre de caractères à espacement fixe. Utiliser plusieurs valeurs pour plusieurs règles. Aucune règle n'est dessinée si le tableau est vide", "wordSeparators": "Caractères utilisés comme séparateurs de mots durant la navigation ou les opérations basées sur les mots", "tabSize": "Le nombre d'espaces correspondant à une tabulation. Ce paramètre est remplacé en fonction du contenu du fichier quand 'editor.detectIndentation' est activé.", @@ -40,9 +40,6 @@ "wordWrapColumn": "Contrôle la colonne de retour automatique à la ligne de l'éditeur quand 'editor.wordWrap' a la valeur 'wordWrapColumn' ou 'bounded'.", "wrappingIndent": "Contrôle le retrait des lignes renvoyées. La valeur peut être 'none', 'same' ou 'indent'.", "mouseWheelScrollSensitivity": "Multiplicateur à utiliser pour le 'deltaX' et le 'deltaY' des événements de défilement de la roulette de la souris", - "multiCursorModifier.ctrlCmd": "Mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans OSX.", - "multiCursorModifier.alt": "Mappe vers 'Alt' dans Windows et Linux, et vers 'Option' dans OSX.", - "multiCursorModifier": "Modificateur à utiliser pour ajouter plusieurs curseurs avec la souris. 'ctrlCmd' mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans OSX. Les mouvements de souris Accéder à la définition et Ouvrir le lien s'adaptent pour ne pas entrer en conflit avec le modificateur multicurseur.", "quickSuggestions.strings": "Activez les suggestions rapides dans les chaînes.", "quickSuggestions.comments": "Activez les suggestions rapides dans les commentaires.", "quickSuggestions.other": "Activez les suggestions rapides en dehors des chaînes et des commentaires.", @@ -72,6 +69,7 @@ "cursorBlinking": "Contrôle le style d'animation du curseur. Valeurs possibles : 'blink', 'smooth', 'phase', 'expand' et 'solid'", "mouseWheelZoom": "Agrandir ou réduire la police de l'éditeur quand l'utilisateur fait tourner la roulette de la souris tout en maintenant la touche Ctrl enfoncée", "cursorStyle": "Contrôle le style du curseur. Les valeurs acceptées sont 'block', 'block-outline', 'line', 'line-thin', 'underline' et 'underline-thin'", + "lineCursorWidth": "Contrôle la largeur du curseur quand editor.cursorStyle est à 'line'", "fontLigatures": "Active les ligatures de police", "hideCursorInOverviewRuler": "Contrôle si le curseur doit être masqué dans la règle d'aperçu.", "renderWhitespace": "Contrôle la façon dont l'éditeur affiche les espaces blancs. Il existe trois options possibles : 'none', 'boundary' et 'all'. L'option 'boundary' n'affiche pas les espaces uniques qui séparent les mots.", diff --git a/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json index 4bea17a181e..aff67fd2a97 100644 --- a/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/fra/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "Couleur d'arrière-plan de la mise en surbrillance de la ligne à la position du curseur.", "lineHighlightBorderBox": "Couleur d'arrière-plan de la bordure autour de la ligne à la position du curseur.", - "rangeHighlight": "Couleur d'arrière-plan des plages mises en surbrillance, par exemple par les fonctionnalités de recherche et Quick Open.", + "rangeHighlight": "Couleur d'arrière-plan des plages mises en surbrillance, par exemple par les fonctionnalités d'ouverture rapide et de recherche. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", "caret": "Couleur du curseur de l'éditeur.", "editorCursorBackground": "La couleur de fond du curseur de l'éditeur. Permet de personnaliser la couleur d'un caractère survolé par un curseur de bloc.", "editorWhitespaces": "Couleur des espaces blancs dans l'éditeur.", diff --git a/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 2e7dbc5e1ee..fc4679bba93 100644 --- a/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Accéder à l'erreur ou l'avertissement suivant", - "markerAction.previous.label": "Accéder à l'erreur ou l'avertissement précédent", + "markerAction.next.label": "Aller au problème suivant (Erreur, Avertissement, Info)", + "markerAction.previous.label": "Aller au problème précédent (Erreur, Avertissement, Info)", "editorMarkerNavigationError": "Couleur d'erreur du widget de navigation dans les marqueurs de l'éditeur.", "editorMarkerNavigationWarning": "Couleur d'avertissement du widget de navigation dans les marqueurs de l'éditeur.", "editorMarkerNavigationInfo": "Couleur d’information du widget de navigation du marqueur de l'éditeur.", diff --git a/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 45974daea0a..8e43823c7ac 100644 --- a/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/fra/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Couleur d'arrière-plan d'un symbole durant l'accès en lecture, par exemple la lecture d'une variable.", - "wordHighlightStrong": "Couleur d'arrière-plan d'un symbole durant l'accès en écriture, par exemple l'écriture dans une variable.", + "wordHighlight": "Couleur d'arrière-plan d'un symbole durant l'accès en lecture, par exemple la lecture d'une variable. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", + "wordHighlightStrong": "Couleur d'arrière-plan d'un symbole durant l'accès en écriture, par exemple l'écriture dans une variable. La couleur ne doit pas être opaque pour ne pas masquer les décorations sous-jacentes.", "overviewRulerWordHighlightForeground": "Couleur du marqueur de la règle d'aperçu pour la mise en évidence de symbole.", "overviewRulerWordHighlightStrongForeground": "Couleur du marqueur de la règle d'aperçu la mise en évidence de symbole d’accès en écriture.", "wordHighlight.next.label": "Aller à la prochaine mise en évidence de symbole", diff --git a/i18n/fra/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/fra/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index ed0024d2710..f13a4bbc9e9 100644 --- a/i18n/fra/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/fra/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "'{0}' est un identificateur de menu non valide", "missing.command": "L'élément de menu fait référence à une commande '{0}' qui n'est pas définie dans la section 'commands'.", "missing.altCommand": "L'élément de menu fait référence à une commande alt '{0}' qui n'est pas définie dans la section 'commands'.", - "dupe.command": "L'élément de menu fait référence à la même commande que la commande par défaut et la commande alt", - "nosupport.altCommand": "Actuellement, seul le groupe 'navigation' du menu 'editor/title' prend en charge les commandes alt" + "dupe.command": "L'élément de menu fait référence à la même commande que la commande par défaut et la commande alt" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/environment/node/argv.i18n.json b/i18n/fra/src/vs/platform/environment/node/argv.i18n.json index f676e6c787f..217c685dc72 100644 --- a/i18n/fra/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/fra/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,35 @@ "diff": "Comparez deux fichiers entre eux.", "add": "Ajoutez un ou plusieurs dossiers à la dernière fenêtre active.", "goto": "Ouvrez un fichier dans le chemin, à la ligne et la position de caractère spécifiées.", - "locale": "Paramètres régionaux à utiliser (exemple : fr-FR ou en-US).", "newWindow": "Forcez l'utilisation d'une nouvelle instance de Code.", - "performance": "Démarrez avec la commande 'Développeur : performance de démarrage' activée.", - "prof-startup": "Exécuter le profileur d'UC au démarrage", - "inspect-extensions": "Autorise le débogage et le profilage des extensions. Vérifier les outils de développements pour l'uri de connexion.", - "inspect-brk-extensions": "Autorise le débogage et le profilage des extensions avec l'hôte d'extensions en pause après le démarrage. Vérifier les outils de développement pour l'uri de connexion.", "reuseWindow": "Forcez l'ouverture d'un fichier ou dossier dans la dernière fenêtre active.", - "userDataDir": "Spécifie le répertoire où sont conservées les données des utilisateurs. S'avère utile pour une exécution en tant que root.", - "log": "Niveau de journalisation à utiliser. La valeur par défaut est 'info'. Les valeurs autorisées sont 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off.", - "verbose": "Affichez la sortie détaillée (implique --wait).", "wait": "Attendre que les fichiers soient fermés avant de retourner.", + "locale": "Paramètres régionaux à utiliser (exemple : fr-FR ou en-US).", + "userDataDir": "Spécifie le répertoire où sont conservées les données des utilisateurs. S'avère utile pour une exécution en tant que root.", + "version": "Affichez la version.", + "help": "Affichez le mode d'utilisation.", "extensionHomePath": "Définissez le chemin racine des extensions.", "listExtensions": "Listez les extensions installées.", "showVersions": "Affichez les versions des extensions installées, quand --list-extension est utilisé.", "installExtension": "Installe une extension.", "uninstallExtension": "Désinstalle une extension.", "experimentalApis": "Active les fonctionnalités d'API proposées pour une extension.", - "disableExtensions": "Désactivez toutes les extensions installées.", - "disableGPU": "Désactivez l'accélération matérielle du GPU.", + "verbose": "Affichez la sortie détaillée (implique --wait).", + "log": "Niveau de journalisation à utiliser. La valeur par défaut est 'info'. Les valeurs autorisées sont 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off.", "status": "Imprimer l'utilisation de processus et l'information des diagnostics.", - "version": "Affichez la version.", - "help": "Affichez le mode d'utilisation.", + "performance": "Démarrez avec la commande 'Développeur : performance de démarrage' activée.", + "prof-startup": "Exécuter le profileur d'UC au démarrage", + "disableExtensions": "Désactivez toutes les extensions installées.", + "inspect-extensions": "Autorise le débogage et le profilage des extensions. Vérifier les outils de développements pour l'uri de connexion.", + "inspect-brk-extensions": "Autorise le débogage et le profilage des extensions avec l'hôte d'extensions en pause après le démarrage. Vérifier les outils de développement pour l'uri de connexion.", + "disableGPU": "Désactivez l'accélération matérielle du GPU.", + "uploadLogs": "Upload les logs depuis la session actuelle vers le endpoint sécurisé.", "usage": "Utilisation", "options": "options", "paths": "chemins", - "optionsUpperCase": "Options" + "stdinWindows": "Pour lire la sortie d’un autre programme, ajouter '-' (ex. 'echo Bonjour tout le monde | {0} -')", + "stdinUnix": "Pour lire depuis stdin, ajouter '-' (ex. 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Options", + "extensionsManagement": "Gestion des extensions", + "troubleshooting": "Dépannage" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 620e2694e2a..ccd0c9dadfd 100644 --- a/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/fra/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Extension non valide : package.json n'est pas un fichier JSON.", - "restartCodeLocal": "Redémarrez Code avant de réinstaller {0}.", + "restartCode": "Redémarrez Code avant de réinstaller {0}.", "installingOutdatedExtension": "Une version plus récente de cette extension est déjà installée. Voulez-vous remplacer celle-ci avec l'ancienne version ?", "override": "Remplacer", "cancel": "Annuler", - "notFoundCompatible": "Installation impossible car l'extension '{0}' compatible avec la version actuelle '{1}' de VS Code est introuvable.", - "quitCode": "Installation impossible car une instance obsolète de l'extension est en cours d'exécution. Veuillez quitter et redémarrer VS Code avant de réinstaller.", - "exitCode": "Installation impossible car une instance obsolète de l'extension est en cours d'exécution. Veuillez sortir et redémarrer VS Code avant de réinstaller.", + "errorInstallingDependencies": "Erreur lors de l'installation des dépendances. {0}", + "notFoundCompatible": "Impossible d’installer '{0}'; Il n’y a pas de version disponible compatible avec VS Code '{1}'.", "notFoundCompatibleDependency": "Installation impossible car l'extension dépendante '{0}' compatible avec la version actuelle '{1}' de VS Code est introuvable.", + "quitCode": "Impossible d’installer l’extension. Veuillez s’il vous plaît quitter et redémarrer VS Code avant de le réinstaller.", + "exitCode": "Impossible d’installer l’extension. Veuillez s’il vous plaît sortir et redémarrer VS Code avant de le réinstaller.", "uninstallDependeciesConfirmation": "Voulez-vous désinstaller uniquement '{0}' ou également ses dépendances ?", "uninstallOnly": "Uniquement", "uninstallAll": "Tout", diff --git a/i18n/fra/src/vs/platform/list/browser/listService.i18n.json b/i18n/fra/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..92f8f5bfde6 --- /dev/null +++ b/i18n/fra/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Banc d'essai" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/message/common/message.i18n.json b/i18n/fra/src/vs/platform/message/common/message.i18n.json index 93ee2acf35b..227d6123d7a 100644 --- a/i18n/fra/src/vs/platform/message/common/message.i18n.json +++ b/i18n/fra/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Fermer", "later": "Plus tard", - "cancel": "Annuler" + "cancel": "Annuler", + "moreFile": "...1 fichier supplémentaire non affiché", + "moreFiles": "...{0} fichiers supplémentaires non affichés" } \ No newline at end of file diff --git a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json index 64fc37335ec..125c9debbca 100644 --- a/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/fra/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "Couleur de bordure des widgets de l'éditeur. La couleur est utilisée uniquement si le widget choisit d'avoir une bordure et si la couleur n'est pas remplacée par un widget.", "editorSelectionBackground": "Couleur de la sélection de l'éditeur.", "editorSelectionForeground": "Couleur du texte sélectionné pour le contraste élevé.", - "editorInactiveSelection": "Couleur de la sélection dans un éditeur inactif.", - "editorSelectionHighlight": "Couleur des régions dont le contenu est identique à la sélection.", + "editorInactiveSelection": "Couleur de sélection dans un éditeur inactif. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "editorSelectionHighlight": "Couleur des régions avec le même contenu que la sélection. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "editorFindMatch": "Couleur du résultat de recherche actif.", - "findMatchHighlight": "Couleur des autres résultats de recherche.", - "findRangeHighlight": "Couleur de la plage limitant la recherche.", - "hoverHighlight": "Mettez en surbrillance ci-dessous le mot pour lequel un pointage s'affiche.", + "findMatchHighlight": "Couleur des autres résultats de recherche correspondants. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "findRangeHighlight": "Couleur de la plage limitant la recherche. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "hoverHighlight": "Mettre en surbrillance ci-dessous le mot pour lequel un survol est affiché. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "hoverBackground": "Couleur d'arrière-plan du pointage de l'éditeur.", "hoverBorder": "Couleur de bordure du pointage de l'éditeur.", "activeLinkForeground": "Couleur des liens actifs.", @@ -76,12 +76,12 @@ "diffEditorRemoved": "Couleur d'arrière-plan du texte supprimé.", "diffEditorInsertedOutline": "Couleur de contour du texte inséré.", "diffEditorRemovedOutline": "Couleur de contour du texte supprimé.", - "mergeCurrentHeaderBackground": "Arrière-plan de l'en-tête actuel dans les conflits de fusion inline.", - "mergeCurrentContentBackground": "Arrière-plan du contenu actuel dans les conflits de fusion inline.", - "mergeIncomingHeaderBackground": "Arrière-plan de l'en-tête entrant dans les conflits de fusion inline.", - "mergeIncomingContentBackground": "Arrière-plan du contenu entrant dans les conflits de fusion inline.", - "mergeCommonHeaderBackground": "Arrière-plan de l'en-tête de l'ancêtre commun dans les conflits de fusion inline.", - "mergeCommonContentBackground": "Arrière-plan du contenu de l'ancêtre commun dans les conflits de fusion inline.", + "mergeCurrentHeaderBackground": "Arrière-plan de l'en-tête en cours dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeCurrentContentBackground": "Arrière-plan du contenu en cours dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeIncomingHeaderBackground": "Arrière-plan de l'en-tête qui arrive dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeIncomingContentBackground": "Arrière-plan du contenu qui arrive dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeCommonHeaderBackground": "Arrière-plan de l'en-tête de l'ancêtre commun dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", + "mergeCommonContentBackground": "Arrière-plan du contenu de l'ancêtre commun dans les conflits de fusion inline. La couleur doit ne pas être opaque afin de ne pas masquer les décorations sous-jacentes.", "mergeBorder": "Couleur de bordure des en-têtes et du séparateur dans les conflits de fusion inline.", "overviewRulerCurrentContentForeground": "Premier plan de la règle d'aperçu actuelle pour les conflits de fusion inline.", "overviewRulerIncomingContentForeground": "Premier plan de la règle d'aperçu entrante pour les conflits de fusion inline.", diff --git a/i18n/fra/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/fra/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..1c77d004aae --- /dev/null +++ b/i18n/fra/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "la propriété '{0}' est obligatoire et doit être de type 'string'", + "optstring": "La propriété '{0}' peut être omise ou doit être de type 'string'" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/fra/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/fra/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 2c25d01eeb1..2475bc3e519 100644 --- a/i18n/fra/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/fra/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "Aucune arborescence avec l'ID '{0}' n'est inscrite.", - "treeItem.notFound": "L'élément d'arborescence avec l'ID '{0}' est introuvable.", - "treeView.duplicateElement": "L'élément '{0}' est déjà inscrit" + "treeView.duplicateElement": "L'élément avec l'id {0} est déjà inscrit" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/fra/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 0ea0c59d765..053ff77f9f9 100644 --- a/i18n/fra/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Activer/désactiver l'emplacement de la barre latérale", + "toggleSidebarPosition": "Activer/désactiver la position de la barre latérale", "view": "Affichage" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 6158fd5950f..3bffd603d63 100644 --- a/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Ouvrir un fichier...", "openFolder": "Ouvrir un dossier...", "openFileFolder": "Ouvrir...", - "addFolderToWorkspace": "Ajouter un dossier à l'espace de travail...", - "add": "&&Ajouter", - "addFolderToWorkspaceTitle": "Ajouter un dossier à l'espace de travail", "globalRemoveFolderFromWorkspace": "Supprimer le dossier d’espace de travail...", - "removeFolderFromWorkspace": "Supprimer le dossier de l'espace de travail", - "openFolderSettings": "Ouvrir le dossier Paramètres", "saveWorkspaceAsAction": "Enregistrer l’espace de travail sous...", "save": "&&Enregistrer", "saveWorkspace": "Enregistrer l’espace de travail", "openWorkspaceAction": "Ouvrir un espace de travail...", "openWorkspaceConfigFile": "Ouvrir le Fichier de Configuration d’espace de travail", - "openFolderAsWorkspaceInNewWindow": "Ouvrir le dossier en tant qu'espace de travail dans une nouvelle fenêtre", - "workspaceFolderPickerPlaceholder": "Sélectionner le dossier de l’espace de travail" + "openFolderAsWorkspaceInNewWindow": "Ouvrir le dossier en tant qu'espace de travail dans une nouvelle fenêtre" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/fra/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..b644d1c9572 --- /dev/null +++ b/i18n/fra/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Ajouter un dossier à l'espace de travail...", + "add": "&&Ajouter", + "addFolderToWorkspaceTitle": "Ajouter un dossier à l'espace de travail", + "workspaceFolderPickerPlaceholder": "Sélectionner le dossier de l’espace de travail" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 4326e29e9e4..22a325e3fa6 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "Afficher les éditeurs du troisième groupe", "allEditorsPicker": "Afficher tous les éditeurs ouverts", "view": "Affichage", - "file": "Fichier" + "file": "Fichier", + "close": "Fermer", + "closeOthers": "Fermer les autres", + "closeRight": "Fermer à droite", + "closeAllUnmodified": "Fermer les éléments non modifiés", + "closeAll": "Tout fermer", + "keepOpen": "Garder ouvert", + "toggleInlineView": "Activer/désactiver l'affichage Inline", + "showOpenedEditors": "Afficher les éditeurs ouverts", + "keepEditor": "Conserver l'éditeur", + "closeEditorsInGroup": "Fermer tous les éditeurs du groupe", + "closeUnmodifiedEditors": "Fermer les éditeurs non modifiés du groupe", + "closeOtherEditors": "Fermer les autres éditeurs", + "closeRightEditors": "Fermer les éditeurs situés à droite" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 19586632ac8..a2562d91fe9 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Fermer l'éditeur", "revertAndCloseActiveEditor": "Restaurer et fermer l'éditeur", "closeEditorsToTheLeft": "Fermer les éditeurs situés à gauche", - "closeEditorsToTheRight": "Fermer les éditeurs situés à droite", "closeAllEditors": "Fermer tous les éditeurs", - "closeUnmodifiedEditors": "Fermer les éditeurs non modifiés du groupe", "closeEditorsInOtherGroups": "Fermer les éditeurs des autres groupes", - "closeOtherEditorsInGroup": "Fermer les autres éditeurs", - "closeEditorsInGroup": "Fermer tous les éditeurs du groupe", "moveActiveGroupLeft": "Déplacer le groupe d'éditeurs vers la gauche", "moveActiveGroupRight": "Déplacer le groupe d'éditeurs vers la droite", "minimizeOtherEditorGroups": "Réduire les autres groupes d'éditeurs", "evenEditorGroups": "Même largeur pour le groupe d'éditeurs", "maximizeEditor": "Agrandir le groupe d'éditeurs et masquer la barre latérale", - "keepEditor": "Conserver l'éditeur", "openNextEditor": "Ouvrir l'éditeur suivant", "openPreviousEditor": "Ouvrir l'éditeur précédent", "nextEditorInGroup": "Ouvrir l'éditeur suivant du groupe", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Afficher les éditeurs du premier groupe", "showEditorsInSecondGroup": "Afficher les éditeurs du deuxième groupe", "showEditorsInThirdGroup": "Afficher les éditeurs du troisième groupe", - "showEditorsInGroup": "Afficher les éditeurs du groupe", "showAllEditors": "Afficher tous les éditeurs", "openPreviousRecentlyUsedEditorInGroup": "Ouvrir l'éditeur précédent du groupe", "openNextRecentlyUsedEditorInGroup": "Ouvrir l'éditeur suivant du groupe", @@ -54,5 +48,8 @@ "moveEditorLeft": "Déplacer l'éditeur vers la gauche", "moveEditorRight": "Déplacer l'éditeur vers la droite", "moveEditorToPreviousGroup": "Déplacer l'éditeur vers le groupe précédent", - "moveEditorToNextGroup": "Déplacer l'éditeur vers le groupe suivant" + "moveEditorToNextGroup": "Déplacer l'éditeur vers le groupe suivant", + "moveEditorToFirstGroup": "Déplacer l'éditeur vers le premier groupe", + "moveEditorToSecondGroup": "Déplacer l'éditeur vers le second groupe", + "moveEditorToThirdGroup": "Déplacer l'éditeur vers le troisième groupe" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index be96f08df0d..5dc335cf48b 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Déplacer l'éditeur actif par onglets ou par groupes", "editorCommand.activeEditorMove.arg.name": "Argument de déplacement de l'éditeur actif", - "editorCommand.activeEditorMove.arg.description": "Propriétés d’argument : * 'to' : Valeur de chaîne spécifiant où aller.\n\t* 'by' : Valeur de chaîne spécifiant l'unité à déplacer. Par tabulation ou par groupe.\n\t* 'value' : Valeur numérique spécifiant combien de positions ou une position absolue à déplacer.", - "commandDeprecated": "La commande **{0}** a été supprimée. Vous pouvez utiliser **{1}** à la place", - "openKeybindings": "Configurer les raccourcis clavier" + "editorCommand.activeEditorMove.arg.description": "Propriétés d’argument : * 'to' : Valeur de chaîne spécifiant où aller.\n\t* 'by' : Valeur de chaîne spécifiant l'unité à déplacer. Par tabulation ou par groupe.\n\t* 'value' : Valeur numérique spécifiant combien de positions ou une position absolue à déplacer." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 92e9eaf8779..3a04eca1120 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Éditeur de comparaison de fichier texte.", "navigate.next.label": "Modification suivante", "navigate.prev.label": "Modification précédente", - "inlineDiffLabel": "Passer au mode inline", - "sideBySideDiffLabel": "Passer au mode Côte à côte" + "toggleIgnoreTrimWhitespace.label": "Ignorer la suppression des espaces" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 99c0ec41f61..a0384c94b7a 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Fermer", - "closeOthers": "Fermer les autres", - "closeRight": "Fermer à droite", - "closeAll": "Tout fermer", - "closeAllUnmodified": "Fermer les éléments non modifiés", - "keepOpen": "Garder ouvert", - "showOpenedEditors": "Afficher les éditeurs ouverts", "araLabelEditorActions": "Actions de l'éditeur" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index d9f31d9c850..3d0b4541c12 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Non prise en charge]", + "userIsAdmin": "[Administrator]", + "userIsSudo": "[Superuser]", "devExtensionWindowTitlePrefix": "[Hôte de développement d'extension]" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/fra/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index 3ed5e9fc685..dd1dfbd52dd 100644 --- a/i18n/fra/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/fra/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "Masquer dans la barre latérale" + "hideView": "Masquer" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/common/theme.i18n.json b/i18n/fra/src/vs/workbench/common/theme.i18n.json index 0082e6d4ec1..42755eb915e 100644 --- a/i18n/fra/src/vs/workbench/common/theme.i18n.json +++ b/i18n/fra/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "Couleur d'arrière-plan de l'onglet actif. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", "tabInactiveBackground": "Couleur d'arrière-plan de l'onglet inactif. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", + "tabHoverBackground": "Couleur de l'onglet d’arrière-plan lors du survol. Les onglets sont les conteneurs pour les éditeurs dans la zone de l’éditeur. Plusieurs onglets peuvent être ouverts dans un groupe d'éditeur. Il peut y avoir plusieurs groupes d’éditeur.", + "tabUnfocusedHoverBackground": "Couleur de l'onglet d’arrière-plan dans un groupe n'ayant pas le focus lors du survol. Les onglets sont les conteneurs pour les éditeurs dans la zone de l’éditeur. Plusieurs onglets peuvent être ouverts dans un groupe d'éditeur. Il peut y avoir plusieurs groupes d’éditeur.", "tabBorder": "Bordure séparant les onglets les uns des autres. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", "tabActiveBorder": "Bordure pour mettre en évidence les onglets actifs. Les onglets sont les conteneurs des éditeurs dans la zone d'édition. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", "tabActiveUnfocusedBorder": "Bordure pour mettre en évidence les onglets actifs dans un groupe inactif. Les onglets sont les conteneurs des éditeurs dans la zone d'édition. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", + "tabHoverBorder": "Bordure avec laquelle surligner les onglets lors du survol. Couleur de l'onglet d’arrière-plan dans un groupe n'ayant pas le focus lors du survol. Les onglets sont les conteneurs pour les éditeurs dans la zone de l’éditeur. Plusieurs onglets peuvent être ouverts dans un groupe d'éditeur. Il peut y avoir plusieurs groupes d’éditeur.", + "tabUnfocusedHoverBorder": "Bordure avec laquelle surligner les onglets lors du survol dans un groupe n'ayant pas le focus. Couleur de l'onglet d’arrière-plan dans un groupe n'ayant pas le focus lors du survol. Les onglets sont les conteneurs pour les éditeurs dans la zone de l’éditeur. Plusieurs onglets peuvent être ouverts dans un groupe d'éditeur. Il peut y avoir plusieurs groupes d’éditeur.", "tabActiveForeground": "Couleur de premier plan de l'onglet actif dans un groupe actif. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", "tabInactiveForeground": "Couleur de premier plan de l'onglet inactif dans un groupe actif. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", "tabUnfocusedActiveForeground": "Couleur de premier plan de l'onglet actif dans un groupe inactif. Les onglets sont les conteneurs des éditeurs dans la zone d'éditeurs. Vous pouvez ouvrir plusieurs onglets dans un groupe d'éditeurs. Il peut exister plusieurs groupes d'éditeurs.", @@ -16,7 +20,7 @@ "editorGroupBackground": "Couleur d'arrière-plan d'un groupe d'éditeurs. Les groupes d'éditeurs sont les conteneurs des éditeurs. La couleur d'arrière-plan s'affiche pendant le glissement de groupes d'éditeurs.", "tabsContainerBackground": "Couleur d'arrière-plan de l'en-tête du titre du groupe d'éditeurs quand les onglets sont activés. Les groupes d'éditeurs sont les conteneurs des éditeurs.", "tabsContainerBorder": "Couleur de bordure de l'en-tête du titre du groupe d'éditeurs quand les onglets sont activés. Les groupes d'éditeurs sont les conteneurs des éditeurs.", - "editorGroupHeaderBackground": "Couleur d'arrière-plan de l'en-tête du titre du groupe d'éditeurs quand les onglets sont désactivés. Les groupes d'éditeurs sont les conteneurs des éditeurs.", + "editorGroupHeaderBackground": "Couleur d'arrière-plan de l'en-tête du titre du groupe d'éditeurs quand les onglets sont désactivés (`\"workbench.editor.showTabs\": false`). Les groupes d'éditeurs sont les conteneurs des éditeurs.", "editorGroupBorder": "Couleur séparant plusieurs groupes d'éditeurs les uns des autres. Les groupes d'éditeurs sont les conteneurs des éditeurs.", "editorDragAndDropBackground": "Couleur d'arrière-plan lors du déplacement des éditeurs par glissement. La couleur doit avoir une transparence pour que le contenu de l'éditeur soit visible à travers.", "panelBackground": "Couleur d'arrière-plan du panneau. Les panneaux s'affichent sous la zone d'éditeurs et contiennent des affichages tels que la sortie et le terminal intégré.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "Couleur de la bordure qui sépare la barre latérale et l’éditeur lorsque aucun dossier ne s’ouvre la barre d’état. La barre d’état s’affiche en bas de la fenêtre.", "statusBarItemActiveBackground": "Couleur d'arrière-plan de l'élément de la barre d'état durant un clic. La barre d'état est affichée en bas de la fenêtre.", "statusBarItemHoverBackground": "Couleur d'arrière-plan de l'élément de la barre d'état durant un pointage. La barre d'état est affichée en bas de la fenêtre.", - "statusBarProminentItemBackground": "Couleur d'arrière-plan des éléments importants de la barre d'état. Les éléments importants se différencient des autres entrées de la barre d'état pour indiquer l'importance. La barre d'état est affichée en bas de la fenêtre.", - "statusBarProminentItemHoverBackground": "Couleur d'arrière-plan des éléments importants de la barre d'état pendant le pointage. Les éléments importants se différencient des autres entrées de la barre d'état pour indiquer l'importance. La barre d'état est affichée en bas de la fenêtre.", + "statusBarProminentItemBackground": "Couleur d'arrière-plan des éléments importants de la barre d'état. Les éléments importants se différencient des autres entrées de la barre d'état pour indiquer l'importance. Changer le mode `Appuyer sur la touche tabulation déplace le focus` depuis la palette de commandes pour voir un exemple. La barre d'état est affichée en bas de la fenêtre.", + "statusBarProminentItemHoverBackground": "Couleur d'arrière-plan des éléments importants de la barre d'état lors du survol. Les éléments importants se différencient des autres entrées de la barre d'état pour indiquer l'importance. Changer le mode `Appuyer sur la touche tabulation déplace le focus` depuis la palette de commandes pour voir un exemple. La barre d'état est affichée en bas de la fenêtre.", "activityBarBackground": "Couleur d'arrière-plan de la barre d'activités. La barre d'activités s'affiche complètement à gauche ou à droite, et permet de naviguer entre les affichages de la barre latérale.", "activityBarForeground": "Couleur de premier plan de la barre d'activités (par ex., utilisée pour les icônes). La barre d'activités s'affiche complètement à gauche ou à droite, et permet de parcourir les vues de la barre latérale.", "activityBarBorder": "Couleur de bordure de la barre d'activités faisant la séparation avec la barre latérale. La barre d'activités, située à l'extrême droite ou gauche, permet de parcourir les vues de la barre latérale.", diff --git a/i18n/fra/src/vs/workbench/common/views.i18n.json b/i18n/fra/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..e7ba8e9e54b --- /dev/null +++ b/i18n/fra/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Une vue avec l’id `{0}` est déjà enregistrée à l’emplacement `{1}`" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json index 541429a5408..93919d9a851 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Fermer l'éditeur", "closeWindow": "Fermer la fenêtre", "closeWorkspace": "Fermer l’espace de travail", "noWorkspaceOpened": "Il n’y a actuellement aucun espace de travail ouvert dans cette instance à fermer.", @@ -52,21 +51,5 @@ "displayLanguage": "Définit le langage affiché par VSCode.", "doc": "Consultez {0} pour connaître la liste des langues prises en charge.", "restart": "Le changement de la valeur nécessite le redémarrage de VS Code.", - "fail.createSettings": "Impossible de créer '{0}' ({1}).", - "openLogsFolder": "Ouvrir le dossier des journaux", - "showLogs": "Afficher les journaux...", - "mainProcess": "Principal", - "sharedProcess": "Partagé", - "rendererProcess": "Renderer", - "extensionHost": "Hôte de l’extension", - "selectProcess": "Sélectionner le processus", - "setLogLevel": "Définir le niveau de journalisation (log)", - "trace": "Trace", - "debug": "Déboguer", - "info": "Informations", - "warn": "Avertissement", - "err": "Erreur", - "critical": "Critique", - "off": "Désactivé", - "selectLogLevel": "Sélectionner le niveau de journalisation (log)" + "fail.createSettings": "Impossible de créer '{0}' ({1})." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json index 7c7573087ca..d44b504894c 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Affichage", "help": "Aide", "file": "Fichier", - "developer": "Développeur", "workspaces": "Espaces de travail", + "developer": "Développeur", + "workbenchConfigurationTitle": "Banc d'essai", "showEditorTabs": "Contrôle si les éditeurs ouverts doivent s'afficher ou non sous des onglets.", "workbench.editor.labelFormat.default": "Afficher le nom du fichier. Lorsque les onglets sont activés et que deux fichiers portent le même nom dans un groupe, les sections distinctes du chemin de chaque fichier sont ajoutées. Lorsque les onglets sont désactivées, le chemin d’accès relatif au dossier de l'espace de travail est affiché si l’éditeur est actif.", "workbench.editor.labelFormat.short": "Indiquer le nom du fichier suivi de son nom de répertoire.", @@ -20,23 +21,23 @@ "showIcons": "Contrôle si les éditeurs ouverts doivent s'afficher ou non avec une icône. Cela implique notamment l'activation d'un thème d'icône.", "enablePreview": "Contrôle si les éditeurs ouverts s'affichent en mode aperçu. Les éditeurs en mode aperçu sont réutilisés jusqu'à ce qu'ils soient conservés (par exemple, après un double-clic ou une modification) et apparaissent avec un style de police en italique.", "enablePreviewFromQuickOpen": "Contrôle si les éditeurs de Quick Open s'affichent en mode aperçu. Les éditeurs en mode aperçu sont réutilisés jusqu'à ce qu'ils soient conservés (par exemple, après un double-clic ou une modification).", + "closeOnFileDelete": "Contrôle si les éditeurs qui affichent un fichier doivent se fermer automatiquement quand ce fichier est supprimé ou renommé par un autre processus. Si vous désactivez cette option, l'éditeur reste ouvert dans un état indiquant une intégrité compromise. Notez que la suppression de fichiers à partir de l'application entraîne toujours la fermeture de l'éditeur, et que les fichiers à l'intégrité compromise ne sont jamais fermés pour permettre la conservation de vos données.", "editorOpenPositioning": "Permet de définir à quel endroit les éditeurs s'ouvrent. Sélectionnez 'left' ou 'right' pour ouvrir les éditeurs à gauche ou à droite de celui actuellement actif. Sélectionnez 'first' ou 'last' pour ouvrir les éditeurs indépendamment de celui actuellement actif.", "revealIfOpen": "Contrôle si un éditeur est affiché dans l'un des groupes visibles, s'il est ouvert. Si cette option est désactivée, l'éditeur s'ouvre de préférence dans le groupe d'éditeurs actif. Si cette option est activée, tout éditeur déjà ouvert est affiché au lieu d'être rouvert dans le groupe d'éditeurs actif. Notez que dans certains cas, ce paramètre est ignoré, par exemple quand vous forcez un éditeur à s'ouvrir dans un groupe spécifique ou à côté du groupe actif.", + "swipeToNavigate": "Parcourez les fichiers ouverts en faisant glisser trois doigts horizontalement. ", "commandHistory": "Contrôle le nombre de commandes récemment utilisées à retenir dans l’historique de la palette de commande. Spécifier la valeur 0 pour désactiver l’historique des commandes.", "preserveInput": "Contrôle si la dernière entrée tapée dans la palette de commandes doit être restaurée à la prochaine ouverture.", "closeOnFocusLost": "Contrôle si Quick Open doit se fermer automatiquement, une fois qu'il a perdu le focus.", "openDefaultSettings": "Contrôle si l'ouverture des paramètres entraîne également l'ouverture d'un éditeur qui affiche tous les paramètres par défaut.", "sideBarLocation": "Contrôle l'emplacement de la barre latérale. Elle peut s'afficher à gauche ou à droite du banc d'essai.", + "panelDefaultLocation": "Contrôle l’emplacement par défaut du panneau. Il peut être affiché soit en bas ou à droite du banc d'essai.", "statusBarVisibility": "Contrôle la visibilité de la barre d'état au bas du banc d'essai.", "activityBarVisibility": "Contrôle la visibilité de la barre d'activités dans le banc d'essai.", - "closeOnFileDelete": "Contrôle si les éditeurs qui affichent un fichier doivent se fermer automatiquement quand ce fichier est supprimé ou renommé par un autre processus. Si vous désactivez cette option, l'éditeur reste ouvert dans un état indiquant une intégrité compromise. Notez que la suppression de fichiers à partir de l'application entraîne toujours la fermeture de l'éditeur, et que les fichiers à l'intégrité compromise ne sont jamais fermés pour permettre la conservation de vos données.", - "enableNaturalLanguageSettingsSearch": "Contrôle s’il faut activer le mode de recherche en langage naturel pour les paramètres.", "fontAliasing": "Contrôle la méthode de font aliasing dans le workbench.\n- par défaut : Lissage des polices de sous-pixel. Sur la plupart des affichages non-ratina, cela vous donnera le texte le plus vif\n- crénelées : Lisse les polices au niveau du pixel, plutôt que les sous-pixels. Peut faire en sorte que la police apparaisse plus légère dans l’ensemble \n- none : désactive le lissage des polices. Le texte s'affichera avec des bordures dentelées", "workbench.fontAliasing.default": "Lissage de sous-pixel des polices. Sur la plupart des affichages non-retina, cela vous donnera le texte le plus vif.", "workbench.fontAliasing.antialiased": "Lisser les polices au niveau du pixel, plutôt que les sous-pixels. Peut faire en sorte que la police apparaisse plus légère dans l’ensemble.", "workbench.fontAliasing.none": "Désactive le lissage des polices. Le texte s'affichera avec des bordures dentelées.", - "swipeToNavigate": "Parcourez les fichiers ouverts en faisant glisser trois doigts horizontalement. ", - "workbenchConfigurationTitle": "Banc d'essai", + "enableNaturalLanguageSettingsSearch": "Contrôle s’il faut activer le mode de recherche en langage naturel pour les paramètres.", "windowConfigurationTitle": "Fenêtre", "window.openFilesInNewWindow.on": "Les fichiers s'ouvrent dans une nouvelle fenêtre", "window.openFilesInNewWindow.off": "Les fichiers s'ouvrent dans la fenêtre du dossier conteneur ouvert ou dans la dernière fenêtre active", diff --git a/i18n/fra/src/vs/workbench/electron-browser/window.i18n.json b/i18n/fra/src/vs/workbench/electron-browser/window.i18n.json index 96dc00191af..25e0b269de1 100644 --- a/i18n/fra/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/fra/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Couper", "copy": "Copier", "paste": "Coller", - "selectAll": "Tout Sélectionner" + "selectAll": "Tout Sélectionner", + "runningAsRoot": "Il est déconseillé d’exécuter {0} en tant qu’utilisateur root." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index 2cfe628ea39..07d9f8f5644 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "Couleur d'arrière-plan de la barre d'outils de débogage." + "debugToolBarBackground": "Couleur d'arrière-plan de la barre d'outils de débogage.", + "debugToolBarBorder": "Couleur de bordure de la barre d'outils de débogage." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 5a3987eaa76..64badf8518f 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "Configurations de schéma JSON pour la validation de 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Paramètres spécifiques à Windows.", "vscode.extension.contributes.debuggers.windows.runtime": "Runtime utilisé pour Windows.", - "vscode.extension.contributes.debuggers.osx": "Paramètres spécifiques à OS X.", - "vscode.extension.contributes.debuggers.osx.runtime": "Runtime utilisé pour OS X.", "vscode.extension.contributes.debuggers.linux": "Paramètres spécifiques à Linux.", "vscode.extension.contributes.debuggers.linux.runtime": "Runtime utilisé pour Linux.", "vscode.extension.contributes.breakpoints": "Ajoute des points d'arrêt.", diff --git a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 6740cff8f8e..c08a897c7ff 100644 --- a/i18n/fra/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "élément débogué", - "debug.terminal.not.available.error": "Terminal intégré non disponible" + "debug.terminal.title": "élément débogué" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 8fadf8b958b..f5bf621cde9 100644 --- a/i18n/fra/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Ouvrir une nouvelle invite de commandes", "globalConsoleActionMacLinux": "Ouvrir un nouveau Terminal", "scopedConsoleActionWin": "Ouvrir dans l'invite de commandes", - "scopedConsoleActionMacLinux": "Ouvrir dans Terminal", - "openFolderInIntegratedTerminal": "Ouvrir dans Terminal" + "scopedConsoleActionMacLinux": "Ouvrir dans Terminal" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 32c0006fd67..01219f8b3f8 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Cette extension est recommandée basé sur les fichiers que vous avez ouverts récemment.", + "neverShowAgain": "Ne plus afficher", + "close": "Fermer", "workspaceRecommendation": "Cette extension est recommandée par les utilisateurs de l’espace de travail actuel.", + "fileBasedRecommendation": "Cette extension est recommandée basé sur les fichiers que vous avez ouverts récemment.", "exeBasedRecommendation": "Cette extension est recommandée parce que {0} est installé.", "reallyRecommended2": "L'extension '{0}' est recommandée pour ce type de fichier.", "reallyRecommendedExtensionPack": "Le pack d’extensions '{0}' est recommandé pour ce type de fichier.", "showRecommendations": "Afficher les recommandations", "install": "Installer", - "neverShowAgain": "Ne plus afficher", - "close": "Fermer", + "showLanguageExtensions": "Le Marketplace a des extensions qui peuvent aider avec les fichiers '.{0}'", + "searchMarketplace": "Rechercher dans le Marketplace", "workspaceRecommended": "Cet espace de travail a des recommandations d'extension.", "installAll": "Tout installer", "ignoreExtensionRecommendations": "Voulez-vous ignorer toutes les recommandations d’extensions ?", diff --git a/i18n/fra/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/fra/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index 8ea9b909100..b3a917afeda 100644 --- a/i18n/fra/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "Installation d'extension depuis un VSIX...", + "installingMarketPlaceExtension": "Installation d'extension depuis le Marketplace...", + "uninstallingExtension": "Désinstallation d'extension...", "enableDependeciesConfirmation": "L'activation de '{0}' entraîne également l'activation de ses dépendances. Voulez-vous continuer ?", "enable": "Oui", "doNotEnable": "Non", diff --git a/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..2cd1d40a124 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Banc d'essai", + "feedbackVisibility": "Contrôle la visibilité du feedback Twitter (smiley) dans la barre d'état au bas du banc d'essai." +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index a7605d084cd..45a05b23cfe 100644 --- a/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "Demander une fonctionnalité manquante", "tell us why?": "Pourquoi ?", "commentsHeader": "Commentaires", + "showFeedback": "Afficher le Smiley Feedback dans la barre d'état", "tweet": "Tweet", "character left": "caractère restant", "characters left": "caractères restants", diff --git a/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..16a5fa73cb2 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "Masquer" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 54a25f75ec0..1b0804c3433 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "Fichier", "revealInSideBar": "Afficher dans la barre latérale", "acceptLocalChanges": "Utiliser vos modifications et écraser les contenus du disque", - "revertLocalChanges": "Ignorer les modifications locales et restaurer le contenu sur disque" + "revertLocalChanges": "Ignorer les modifications locales et restaurer le contenu sur disque", + "copyPathOfActive": "Copier le chemin du fichier actif", + "saveAllInGroup": "Enregistrer tout dans le groupe", + "saveFiles": "Enregistrer tous les fichiers", + "revert": "Rétablir le fichier", + "compareActiveWithSaved": "Compare le fichier actif avec celui enregistré", + "closeEditor": "Fermer l'éditeur", + "view": "Affichage", + "openToSide": "Ouvrir sur le côté", + "revealInWindows": "Révéler dans l'Explorateur", + "revealInMac": "Révéler dans le Finder", + "openContainer": "Ouvrir le dossier contenant", + "copyPath": "Copier le chemin", + "saveAll": "Enregistrer tout", + "compareWithSaved": "Comparer avec celui enregistré", + "compareWithSelected": "Comparer avec ce qui est sélectionné", + "compareSource": "Sélectionner pour comparer", + "compareSelected": "Comparer le sélectionné", + "close": "Fermer", + "closeOthers": "Fermer les autres", + "closeUnmodified": "Fermer les éléments non modifiés", + "closeAll": "Tout fermer", + "deleteFile": "Supprimer définitivement" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 002c86e7daa..90edc5bf9f2 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Réessayer", - "rename": "Renommer", "newFile": "Nouveau fichier", "newFolder": "Nouveau dossier", + "rename": "Renommer", + "delete": "Supprimer", + "copyFile": "Copier", + "pasteFile": "Coller", + "retry": "Réessayer", "openFolderFirst": "Ouvrez d'abord un dossier pour y créer des fichiers ou des dossiers.", "newUntitledFile": "Nouveau fichier sans titre", "createNewFile": "Nouveau fichier", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "&&Déplacer vers la Corbeille", "deleteButtonLabelTrash": "&&Déplacer vers la Poubelle", "deleteButtonLabel": "S&&upprimer", + "dirtyMessageFilesDelete": "Vous supprimez des fichiers dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyMessageFolderOneDelete": "Vous supprimez un dossier contenant 1 fichier dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyMessageFolderDelete": "Vous supprimez un dossier contenant {0} fichiers dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyMessageFileDelete": "Vous supprimez un fichier dont les changements n'ont pas été enregistrés. Voulez-vous continuer ?", "dirtyWarning": "Vous perdrez vos modifications, si vous ne les enregistrez pas.", + "confirmMoveTrashMessageMultiple": "Êtes-vous sûr de vouloir supprimer les fichiers {0} suivants ?", "confirmMoveTrashMessageFolder": "Voulez-vous vraiment supprimer '{0}' et son contenu ?", "confirmMoveTrashMessageFile": "Voulez-vous vraiment supprimer '{0}' ?", "undoBin": "Vous pouvez effectuer une restauration à partir de la Corbeille.", "undoTrash": "Vous pouvez effectuer une restauration à partir de la Poubelle.", "doNotAskAgain": "Ne plus me demander", + "confirmDeleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer définitivement les fichiers {0} suivants ?", "confirmDeleteMessageFolder": "Voulez-vous vraiment supprimer définitivement '{0}' et son contenu ?", "confirmDeleteMessageFile": "Voulez-vous vraiment supprimer définitivement '{0}' ?", "irreversible": "Cette action est irréversible !", "permDelete": "Supprimer définitivement", - "delete": "Supprimer", "importFiles": "Importer des fichiers", "confirmOverwrite": "Un fichier ou dossier portant le même nom existe déjà dans le dossier de destination. Voulez-vous le remplacer ?", "replaceButtonLabel": "&&Remplacer", - "copyFile": "Copier", - "pasteFile": "Coller", + "fileDeleted": "Le fichier a été supprimé ou déplacé pendant ce temps", + "fileIsAncestor": "Le fichier à copier est un ancêtre du dossier destination", "duplicateFile": "Doublon", - "openToSide": "Ouvrir sur le côté", - "compareSource": "Sélectionner pour comparer", "globalCompareFile": "Comparer le fichier actif à...", "openFileToCompare": "Ouvrez d'abord un fichier pour le comparer à un autre fichier.", - "compareWith": "Comparer '{0}' à '{1}'", - "compareFiles": "Comparer des fichiers", "refresh": "Actualiser", - "save": "Enregistrer", - "saveAs": "Enregistrer sous...", - "saveAll": "Enregistrer tout", "saveAllInGroup": "Enregistrer tout dans le groupe", - "saveFiles": "Enregistrer tous les fichiers", - "revert": "Rétablir le fichier", "focusOpenEditors": "Mettre le focus sur la vue des éditeurs ouverts", "focusFilesExplorer": "Focus sur l'Explorateur de fichiers", "showInExplorer": "Révéler le fichier actif dans la barre latérale", @@ -56,20 +52,11 @@ "refreshExplorer": "Actualiser l'explorateur", "openFileInNewWindow": "Ouvrir le fichier actif dans une nouvelle fenêtre", "openFileToShowInNewWindow": "Ouvrir d'abord un fichier à ouvrir dans une nouvelle fenêtre", - "revealInWindows": "Révéler dans l'Explorateur", - "revealInMac": "Révéler dans le Finder", - "openContainer": "Ouvrir le dossier contenant", - "revealActiveFileInWindows": "Révéler le fichier actif dans l'Explorateur Windows", - "revealActiveFileInMac": "Révéler le fichier actif dans le Finder", - "openActiveFileContainer": "Ouvrir le dossier contenant le fichier actif", "copyPath": "Copier le chemin", - "copyPathOfActive": "Copier le chemin du fichier actif", "emptyFileNameError": "Un nom de fichier ou de dossier doit être fourni.", "fileNameExistsError": "Un fichier ou dossier **{0}** existe déjà à cet emplacement. Choisissez un autre nom.", "invalidFileNameError": "Le nom **{0}** est non valide en tant que nom de fichier ou de dossier. Choisissez un autre nom.", "filePathTooLongError": "Le nom **{0}** correspond à un chemin d'accès trop long. Choisissez un nom plus court.", - "compareWithSaved": "Compare le fichier actif avec celui enregistré", - "modifiedLabel": "{0} (sur le disque) ↔ {1}", "compareWithClipboard": "Compare le fichier actif avec le presse-papiers", "clipboardComparisonLabel": "Presse-papier ↔ {0}" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index ee5d441071a..a8dcaebe5a2 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Ouvrir d'abord un fichier pour copier son chemin", - "openFileToReveal": "Ouvrir d'abord un fichier à révéler" + "revealInWindows": "Révéler dans l'Explorateur", + "revealInMac": "Révéler dans le Finder", + "openContainer": "Ouvrir le dossier contenant", + "saveAs": "Enregistrer sous...", + "save": "Enregistrer", + "saveAll": "Enregistrer tout", + "removeFolderFromWorkspace": "Supprimer le dossier de l'espace de travail", + "genericRevertError": "Échec pour faire revenir '{0}' : {1}", + "modifiedLabel": "{0} (sur le disque) ↔ {1}", + "openFileToReveal": "Ouvrir d'abord un fichier à révéler", + "openFileToCopy": "Ouvrir d'abord un fichier pour copier son chemin" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 9693ca31c50..9427b00fc2a 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "Éditeur", "formatOnSave": "Met en forme un fichier au moment de l'enregistrement. Un formateur doit être disponible, le fichier ne doit pas être enregistré automatiquement, et l'éditeur ne doit pas être en cours d'arrêt.", "explorerConfigurationTitle": "Explorateur de fichiers", - "openEditorsVisible": "Nombre d'éditeurs affichés dans le volet Éditeurs ouverts. Définissez la valeur 0 pour masquer le volet.", - "dynamicHeight": "Contrôle si la hauteur de la section des éditeurs ouverts doit s'adapter dynamiquement ou non au nombre d'éléments.", + "openEditorsVisible": "Nombre d'éditeurs affichés dans le volet Éditeurs ouverts.", "autoReveal": "Contrôle si l'Explorateur doit automatiquement afficher et sélectionner les fichiers à l'ouverture.", "enableDragAndDrop": "Contrôle si l'explorateur doit autoriser le déplacement de fichiers et de dossiers par glisser-déplacer.", "confirmDragAndDrop": "Contrôle si l’Explorateur doit demander confirmation lors du déplacement de fichiers ou de dossiers via glisser-déposer.", diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index f944e7fc14f..0c4d859caa4 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Utiliser les actions dans la barre d’outils de l’éditeur vers la droite pour soit **annuler** vos modifications ou **écraser** le contenu sur le disque avec vos modifications", - "discard": "Abandonner", + "overwriteElevated": "Remplacer en tant qu'Admin...", + "saveElevated": "Réessayer en tant qu'Admin...", "overwrite": "Remplacer", "retry": "Réessayer", - "readonlySaveError": "Échec de l'enregistrement de '{0}' : le fichier est protégé en écriture. Sélectionnez 'Remplacer' pour supprimer la protection.", + "discard": "Abandonner", + "readonlySaveErrorAdmin": "Échec de l'enregistrement de '{0}' : le fichier est protégé en écriture. Sélectionnez 'Remplacer' pour réessayer en tant qu'administrateur.", + "readonlySaveError": "Échec de l'enregistrement de '{0}' : le fichier est protégé en écriture. Sélectionnez 'Remplacer' pour essayer de supprimer la protection.", + "permissionDeniedSaveError": "Échec de l'enregistrement de '{0}' : Permissions insuffisantes. Sélectionnez 'Remplacer en tant qu'Admin' pour réessayer en tant qu'administrator.", "genericSaveError": "Échec d'enregistrement de '{0}' ({1}).", "staleSaveError": "Échec de l'enregistrement de '{0}' : le contenu sur disque est plus récent. Cliquez sur **Comparer** pour comparer votre version à celle située sur le disque.", "compareChanges": "Comparer", diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 631a14a1cef..64edc5f6461 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,6 +10,7 @@ "dropFolder": "Voulez-vous ajouter le dossier à l’espace de travail ?", "addFolders": "&&Ajouter les dossiers", "addFolder": "&&Ajouter le dossier", + "confirmMultiMove": "Êtes-vous sûr de vouloir déplacer les fichiers '{0}' suivants ?", "confirmMove": "Êtes-vous certain de vouloir déplacer '{0}' ?", "doNotAskAgain": "Ne plus me demander", "moveButtonLabel": "&&Déplacer", diff --git a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index c536ea46a5d..620260dc73a 100644 --- a/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Éditeurs ouverts", "openEditosrSection": "Section des éditeurs ouverts", - "dirtyCounter": "{0} non enregistré(s)", - "saveAll": "Enregistrer tout", - "closeAllUnmodified": "Fermer les éléments non modifiés", - "closeAll": "Tout fermer", - "compareWithSaved": "Comparer avec celui enregistré", - "close": "Fermer", - "closeOthers": "Fermer les autres" + "dirtyCounter": "{0} non enregistré(s)" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..b5604efd4c8 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "Journal (Principal)", + "sharedLog": "Journal (Partagé)", + "rendererLog": "Journal (Fenêtre)", + "extensionsLog": "Journal (Hôte d'extension)", + "developer": "Développeur" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..6d8707bc4eb --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Ouvrir le dossier des journaux", + "showLogs": "Afficher les journaux...", + "mainProcess": "Principal", + "sharedProcess": "Partagé", + "rendererProcess": "Fenêtre", + "extensionHost": "Hôte d'extension", + "selectProcess": "Sélectionner le processus", + "openLogFile": "Ouvrir le fichier de log...", + "setLogLevel": "Définir le niveau de journalisation (log)", + "trace": "Trace", + "debug": "Déboguer", + "info": "Informations", + "warn": "Avertissement", + "err": "Erreur", + "critical": "Critique", + "off": "Désactivé", + "selectLogLevel": "Sélectionner le niveau de journalisation (log)" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/fra/src/vs/workbench/parts/markers/common/messages.i18n.json index de7f944af49..2b60a006c26 100644 --- a/i18n/fra/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Affichage", - "problems.view.toggle.label": "Activer/désactiver les problèmes", - "problems.view.focus.label": "Problèmes de focus", "problems.panel.configuration.title": "Affichage des problèmes", "problems.panel.configuration.autoreveal": "Contrôle si l'affichage des problèmes doit automatiquement montrer les fichiers quand il les ouvre", "markers.panel.title.problems": "Problèmes", diff --git a/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..7666fba29aa --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Sortie", + "logViewer": "Visualiseur de journal", + "viewCategory": "Affichage", + "clearOutput.label": "Effacer la sortie" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/fra/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..2ae62f64fbe --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - Sortie", + "channel": "Canal de sortie pour '{0}'" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index c7b2dfd5e8a..a41e960d2e8 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 paramètre correspondant", "settingsFound": "{0} paramètres correspondants", "totalSettingsMessage": "Total de {0} paramètres", + "nlpResult": "Résultats en langage naturel", + "filterResult": "Résultats filtrés", "defaultSettings": "Paramètres par défaut", "defaultFolderSettings": "Paramètres de dossier par défaut", "defaultEditorReadonly": "Modifier dans l’éditeur du côté droit pour substituer les valeurs par défaut.", diff --git a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 89aaca94b7b..d5cd0fe71d7 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Essayez la recherche en langage naturel !", "defaultSettings": "Placez vos paramètres dans l’éditeur du côté droit pour substituer.", "noSettingsFound": "Aucun paramètre.", "settingsSwitcherBarAriaLabel": "Sélecteur de paramètres", "userSettings": "Paramètres utilisateur", "workspaceSettings": "Paramètres de l'espace de travail", - "folderSettings": "Paramètres de dossier", - "enableFuzzySearch": "Activer la recherche en langage naturel" + "folderSettings": "Paramètres de dossier" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/fra/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 42c1698dcd3..5800126a777 100644 --- a/i18n/fra/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Utilisés le plus souvent", - "mostRelevant": "Plus pertinent", "defaultKeybindingsHeader": "Remplacez les combinaisons de touches dans votre fichier de combinaisons de touches." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 923695e6fb4..561c8b8fcd3 100644 --- a/i18n/fra/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Affichage", "commandsHandlerDescriptionDefault": "Commandes d'affichage et d'exécution", "gotoLineDescriptionMac": "Atteindre la ligne", "gotoLineDescriptionWin": "Atteindre la ligne", diff --git a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 015c5898f64..2d2ad3ba485 100644 --- a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "Afficher Git", "source control": "Contrôle de code source", "toggleSCMViewlet": "Afficher SCM", - "view": "Afficher" + "view": "Afficher", + "scmConfigurationTitle": "SCM", + "alwaysShowProviders": "S'il faut toujours afficher la section Fournisseur de contrôle de code source.", + "diffDecorations": "Contrôle les décorations diff dans l'éditeur", + "inputCounter": "Contrôle quand afficher le compteur de saisie" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 4852691d7f0..e262a05e669 100644 --- a/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "Fournisseurs de contrôle de code source", "hideRepository": "Masquer", + "commitMessageInfo": "{0} caractères sur la ligne actuelle", + "commitMessageCountdown": "{0} caractères restants sur la ligne actuelle", + "commitMessageWarning": "{0} caractères sur {1} sur la ligne actuelle", "installAdditionalSCMProviders": "Installer des fournisseurs SCM supplémentaires...", "no open repo": "Il n’y a aucun fournisseur de contrôle de code source actif.", "source control": "Contrôle de code source", diff --git a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 72ef3e89f83..c87f37c878c 100644 --- a/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Afficher le terme de recherche précédent", "showSearchViewlet": "Afficher la zone de recherche", "findInFiles": "Chercher dans les fichiers", - "findInFilesWithSelectedText": "Rechercher dans les fichiers avec le texte sélectionné", "replaceInFiles": "Remplacer dans les fichiers", - "replaceInFilesWithSelectedText": "Remplacer dans les fichiers avec le texte sélectionné", "RefreshAction.label": "Actualiser", "CollapseDeepestExpandedLevelAction.label": "Réduire tout", "ClearSearchResultsAction.label": "Effacer", diff --git a/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 727436ac8ed..69ce9d7f6cd 100644 --- a/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Rechercher dans le dossier...", + "findInWorkspace": "Trouver dans l’espace de travail...", "showTriggerActions": "Atteindre le symbole dans l'espace de travail...", "name": "Rechercher", "search": "Rechercher", + "showSearchViewlet": "Afficher la zone de recherche", "view": "Affichage", + "findInFiles": "Chercher dans les fichiers", "openAnythingHandlerDescription": "Accéder au fichier", "openSymbolDescriptionNormal": "Atteindre le symbole dans l'espace de travail", - "searchOutputChannelTitle": "Rechercher", "searchConfigurationTitle": "Rechercher", "exclude": "Configurez les modèles Glob pour exclure les fichiers et les dossiers des recherches. Hérite de tous les modèles Glob à partir du paramètre files.exclude.", "exclude.boolean": "Modèle Glob auquel les chemins de fichiers doivent correspondre. Affectez la valeur true ou false pour activer ou désactiver le modèle.", @@ -18,5 +21,6 @@ "useRipgrep": "Contrôle si ripgrep doit être utilisé dans la recherche de texte et de fichier", "useIgnoreFiles": "Contrôle s'il faut utiliser les fichiers .gitignore et .ignore par défaut pendant la recherche de fichiers.", "search.quickOpen.includeSymbols": "Configurez l'ajout des résultats d'une recherche de symboles globale dans le fichier de résultats pour Quick Open.", - "search.followSymlinks": "Contrôle s'il faut suivre les symlinks pendant la recherche." + "search.followSymlinks": "Contrôle s'il faut suivre les symlinks pendant la recherche.", + "search.smartCase": "Recherches de manière non case-sensitive si le modèle est entièrement en minuscules, dans le cas contraire, recherche de manière case-sensitive" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..4823418ee4d --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "new.global": "Nouveau fichier d'extraits globaux...", + "group.global": "Extraits existants", + "openSnippet.pickLanguage": "Sélectionner le fichier d'extraits ou créer des extraits", + "openSnippet.label": "Configurer les extraits de l’utilisateur", + "preferences": "Préférences" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 96366bc3eb5..1917de0f41a 100644 --- a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Sélectionner le langage de l'extrait de code", - "openSnippet.errorOnCreate": "Impossible de créer {0}", - "openSnippet.label": "Ouvrir les extraits de code utilisateur", - "preferences": "Préférences", "snippetSchema.json.default": "Extrait de code vide", "snippetSchema.json": "Configuration de l'extrait de code utilisateur", "snippetSchema.json.prefix": "Préfixe à utiliser durant la sélection de l'extrait de code dans IntelliSense", "snippetSchema.json.body": "Contenu de l'extrait de code. Utilisez '$1', '${1:defaultText}' pour définir les positions du curseur, utilisez '$0' pour la position finale du curseur. Insérez les valeurs de variable avec '${varName}' et '${varName:defaultText}', par ex., 'Il s'agit du fichier : $TM_FILENAME'.", - "snippetSchema.json.description": "Description de l'extrait de code." + "snippetSchema.json.description": "Description de l'extrait de code.", + "snippetSchema.json.scope": "Une liste des noms de langages auxquels s’applique cet extrait de code, par exemple 'typescript,javascript'." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..c12c73b0de8 --- /dev/null +++ b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Extrait de code utilisateur" +} \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 0c67783e02a..a21a67fed20 100644 --- a/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Langage inconnu dans 'contributes.{0}.language'. Valeur fournie : {1}", "invalid.path.0": "Chaîne attendue dans 'contributes.{0}.path'. Valeur fournie : {1}", + "invalid.language.0": "Si le langage est omis, la valeur de 'contributes.{0}.path' doit être un fichier `.code-snippets`. Valeur fournie : {1}", + "invalid.language": "Langage inconnu dans 'contributes.{0}.language'. Valeur fournie : {1}", "invalid.path.1": "'contributes.{0}.path' ({1}) est censé être inclus dans le dossier ({2}) de l'extension. Cela risque de rendre l'extension non portable.", "vscode.extension.contributes.snippets": "Ajoute des extraits de code.", "vscode.extension.contributes.snippets-language": "Identificateur de langage pour lequel cet extrait de code est ajouté.", "vscode.extension.contributes.snippets-path": "Chemin du fichier d'extraits de code. Le chemin est relatif au dossier d'extensions et commence généralement par './snippets/'.", "badVariableUse": "Un ou plusieurs extraits de l’extension '{0}' confondent très probablement des snippet-variables et des snippet-placeholders (Voir https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax pour plus de détails)", "badFile": "Le fichier d’extrait \"{0}\" n’a pas pu être lu.", - "source.snippet": "Extrait de code utilisateur", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 8e54d84198f..c372a7b1d75 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -14,6 +14,7 @@ "terminal.integrated.shell.windows": "Le chemin du shell que le terminal utilise sous Windows. Lors de l’utilisation de shells fournies avec Windows (cmd, PowerShell ou Bash sur Ubuntu).", "terminal.integrated.shellArgs.windows": "Arguments de ligne de commande à utiliser sur le terminal Windows.", "terminal.integrated.rightClickCopyPaste": "Une fois le paramètre défini, le menu contextuel cesse de s'afficher quand l'utilisateur clique avec le bouton droit dans le terminal. À la place, une opération de copie est effectuée quand il existe une sélection, et une opération de collage est effectuée en l'absence de sélection.", + "terminal.integrated.copyOnSelection": "Une fois le paramètre défini, le texte sélectionné dans le terminal sera copié dans le presse-papiers.", "terminal.integrated.fontFamily": "Contrôle la famille de polices du terminal. La valeur par défaut est la valeur associée à editor.fontFamily.", "terminal.integrated.fontSize": "Contrôle la taille de police en pixels du terminal.", "terminal.integrated.lineHeight": "Contrôle la hauteur de ligne du terminal. La multiplication de ce nombre par la taille de police du terminal permet d'obtenir la hauteur de ligne réelle en pixels.", @@ -24,10 +25,12 @@ "terminal.integrated.setLocaleVariables": "Contrôle si les variables locales sont définies au démarrage du terminal. La valeur par défaut est true sur OS X, false sur les autres plateformes.", "terminal.integrated.cwd": "Chemin explicite de lancement du terminal. Il est utilisé comme répertoire de travail actif du processus d'interpréteur de commandes. Cela peut être particulièrement utile dans les paramètres d'espace de travail, si le répertoire racine n'est pas un répertoire de travail actif adéquat.", "terminal.integrated.confirmOnExit": "Indique s'il est nécessaire de confirmer l'existence de sessions de terminal actives au moment de quitter.", + "terminal.integrated.enableBell": "Si le terminal bell est activé ou non.", "terminal.integrated.commandsToSkipShell": "Ensemble d'ID de commandes dont les combinaisons de touches sont gérées par Code au lieu d'être envoyées à l'interpréteur de commandes. Cela permet d'utiliser des combinaisons de touches qui sont normalement consommées par l'interpréteur de commandes et d'obtenir le même résultat quand le terminal n'a pas le focus, par exemple Ctrl+P pour lancer Quick Open.", "terminal.integrated.env.osx": "Objet avec les variables d’environnement qui seront ajoutées au processus VS Code pour être utilisées par le terminal sous OS X", "terminal.integrated.env.linux": "Objet avec les variables d’environnement qui seront ajoutées au processus VS Code pour être utilisées par le terminal sous Linux", "terminal.integrated.env.windows": "Objet avec les variables d’environnement qui seront ajoutées au processus VS Code pour être utilisées par le terminal sous Windows", + "terminal.integrated.showExitAlert": "Afficher une alerte `Le processus terminal s’est arrêté avec le code de sortie` lorsque le code de sortie est différent de zéro.", "terminalCategory": "Terminal", "viewCategory": "Affichage" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index b1d65f3e2d3..5b59359d46e 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -14,6 +14,8 @@ "workbench.action.terminal.deleteWordRight": "Supprimer le mot à droite", "workbench.action.terminal.new": "Créer un terminal intégré", "workbench.action.terminal.new.short": "Nouveau terminal", + "workbench.action.terminal.newWorkspacePlaceholder": "Sélectionner le répertoire de travail actuel pour le nouveau terminal", + "workbench.action.terminal.newInActiveWorkspace": "Créer un nouveau Terminal intégré (dans l'espace de travail actif)", "workbench.action.terminal.focus": "Focus sur le terminal", "workbench.action.terminal.focusNext": "Focus sur le terminal suivant", "workbench.action.terminal.focusPrevious": "Focus sur le terminal précédent", diff --git a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index d636f6886f8..64dece8c292 100644 --- a/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,7 @@ "terminal.integrated.chooseWindowsShellInfo": "Vous pouvez changer l'interpréteur de commandes par défaut du terminal en sélectionnant le bouton Personnaliser.", "customize": "Personnaliser", "cancel": "Annuler", - "never again": "OK, ne plus afficher", + "never again": "OK, Ne plus afficher", "terminal.integrated.chooseWindowsShell": "Sélectionnez votre interpréteur de commandes de terminal favori. Vous pouvez le changer plus tard dans vos paramètres", "terminalService.terminalCloseConfirmationSingular": "Il existe une session de terminal active. Voulez-vous la tuer ?", "terminalService.terminalCloseConfirmationPlural": "Il existe {0} sessions de terminal actives. Voulez-vous les tuer ?" diff --git a/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 12b4156b835..1e7c69d38aa 100644 --- a/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/fra/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "Palette de commandes...", "settings": "Paramètres", "keyboardShortcuts": "Raccourcis clavier", + "userSnippets": "Extraits de code de l'utilisateur", "selectTheme.label": "Thème de couleur", "themes.selectIconTheme.label": "Thème d'icône de fichier", "not available": "Mises à jour non disponibles", diff --git a/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 8ca568a2f40..865514aec03 100644 --- a/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "Le fichier est un répertoire", + "fileNotModifiedError": "Fichier non modifié depuis", "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte" } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json index 6ba63445dd2..f83d0f45ec2 100644 --- a/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "Fichier trop volumineux pour être ouvert", "fileNotFoundError": "Fichier introuvable ({0})", "fileBinaryError": "Il semble que le fichier soit binaire. Impossible de l'ouvrir en tant que texte", + "filePermission": "Autorisation refusée en écrivant dans le fichier ({0})", "fileExists": "Le fichier à créer existe déjà ({0})", "fileMoveConflict": "Déplacement/copie impossible. Le fichier existe déjà dans la destination.", "unableToMoveCopyError": "Impossible de déplacer/copier. Le fichier remplace le dossier qui le contient.", diff --git a/i18n/fra/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/fra/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index 232203467df..e217d8d597b 100644 --- a/i18n/fra/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "Condition quand la touche est active.", "keybindings.json.args": "Arguments à passer à la commande à exécuter.", "keyboardConfigurationTitle": "Clavier", - "dispatch": "Contrôle la logique de distribution des appuis sur les touches pour utiliser soit 'code' (recommandé), soit 'keyCode'." + "dispatch": "Contrôle la logique de distribution des appuis sur les touches pour utiliser soit 'code' (recommandé), soit 'keyCode'.", + "touchbar.enabled": "Active les boutons de la touchbar macOS sur le clavier si disponible." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/fra/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 4d90040dd20..a5d794a742e 100644 --- a/i18n/fra/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Voulez-vous enregistrer les modifications apportées à {0} ?", "saveChangesMessages": "Voulez-vous enregistrer les modifications apportées aux {0} fichiers suivants ?", - "moreFile": "...1 fichier supplémentaire non affiché", - "moreFiles": "...{0} fichiers supplémentaires non affichés", "saveAll": "&&Enregistrer tout", "save": "&&Enregistrer", "dontSave": "&&Ne pas enregistrer", diff --git a/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 46a345fad2d..e40e5326149 100644 --- a/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Remplace les couleurs du thème de couleur sélectionné.", - "editorColors": "Remplace les couleurs et le style de la police de l’éditeur du thème par la couleur actuellement sélectionnée.", "editorColors.comments": "Définit les couleurs et les styles des commentaires", "editorColors.strings": "Définit les couleurs et les styles des littéraux de chaînes.", "editorColors.keywords": "Définit les couleurs et les styles des mots clés.", @@ -19,5 +18,6 @@ "editorColors.types": "Définit les couleurs et les styles des déclarations et références de type.", "editorColors.functions": "Définit les couleurs et les styles des déclarations et références de fonctions.", "editorColors.variables": "Définit les couleurs et les styles des déclarations et références de variables.", - "editorColors.textMateRules": "Définit les couleurs et les styles à l’aide de règles de thème textmate (avancé)." + "editorColors.textMateRules": "Définit les couleurs et les styles à l’aide de règles de thème textmate (avancé).", + "editorColors": "Remplace les couleurs et le style de la police de l’éditeur du thème par la couleur actuellement sélectionnée." } \ No newline at end of file diff --git a/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 079d530ab03..f4f2e499154 100644 --- a/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/fra/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Impossible d’écrire dans le fichier de configuration de l’espace de travail. Veuillez ouvrir le fichier pour y corriger les erreurs/avertissements et essayez à nouveau.", "errorWorkspaceConfigurationFileDirty": "Impossible d’écrire dans le fichier de configuration de l’espace de travail, car le fichier a été modifié. Veuillez, s’il vous plaît, l'enregistrez et réessayez.", "openWorkspaceConfigurationFile": "Ouvrir le Fichier de Configuration d’espace de travail", - "close": "Fermer", - "enterWorkspace.close": "Fermer", - "enterWorkspace.dontShowAgain": "Ne plus afficher", - "enterWorkspace.moreInfo": "Informations", - "enterWorkspace.prompt": "En savoir plus sur l’utilisation de dossiers multiples dans VS Code." + "close": "Fermer" } \ No newline at end of file diff --git a/i18n/hun/extensions/git/out/autofetch.i18n.json b/i18n/hun/extensions/git/out/autofetch.i18n.json index fe69406ef37..83092572a2a 100644 --- a/i18n/hun/extensions/git/out/autofetch.i18n.json +++ b/i18n/hun/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Igen", + "read more": "További információk", "no": "Nem", - "not now": "Most nem", - "suggest auto fetch": "Szeretné engedélyezni a Git-forráskódtárhelyek automatikus lekérését (fetch)?" + "not now": "Kérdezzen rá később", + "suggest auto fetch": "Szeretné, hogy a Code időszakosan futtasson `git fetch`-t?" } \ No newline at end of file diff --git a/i18n/hun/extensions/git/out/commands.i18n.json b/i18n/hun/extensions/git/out/commands.i18n.json index d2dfa251e5d..80f41babc05 100644 --- a/i18n/hun/extensions/git/out/commands.i18n.json +++ b/i18n/hun/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nA művelet NEM VONHATÓ VISSZA, az aktuális munka ÖRÖKRE EL FOG VESZNI.", "yes discard tracked": "Egy követett fájl elvetése", "yes discard tracked multiple": "{0} követett fájl elvetése", + "unsaved files single": "A következő fájl nincs elmentve: {0}.\n\nSzeretné menteni a beadás előtt?", + "unsaved files": "{0} nem mentett fájl található.\n\nSzeretné menteni őket a beadás előtt?", + "save and commit": "Összes mentése és beadás", + "commit": "Beadás mindenképp", "no staged changes": "Nincs beadáshoz (commithoz) előjegyzett módosítás. Szeretné automatikusan előjegyeztetni a módosításokat és közvetlenül beadni őket?", "always": "Mindig", "no changes": "Nincs beadandó módosítás.", @@ -64,12 +68,13 @@ "no remotes to pull": "A forráskódtárhoz nincsenek távoli szerverek konfigurálva, ahonnan pullozni lehetne.", "pick remote pull repo": "Válassza ki a távoli szervert, ahonnan pullozni szeretné az ágat", "no remotes to push": "A forráskódtárhoz nincsenek távoli szerverek konfigurálva, ahová pusholni lehetne.", - "push with tags success": "A címkékkel együtt történő pusholás sikeresen befejeződött.", "nobranch": "Válasszon egy ágat a távoli szerverre való pusholáshot!", + "confirm publish branch": "A(z) '{0}' ág nem létezik a távoli szerveren. Szeretné publikálni ezt az ágat?", + "ok": "OK", + "push with tags success": "A címkékkel együtt történő pusholás sikeresen befejeződött.", "pick remote": "Válassza ki a távoli szervert, ahová publikálni szeretné a(z) '{0}' ágat:", "sync is unpredictable": "Ez a művelet pusholja és pullozza a commitokat a következő helyről: '{0}'.", - "ok": "OK", - "never again": "Rendben, ne jelenítse meg újra", + "never again": "Rendben, ne jelenjen meg újra", "no remotes to publish": "A forráskódtárhoz nincsenek távoli szerverek konfigurálva, ahová publikálni lehetne.", "no changes stash": "Nincs elrakandó módosítás.", "provide stash message": "Adja meg a stash-hez tartozó üzenet (nem kötelező)", diff --git a/i18n/hun/extensions/git/out/main.i18n.json b/i18n/hun/extensions/git/out/main.i18n.json index ab59b50cfc7..19742ee7152 100644 --- a/i18n/hun/extensions/git/out/main.i18n.json +++ b/i18n/hun/extensions/git/out/main.i18n.json @@ -7,7 +7,7 @@ "looking": "Git keresése a következő helyen: {0}", "using git": "Git {0} használata a következő helyről: {1}", "downloadgit": "Git letöltése", - "neverShowAgain": "Ne jelenjen meg újra", + "neverShowAgain": "Ne jelenítse meg újra", "notfound": "A Git nem található. Telepítse vagy állítsa be az elérési útját a 'git.path' beállítással.", "updateGit": "Git frissítése", "git20": "Úgy tűnik, hogy a git {0} van telepítve. A Code a git >= 2 verzióival működik együtt a legjobban." diff --git a/i18n/hun/extensions/git/out/repository.i18n.json b/i18n/hun/extensions/git/out/repository.i18n.json index 234abfc4470..b2654e062b7 100644 --- a/i18n/hun/extensions/git/out/repository.i18n.json +++ b/i18n/hun/extensions/git/out/repository.i18n.json @@ -27,6 +27,6 @@ "staged changes": "Beadásra előjegyzett módosítások", "changes": "Módosítások", "ok": "OK", - "neveragain": "Soha ne jelenítse meg újra", + "neveragain": "Ne jelenítse meg újra", "huge": "A(z) '{0}' forráskódtárban túl sok aktív módosítás van. A Git-funkciók csak egy része lesz engedélyezve." } \ No newline at end of file diff --git a/i18n/hun/extensions/git/package.i18n.json b/i18n/hun/extensions/git/package.i18n.json index 150ac02318b..87388db14f4 100644 --- a/i18n/hun/extensions/git/package.i18n.json +++ b/i18n/hun/extensions/git/package.i18n.json @@ -54,6 +54,7 @@ "command.stashPopLatest": "Legutóbbi stash visszaállítása", "config.enabled": "Meghatározza, hogy a git engedélyezve van-e", "config.path": "A git végrehajtható fájl elérési útja", + "config.autoRepositoryDetection": "Meghatározza, hogy a forráskódtárak automatikusan fel legyenek-e derítve", "config.autorefresh": "Meghatározza, hogy engedélyezve van-e az automatikus frissítés", "config.autofetch": "Meghatározza, hogy engedélyezve van-e az automatikus lekérés", "config.enableLongCommitWarning": "Figyelmeztessen-e az alkalmazás hosszú beadási üzenet esetén", @@ -72,5 +73,6 @@ "colors.deleted": "A törölt erőforrások színe.", "colors.untracked": "A nem követett erőforrások színe.", "colors.ignored": "A figyelmen kívül hagyott erőforrások színe.", - "colors.conflict": "A konfliktusos erőforrások színe." + "colors.conflict": "A konfliktusos erőforrások színe.", + "colors.submodule": "Az almodulokhoz tartozó erőforrások színe" } \ No newline at end of file diff --git a/i18n/hun/extensions/typescript/out/commands.i18n.json b/i18n/hun/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..c521fb331a6 --- /dev/null +++ b/i18n/hun/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Nyisson meg egy mappát a VS Code-ban typescriptes vagy javascriptes projekt használatához!", + "typescript.projectConfigUnsupportedFile": "Nem sikerült meghatározni a TypeScript- vagy JavaScript-projektet. Nem támogatott fájltípus", + "typescript.projectConfigCouldNotGetInfo": "Nem sikerült meghatározni a TypeScript- vagy JavaScript-projektet", + "typescript.noTypeScriptProjectConfig": "A fájl nem része egy TypeScript-projektnek", + "typescript.noJavaScriptProjectConfig": "A fájl nem része egy JavaScript-projektnek", + "typescript.configureTsconfigQuickPick": "tsconfig.json konfigurálása", + "typescript.configureJsconfigQuickPick": "jsconfig.json konfigurálása", + "typescript.projectConfigLearnMore": "További információ" +} \ No newline at end of file diff --git a/i18n/hun/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/hun/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..6d6ae6eab7e --- /dev/null +++ b/i18n/hun/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (összes javítása a fájlban)" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/hun/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/hun/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/base/node/ps.i18n.json b/i18n/hun/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..688e86b7228 --- /dev/null +++ b/i18n/hun/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Processzor- és memóriahasználattal kapcsolatos információk gyűjtése. A folyamat eltarthat néhány másodpercig." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json index 48b15939e90..5a0b782e9aa 100644 --- a/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/hun/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "A sorszámok abszolút értékként jelennek meg.", "lineNumbers.relative": "A sorszámok a kurzortól való távolságuk alapján jelennek meg.", "lineNumbers.interval": "A sorszámok minden 10. sorban jelennek meg.", - "lineNumbers": "Meghatározza a sorszámok megjelenését. A lehetséges értékek: 'on', 'off' és 'relative'.", + "lineNumbers": "Meghatározza a sorszámok megjelenését. A lehetséges értékek: 'on', 'off', 'relative' és 'interval'.", "rulers": "Függőleges vonalzók kirajzolása bizonyos számú fix szélességű karakter után. Több vonalzó használatához adjon meg több értéket. Nincs kirajzolva semmi, ha a tömb üres.", "wordSeparators": "Azon karakterek listája, amelyek szóelválasztónak vannak tekintve szavakkal kapcsolatos navigáció vagy műveletek során.", "tabSize": "Egy tabulátor hány szóköznek felel meg. Ez a beállítás felülírásra kerül a fájl tartalma alapján, ha az `editor.detectIndentation` beállítás aktív.", @@ -40,9 +40,9 @@ "wordWrapColumn": "Meghatározza a sortöréshez használt oszlopszámot a szerkesztőablakban, ha az `editor.wordWrap` értéke 'wordWrapColumn' vagy 'bounded'.", "wrappingIndent": "Meghatározza a tördelt sorok behúzását. Értéke 'none', 'same' vagy 'indent' lehet.", "mouseWheelScrollSensitivity": "Az egér görgetési eseményeinél keletkező `deltaX` és `deltaY` paraméterek szorzója", - "multiCursorModifier.ctrlCmd": "Windows és Linux alatt a `Control`, OSX alatt a `Command` billentyűt jelenti.", - "multiCursorModifier.alt": "Windows és Linux alatt az `Alt`, OSX alatt az `Option` billentyűt jelenti.", - "multiCursorModifier": "Több kurzor hozzáadásához használt módosítóbillentyű. A `ctrlCmd` Windows és Linux alatt a `Control`, OSX alatt a `Command` billentyűt jelenti. A Definíció megkeresése és Hivatkozás megnyitása egérgesztusok automatikusan alkalmazkodnak úgy, hogy ne ütközzenek a többkurzorhoz tartozó módosítóval.", + "multiCursorModifier.ctrlCmd": "Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti.", + "multiCursorModifier.alt": "Windows és Linux alatt az `Alt`, macOS alatt az `Option` billentyűt jelenti.", + "multiCursorModifier": "Több kurzor hozzáadásához használt módosítóbillentyű. A `ctrlCmd` Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti. A Definíció megkeresése és Hivatkozás megnyitása egérgesztusok automatikusan úgy lesznek beállítva, hogy ne ütközzenek a többkurzorhoz tartozó módosítóval.", "quickSuggestions.strings": "Kiegészítési javaslatok engedélyezése karakterláncokban (stringekben)", "quickSuggestions.comments": "Kiegészítési javaslatok engedélyezése megjegyzésekben", "quickSuggestions.other": "Kiegészítési javaslatok engedélyezése karakterláncokon (stringeken) és megjegyzéseken kívül", @@ -72,6 +72,7 @@ "cursorBlinking": "Meghatározza a kurzor animációjának stílusát. Lehetséges értékek: 'blink', 'smooth', 'phase', 'expand' vagy 'solid'", "mouseWheelZoom": "A szerkesztőablak betűtípusának nagyítása vagy kicsinyítése az egérgörgő Ctrl lenyomása mellett történő használata esetén", "cursorStyle": "Meghatározza a kurzor stílusát. Lehetséges értékek: 'block', 'block-outline', 'line', 'line-thin', 'underline' vagy 'underline-thin'", + "lineCursorWidth": "Meghatározza a kurzor szélességét, ha az editor.cursorStyle értéke 'line'.", "fontLigatures": "Engedélyezi a betűtípusban található ligatúrák használatát", "hideCursorInOverviewRuler": "Meghatározza, hogy a kurzor pozíciója el legyen-e rejtve az áttekintő sávon.", "renderWhitespace": "Meghatározza, hogy a szerkesztőablakban hogyan legyenek kirajzolva a szóköz karakterek. Lehetséges értékek: 'none', 'boundary', vagy 'all'. A 'boundary' beállítás esetén, ha szavak között egyetlen szóköz található, akkor az nem lesz kirajzolva.", diff --git a/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json index ca5c75eaa93..bcb0b0e54d5 100644 --- a/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/hun/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "A kurzor pozícióján található sor kiemelési háttérszíne.", "lineHighlightBorderBox": "A kurzor pozícióján található sor keretszíne.", - "rangeHighlight": "A kiemelt területek háttérszíne, pl. a gyors megnyitás és keresés funkcióknál.", + "rangeHighlight": "A kiemelt területek háttérszíne, pl. a gyors megnyitás és keresés funkcióknál. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "caret": "A szerkesztőablak kurzorának színe.", "editorCursorBackground": "A szerkesztőablak kurzorának háttérszíne. Lehetővé teszik az olyan karakterek színének módosítását, amelyek fölött egy blokk-típusú kurzor áll.", "editorWhitespaces": "A szerkesztőablakban található szóköz karakterek színe.", diff --git a/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json index e3ec625549e..657741e4ffd 100644 --- a/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Következő hiba vagy figyelmeztetés", - "markerAction.previous.label": "Előző hiba vagy figyelmeztetés", + "markerAction.next.label": "Következő probléma (hiba, figyelmeztetés, információ)", + "markerAction.previous.label": "Előző probléma (hiba, figyelmeztetés, információ)", "editorMarkerNavigationError": "A szerkesztőablak jelzőnavigációs moduljának színe hiba esetén.", "editorMarkerNavigationWarning": "A szerkesztőablak jelzőnavigációs moduljának színe figyelmeztetés esetén.", "editorMarkerNavigationInfo": "A szerkesztőablak jelzőnavigációs moduljának színe információ esetén.", diff --git a/i18n/hun/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json b/i18n/hun/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json index dc4360652cb..96f61fa990d 100644 --- a/i18n/hun/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggle.tabMovesFocus": "Tab billentyűvel mozgatott fókusz ki- és bekapcsolása" + "toggle.tabMovesFocus": "Tabulátor billentyűvel mozgatott fókusz ki- és bekapcsolása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index fa7c3359075..d251158c987 100644 --- a/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/hun/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Szimbólumok háttérszíne olvasási hozzáférés, páldául változó olvasása esetén.", - "wordHighlightStrong": "Szimbólumok háttérszíne írási hozzáférés, páldául változó írása esetén.", + "wordHighlight": "Szimbólumok háttérszíne olvasási hozzáférés, páldául változó olvasása esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "wordHighlightStrong": "Szimbólumok háttérszíne írási hozzáférés, páldául változó írása esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "overviewRulerWordHighlightForeground": "A kiemelt szimbólumokat jelölő jelzések színe az áttekintősávon.", "overviewRulerWordHighlightStrongForeground": "A kiemelt, írási hozzáférésű szimbólumokat jelölő jelzések színe az áttekintősávon.", "wordHighlight.next.label": "Ugrás a következő kiemelt szimbólumhoz", diff --git a/i18n/hun/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/hun/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 27181140f4b..9ef8de88790 100644 --- a/i18n/hun/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/hun/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "A(z) `{0}` nem érvényes menüazonosító", "missing.command": "A menüpont a(z) `{0}` parancsra hivatkozik, ami nincs deklarálva a 'commands'-szakaszban.", "missing.altCommand": "A menüpont a(z) `{0}` alternatív parancsra hivatkozik, ami nincs deklarálva a 'commands'-szakaszban.", - "dupe.command": "A menüpont ugyanazt a parancsot hivatkozza alapértelmezett és alternatív parancsként", - "nosupport.altCommand": "Jelenleg csak az 'editor/title' menü 'navigation' csoportja támogatja az alternatív parancsokat" + "dupe.command": "A menüpont ugyanazt a parancsot hivatkozza alapértelmezett és alternatív parancsként" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/environment/node/argv.i18n.json b/i18n/hun/src/vs/platform/environment/node/argv.i18n.json index acbe400a835..06b5ed441c6 100644 --- a/i18n/hun/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/hun/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,36 @@ "diff": "Két fájl összehasonlítása egymással.", "add": "Mappá(k) hozzáadása a legutolsó aktív ablakhoz.", "goto": "Megnyitja a megadott elérési úton található fájlt a megadott sornál és oszlopnál.", - "locale": "A használt lokalizáció (pl. en-US vagy zh-TW)", "newWindow": "Mindenképp induljon új példány a Code-ból.", - "performance": "Indítás a 'Developer: Startup Performance' parancs engedélyezésével.", - "prof-startup": "Processzorhasználat profilozása induláskor", - "inspect-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz.", - "inspect-brk-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben, úgy, hogy a kiegészítő gazdafolyamata szüneteltetve lesz az indítás után. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz. ", "reuseWindow": "Fájl vagy mappa megnyitása a legutoljára aktív ablakban.", - "userDataDir": "Meghatározza a könyvtárat, ahol a felhasználói adatok vannak tárolva. Hasznás, ha rootként van futtatva.", - "log": "A naplózott események szintje.Az 'info' az alapértelmezett értéke. Lehetséges értékek: 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", - "verbose": "Részletes kimenet kiírása (magába foglalja a --wait kapcsolót)", "wait": "Várjon a fájlok bezárására a visszatérés előtt.", + "locale": "A használt lokalizáció (pl. en-US vagy zh-TW)", + "userDataDir": "Meghatározza a könyvtárat, ahol a felhasználói adatok vannak tárolva. Hasznás, ha rootként van futtatva.", + "version": "Verzió kiírása.", + "help": "Használati útmutató kiírása.", "extensionHomePath": "A kiegészítők gyökérkönyvtárának beállítása.", "listExtensions": "Telepített kiegészítők listázása.", "showVersions": "Telepített kiegészítők verziójának megjelenítése a --list-extension kapcsoló használata esetén.", "installExtension": "Kiegészítő telepítése.", "uninstallExtension": "Kiegészítő eltávolítása.", "experimentalApis": "Tervezett API-funkciók engedélyezése egy kiegészítő számára.", - "disableExtensions": "Összes telepített kiegészítő letiltása.", - "disableGPU": "Hardveres gyorsítás letiltása.", + "verbose": "Részletes kimenet kiírása (magába foglalja a --wait kapcsolót)", + "log": "A naplózott események szintje.Az 'info' az alapértelmezett értéke. Lehetséges értékek: 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Folyamatok erőforrás-használati és diagnosztikai adatinak kiíratása.", - "version": "Verzió kiírása.", - "help": "Használati útmutató kiírása.", + "performance": "Indítás a 'Developer: Startup Performance' parancs engedélyezésével.", + "prof-startup": "Processzorhasználat profilozása induláskor", + "disableExtensions": "Összes telepített kiegészítő letiltása.", + "inspect-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz.", + "inspect-brk-extensions": "Hibakeresés és profilozás engedélyezése a kiegészítőkben, úgy, hogy a kiegészítő gazdafolyamata szüneteltetve lesz az indítás után. Ellenőrizze a fejlesztői eszközöket a csatlakozási URI-hoz. ", + "disableGPU": "Hardveres gyorsítás letiltása.", + "uploadLogs": "Az aktuális munkamenet naplóinak feltöltése egy biztonságos végpontra.", + "issue": "Probléma jelentése", "usage": "Használat", "options": "beállítások", "paths": "elérési utak", - "optionsUpperCase": "Beálítások" + "stdinWindows": "Más program bemenetének olvasásához fűzze a '-' karaktert a parancshoz (pl.: 'echo Hello World | {0} -')", + "stdinUnix": "Az stdin-ről történő olvasásához fűzze a '-' karaktert a parancshoz (pl.: 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Beálítások", + "extensionsManagement": "Kiegészítők kezelése", + "troubleshooting": "Hibaelhárítás" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 8788d40a469..b5c8c712977 100644 --- a/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/hun/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "A kiegészítő érvénytelen: a package.json nem egy JSON-fájl.", - "restartCodeLocal": "Indítsa újra a Code-ot a(z) {0} újratelepítése előtt.", + "restartCode": "Indítsa újra a Code-ot a(z) {0} újratelepítése előtt.", "installingOutdatedExtension": "A kiegészítő egy újabb verziója már telepítve van. Szeretné felülírni a régebbi verzióval?", "override": "Felülírás", "cancel": "Mégse", - "notFoundCompatible": "A telepítés nem sikerült, mert a(z) '{0}' kiegészítő VS Code '{1}' verziójával kompatibilis változata nem található.", - "quitCode": "A telepítés nem sikerült, mert a kiegészítő elavult példánya még mindig fut. Lépjen ki a VS Code-ból, és indítsa újra az újratelepítés előtt.", - "exitCode": "A telepítés nem sikerült, mert a kiegészítő elavult példánya még mindig fut. Lépjen ki a VS Code-ból, és indítsa újra az újratelepítés előtt.", + "errorInstallingDependencies": "Hiba a függőségek telepítése közben. {0}", + "notFoundCompatible": "A(z) '{0}' nem telepíthető: nincs a VS Code '{1}' verziójával kompatibilis változat.", "notFoundCompatibleDependency": "A telepítés nem sikerült, mert a(z) '{0}' kiegészítő függőség VS Code '{1}' verziójával kompatibilis változata nem található. ", + "quitCode": "A kiegészítő telepítése nem sikerült. Lépjen ki és indítsa el a VS Code-ot az újratelepítés előtt!", + "exitCode": "A kiegészítő telepítése nem sikerült. Lépjen ki és indítsa el a VS Code-ot az újratelepítés előtt!", "uninstallDependeciesConfirmation": "Csak a(z) '{0}' kiegészítőt szeretné eltávolítani vagy annak függőségeit is?", "uninstallOnly": "Csak ezt", "uninstallAll": "Mindent", diff --git a/i18n/hun/src/vs/platform/list/browser/listService.i18n.json b/i18n/hun/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..b784e240a18 --- /dev/null +++ b/i18n/hun/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Munkaterület", + "multiSelectModifier.ctrlCmd": "Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti.", + "multiSelectModifier.alt": "Windows és Linux alatt az `Alt`, macOS alatt az `Option` billentyűt jelenti.", + "multiSelectModifier": "Több elem kijelölése esetén újabb elem hozzáadásához használt módosítóbillentyű (például a fanézetekben és listáknál, ha támogatva van). A `ctrlCmd` Windows és Linux alatt a `Control`, macOS alatt a `Command` billentyűt jelenti. A 'Megnyitás oldalt\" egérgesztusok – ha támogatva vannak – automatikusan úgy lesznek beállítva, hogy ne ütközzenek a több elem kijelöléséhez tartozó módosítóbillentyűvel." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/message/common/message.i18n.json b/i18n/hun/src/vs/platform/message/common/message.i18n.json index a4f556eb01c..ee6d194b8dd 100644 --- a/i18n/hun/src/vs/platform/message/common/message.i18n.json +++ b/i18n/hun/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Bezárás", "later": "Később", - "cancel": "Mégse" + "cancel": "Mégse", + "moreFile": "...1 további fájl nincs megjelenítve", + "moreFiles": "...{0} további fájl nincs megjelenítve" } \ No newline at end of file diff --git a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json index a024837c583..e489cf247bf 100644 --- a/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/hun/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "A szerkesztőablak-modulok keretszíne. A szín csak akkor van használva, ha a modul beállítása alapján rendelkezik kerettel, és a színt nem írja felül a modul.", "editorSelectionBackground": "A szerkesztőablak-szakasz színe.", "editorSelectionForeground": "A kijelölt szöveg színe nagy kontrasztú téma esetén.", - "editorInactiveSelection": "Az inaktív szerkesztőablakban található kijelölések színe.", - "editorSelectionHighlight": "A kijelöléssel megegyező tartalmú területek színe.", + "editorInactiveSelection": "Az inaktív szerkesztőablakban található kijelölések színe. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "editorSelectionHighlight": "A kijelöléssel megegyező tartalmú területek színe. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "editorFindMatch": "A keresés jelenlegi találatának színe.", - "findMatchHighlight": "A keresés további találatainak színe.", - "findRangeHighlight": "A keresést korlátozó terület színe.", - "hoverHighlight": "Kiemelés azon szó alatt, amely fölött lebegő elem jelenik meg.", + "findMatchHighlight": "A keresés további találatainak színe. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "findRangeHighlight": "A keresést korlátozó terület színe. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "hoverHighlight": "Kiemelés azon szó alatt, amely fölött lebegő elem jelenik meg. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "hoverBackground": "A szerkesztőablakban lebegő elemek háttérszíne.", "hoverBorder": "A szerkesztőablakban lebegő elemek keretszíne.", "activeLinkForeground": "Az aktív hivatkozások háttérszíne.", @@ -76,12 +76,12 @@ "diffEditorRemoved": "Az eltávolított szövegek háttérszíne.", "diffEditorInsertedOutline": "A beillesztett szövegek körvonalának színe.", "diffEditorRemovedOutline": "Az eltávolított szövegek körvonalának színe.", - "mergeCurrentHeaderBackground": "A helyi tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.", - "mergeCurrentContentBackground": "A helyi tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.", - "mergeIncomingHeaderBackground": "A beérkező tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.", - "mergeIncomingContentBackground": "A beérkező tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.", - "mergeCommonHeaderBackground": "A közös ős tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. ", - "mergeCommonContentBackground": "A közös ős tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. ", + "mergeCurrentHeaderBackground": "A helyi tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "mergeCurrentContentBackground": "A helyi tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "mergeIncomingHeaderBackground": "A beérkező tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "mergeIncomingContentBackground": "A beérkező tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "mergeCommonHeaderBackground": "A közös ős tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", + "mergeCommonContentBackground": "A közös ős tartalmának háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. A színnek áttetszőnek kell lennie, hogy ne fedje el az alatta lévő dekorátorokat.", "mergeBorder": "A fejlécek és az elválasztó sáv keretszíne a sorok között megjelenített összeolvasztási konfliktusok esetén.", "overviewRulerCurrentContentForeground": "A helyi tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.", "overviewRulerIncomingContentForeground": "A beérkező tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.", diff --git a/i18n/hun/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/hun/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..95d3d6d773a --- /dev/null +++ b/i18n/hun/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirearray": "a localizationst tömbként kell megadni", + "requirestring": "a(z) `{0}` tulajdonság kötelező és `string` típusúnak kell lennie", + "optstring": "a(z) `{0}` tulajdonság elhagyható vagy `string` típusúnak kell lennie", + "vscode.extension.contributes.localizations": "Lokalizációkat szolgáltat a szerkesztőhöz", + "vscode.extension.contributes.localizations.languageId": "Annak a nyelvnek az azonosítója, amelyre a megjelenített szövegek fordítva vannak.", + "vscode.extension.contributes.localizations.languageName": "Annak a nyelvnek a neve, amelyre a megjelenített szövegek fordítva vannak.", + "vscode.extension.contributes.localizations.translations": "A nyelvhez tartozó összes, fordítási fájlokat tartalmazó mappa relatív elérési útja." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..753cc84e856 --- /dev/null +++ b/i18n/hun/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Mentési események futtatása..." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/hun/src/vs/workbench/api/node/extHostTreeViews.i18n.json index ad630367cba..d46c5a08986 100644 --- a/i18n/hun/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/hun/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "Nincs '{0}' azonosítóval regisztrált fanézet.", - "treeItem.notFound": "Nincs '{0}' azonosítójú elem a fában.", - "treeView.duplicateElement": "A(z) {0} elem már regisztrálva van" + "treeView.duplicateElement": "Már van {0} azonosítójú elem regisztrálva" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/hun/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index b5b22901d6a..8846afdbff9 100644 --- a/i18n/hun/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Oldalsáv helyének váltása", + "toggleSidebarPosition": "Oldalsáv helyzetének váltása", "view": "Nézet" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 586bbb9d5a1..5b05c77fb5d 100644 --- a/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Fájl megnyitása...", "openFolder": "Mappa megnyitása...", "openFileFolder": "Megnyitás...", - "addFolderToWorkspace": "Mappa hozzáadása a munkaterülethez...", - "add": "&&Hozzáadás", - "addFolderToWorkspaceTitle": "Mappa hozzáadása a munkaterülethez", "globalRemoveFolderFromWorkspace": "Mappa eltávolítása a munkaterületről...", - "removeFolderFromWorkspace": "Mappa eltávolítása a munkaterületről", - "openFolderSettings": "Mappa beállításainak megnyitása", "saveWorkspaceAsAction": "Munkaterület mentése másként...", "save": "Menté&&s", "saveWorkspace": "Munkaterület mentése", "openWorkspaceAction": "Munkaterület megnyitása...", "openWorkspaceConfigFile": "Munkaterület konfigurációs fájljának megnyitása", - "openFolderAsWorkspaceInNewWindow": "Mappa megnyitása munkaterületként egy új ablakban", - "workspaceFolderPickerPlaceholder": "Válasszon munkaterület-mappát!" + "openFolderAsWorkspaceInNewWindow": "Mappa megnyitása munkaterületként egy új ablakban" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/hun/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..080898a7ed6 --- /dev/null +++ b/i18n/hun/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Mappa hozzáadása a munkaterülethez...", + "add": "&&Hozzáadás", + "addFolderToWorkspaceTitle": "Mappa hozzáadása a munkaterülethez", + "workspaceFolderPickerPlaceholder": "Válasszon munkaterület-mappát!" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 05a3be82161..5d48accc6b6 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "A harmadik csoportban található szerkesztőablakok megjelenítése", "allEditorsPicker": "Összes megnyitott szerkesztőablak megjelenítése", "view": "Nézet", - "file": "Fájl" + "file": "Fájl", + "close": "Bezárás", + "closeOthers": "Többi bezárása", + "closeRight": "Jobbra lévők bezárása", + "closeAllUnmodified": "Nem módosultak bezárása", + "closeAll": "Összes bezárása", + "keepOpen": "Maradjon nyitva", + "toggleInlineView": "Sorok közötti nézet be- és kikapcsolása", + "showOpenedEditors": "Megnyitott szerkesztőablak megjelenítése", + "keepEditor": "Szerkesztőablak nyitva tartása", + "closeEditorsInGroup": "A csoportban lévő összes szerkesztőablak bezárása", + "closeUnmodifiedEditors": "Nem módosult szerkesztőablakok bezárása a csoportban", + "closeOtherEditors": "Többi szerkesztőablak bezárása", + "closeRightEditors": "Jobbra lévő szerkesztőablakok bezárása" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index c82ab6ff2a2..52fa76d91e7 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Szerkesztőablak bezárása", "revertAndCloseActiveEditor": "Visszaállítás és szerkesztőablak bezárása", "closeEditorsToTheLeft": "Balra lévő szerkesztőablakok bezárása", - "closeEditorsToTheRight": "Jobbra lévő szerkesztőablakok bezárása", "closeAllEditors": "Összes szerkesztőablak bezárása", - "closeUnmodifiedEditors": "Nem módosult szerkesztőablakok bezárása a csoportban", "closeEditorsInOtherGroups": "A többi csoport szerkesztőablakainak bezárása", - "closeOtherEditorsInGroup": "Többi szerkesztőablak bezárása", - "closeEditorsInGroup": "A csoportban lévő összes szerkesztőablak bezárása", "moveActiveGroupLeft": "Szerkesztőablak-csoport mozgatása balra", "moveActiveGroupRight": "Szerkesztőablak-csoport mozgatása jobbra", "minimizeOtherEditorGroups": "Többi szerkesztőablak-csoport kis méretűvé tétele", "evenEditorGroups": "Szerkesztőablak-csoportok egyenlő méretűvé tétele", "maximizeEditor": "Szerkesztőablak-csoport nagy méretűvé tétele és oldalsáv elrejtése", - "keepEditor": "Szerkesztőablak nyitva tartása", "openNextEditor": "Következő szerkesztőablak megnyitása", "openPreviousEditor": "Előző szerkesztőablak megnyitása", "nextEditorInGroup": "A csoport következő szerkesztőablakának megnyitása", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Az első csoportban található szerkesztőablakok megjelenítése", "showEditorsInSecondGroup": "A második csoportban található szerkesztőablakok megjelenítése", "showEditorsInThirdGroup": "A harmadik csoportban található szerkesztőablakok megjelenítése", - "showEditorsInGroup": "A csoportban található szerkesztőablakok megjelenítése", "showAllEditors": "Összes szerkesztőablak megjelenítése", "openPreviousRecentlyUsedEditorInGroup": "A csoportban előző legutoljára használt szerksztőablak megnyitása", "openNextRecentlyUsedEditorInGroup": "A csoportban következő legutoljára használt szerksztőablak megnyitása", @@ -54,5 +48,8 @@ "moveEditorLeft": "Szerkesztőablak mozgatása balra", "moveEditorRight": "Szerkesztőablak mozgatása jobbra", "moveEditorToPreviousGroup": "Szerkesztőablak mozgatása az előző csoportba", - "moveEditorToNextGroup": "Szerkesztőablak mozgatása a következő csoportba" + "moveEditorToNextGroup": "Szerkesztőablak mozgatása a következő csoportba", + "moveEditorToFirstGroup": "Szerkesztőablak mozgatása az első csoportba", + "moveEditorToSecondGroup": "Szerkesztőablak mozgatása a második csoportba", + "moveEditorToThirdGroup": "Szerkesztőablak mozgatása a harmadik csoportba" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index b15ee093f22..37f4933240b 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Aktív szerkesztőablak mozgatása fülek vagy csoportok között", "editorCommand.activeEditorMove.arg.name": "Aktív szerkesztőablak mozgatási argumentum", - "editorCommand.activeEditorMove.arg.description": "Argumentumtulajdonságok:\n\t* 'to': karakterlánc, a mozgatás célpontja.\n\t* 'by': karakterlánc, a mozgatás egysége. Fülek (tab) vagy csoportok (group) alapján.\n\t* 'value': szám, ami meghatározza, hogy hány pozíciót kell mozgatni, vagy egy abszolút pozíciót, ahová mozgatni kell.", - "commandDeprecated": "A(z) **{0}** parancs el lett távolítva. A(z) **{1}** használható helyette", - "openKeybindings": "Billentyűparancsok beállítása" + "editorCommand.activeEditorMove.arg.description": "Argumentumtulajdonságok:\n\t* 'to': karakterlánc, a mozgatás célpontja.\n\t* 'by': karakterlánc, a mozgatás egysége. Fülek (tab) vagy csoportok (group) alapján.\n\t* 'value': szám, ami meghatározza, hogy hány pozíciót kell mozgatni, vagy egy abszolút pozíciót, ahová mozgatni kell." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 0cb7c46cb05..5d020bd339d 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Szövegfájl-összehasonlító.", "navigate.next.label": "Következő módosítás", "navigate.prev.label": "Előző módosítás", - "inlineDiffLabel": "Váltás inline nézetre", - "sideBySideDiffLabel": "Váltás párhuzamos nézetre" + "toggleIgnoreTrimWhitespace.label": "Térközlevágás mellőzése" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 0ef6405cab2..11d4a655ad1 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Bezárás", - "closeOthers": "Többi bezárása", - "closeRight": "Jobbra lévők bezárása", - "closeAll": "Összes bezárása", - "closeAllUnmodified": "Nem módosultak bezárása", - "keepOpen": "Maradjon nyitva", - "showOpenedEditors": "Megnyitott szerkesztőablak megjelenítése", "araLabelEditorActions": "Szerkesztőablak-műveletek" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 6ed546539cf..9fd111df3c0 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Nem támogatott]", + "userIsAdmin": "(Rendszergazda)", + "userIsSudo": "(Superuser)", "devExtensionWindowTitlePrefix": "[Kiegészítő fejlesztői példány]" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/hun/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index b21a79bc546..b88b3f6c04e 100644 --- a/i18n/hun/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/hun/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "Elrejtés az oldalsávról" + "hideView": "Elrejtés" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/common/theme.i18n.json b/i18n/hun/src/vs/workbench/common/theme.i18n.json index b30bec0d245..634a2ddeccc 100644 --- a/i18n/hun/src/vs/workbench/common/theme.i18n.json +++ b/i18n/hun/src/vs/workbench/common/theme.i18n.json @@ -6,17 +6,21 @@ { "tabActiveBackground": "Az aktív fül háttérszíne. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", "tabInactiveBackground": "Az inaktív fülek háttérszíne. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabBorder": "A füleket egymástól elválasztó keret színe. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabActiveBorder": "Az aktív fülek kiemelésére használt keretszín. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabActiveUnfocusedBorder": "Az aktív fülek kiemelésére használt keretszín egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni. ", - "tabActiveForeground": "Az aktív fül előtérszíne az aktív csoportban. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabInactiveForeground": "Az inaktív fülek előtérszíne az aktív csoportban. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabUnfocusedActiveForeground": "Az aktív fül előtérszíne egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", - "tabUnfocusedInactiveForeground": "Az inaktív fülek előtérszíne egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőablakokat a szerkesztőterületen. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabHoverBackground": "A fülek háttérszíne amikor az egérkurzor fölöttük van. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabUnfocusedHoverBackground": "A fülek háttérszíne egy fókusz nélküli csoportban, amikor az egérkurzor fölötte van. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabBorder": "A füleket egymástól elválasztó keret színe. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabActiveBorder": "Az aktív fülek kiemelésére használt keret színe. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabActiveUnfocusedBorder": "Az aktív fülek kiemelésére használt keret színe egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabHoverBorder": "A fülek kiemelésére használt keret színe amikor az egérkurzor fölöttük van. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabUnfocusedHoverBorder": "A fülek kiemelésére használt keret színe egy fókusz nélküli csoportban, amikor az egérkurzor fölöttük van. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabActiveForeground": "Az aktív fül előtérszíne az aktív csoportban. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabInactiveForeground": "Az inaktív fülek előtérszíne az aktív csoportban. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabUnfocusedActiveForeground": "Az aktív fül előtérszíne egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", + "tabUnfocusedInactiveForeground": "Az inaktív fülek előtérszíne egy fókusz nélküli csoportban. A fülek tartalmazzák a szerkesztőterületen lévő szerkesztőablakokat. Egy szerkesztőablak-csoportban több fül is megnyitható. Több szerkesztőablak-csoportot is létre lehet hozni.", "editorGroupBackground": "A szerkesztőcsoportok háttérszíne. A szerkesztőcsoportok szerkesztőablakokat tartalmaznak. A háttérszín akkor jelenik meg, ha a szerkesztőcsoportok mozgatva vannak.", "tabsContainerBackground": "A szerkesztőcsoport címsorának háttérszíne, ha a fülek engedélyezve vannak. A szerkesztőcsoportok szerkesztőablakokat tartalmaznak.", "tabsContainerBorder": "A szerkesztőcsoport címsorának keretszíne, ha a fülek engedélyezve vannak. A szerkesztőcsoportok szerkesztőablakokat tartalmaznak.", - "editorGroupHeaderBackground": "A szerkesztőcsoport címsorának keretszíne, ha a fülek le vannak tiltva. A szerkesztőcsoportok szerkesztőablakokat tartalmaznak.", + "editorGroupHeaderBackground": "A szerkesztőcsoportok címsorának keretszíne, ha a fülek le vannak tiltva (`\"workbench.editor.showTabs\": false`). A szerkesztőcsoportok szerkesztőablakokat tartalmaznak.", "editorGroupBorder": "A szerkesztőcsoportokat elválasztó vonal színe. A szerkesztőcsoportok szerkesztőablakokat tartalmaznak.", "editorDragAndDropBackground": "A szerkesztőablakok mozgatásánál használt háttérszín. Érdemes átlátszó színt választani, hogy a szerkesztőablak tartalma továbbra is látszódjon.", "panelBackground": "A panelek háttérszíne. A panelek a szerkesztőterület alatt jelennek meg, és pl. itt található a kimenet és az integrált terminál.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "Az állapotsort az oldalsávtól és a szerkesztőablakoktól elválasztó keret színe, ha nincs mappa megnyitva. Az állapotsor az ablak alján jelenik meg. ", "statusBarItemActiveBackground": "Az állapotsor elemének háttérszíne kattintás esetén. Az állapotsor az ablak alján jelenik meg.", "statusBarItemHoverBackground": "Az állapotsor elemének háttérszíne, ha az egérkurzor fölötte van. Az állapotsor az ablak alján jelenik meg.", - "statusBarProminentItemBackground": "Az állapotsor kiemelt elemeinek háttérszíne. A kiemelt elemek kitűnnek az állapotsor többi eleme közül, így jelezve a fontosságukat. Az állapotsor az ablak alján jelenik meg.", - "statusBarProminentItemHoverBackground": "Az állapotsor kiemelt elemeinek háttérszíne, ha az egérkurzor fölöttük van. A kiemelt elemek kitűnnek az állapotsor többi eleme közül, így jelezve a fontosságukat. Az állapotsor az ablak alján jelenik meg.", + "statusBarProminentItemBackground": "Az állapotsor kiemelt elemeinek háttérszíne. A kiemelt elemek kitűnnek az állapotsor többi eleme közül, így jelezve a fontosságukat. Kapcsolja be a `Tabulátor billentyűvel mozgatott fókusz` módot a parancskatalógusban egy példa megtekintéséhez! Az állapotsor az ablak alján jelenik meg.", + "statusBarProminentItemHoverBackground": "Az állapotsor kiemelt elemeinek háttérszíne, ha az egérkurzor fölöttük van. A kiemelt elemek kitűnnek az állapotsor többi eleme közül, így jelezve a fontosságukat. Kapcsolja be a `Tabulátor billentyűvel mozgatott fókusz` módot a parancskatalógusban egy példa megtekintéséhez! Az állapotsor az ablak alján jelenik meg.", "activityBarBackground": "A tevékenységsáv háttérszíne. A tevékenységsáv az ablak legszélén jelenik meg bal vagy jobb oldalon, segítségével lehet váltani az oldalsáv nézetei között.", "activityBarForeground": "A tevékenységsáv előtérszíne (pl. az ikonok színe). A tevékenységsáv az ablak legszélén jelenik meg bal vagy jobb oldalon, segítségével lehet váltani az oldalsáv nézetei között.", "activityBarBorder": "A tevékenyésgsáv keretszíne, ami elválasztja az oldalsávtól. A tevékenységsáv az ablak legszélén jelenik meg bal vagy jobb oldalon, segítségével lehet váltani az oldalsáv nézetei között.", diff --git a/i18n/hun/src/vs/workbench/common/views.i18n.json b/i18n/hun/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..52cc050953f --- /dev/null +++ b/i18n/hun/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Már van `{0}` azonosítójú nézet regisztrálva a következő helyen: `{1}`" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json index 8fa88c8859b..f67fea70490 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Szerkesztőablak bezárása", "closeWindow": "Ablak bezárása", "closeWorkspace": "Munkaterület bezárása", "noWorkspaceOpened": "Az aktuális példányban nincs egyetlen munkaterület sem nyitva, amit be lehetne zárni.", @@ -30,6 +29,7 @@ "openRecent": "Legutóbbi megnyitása...", "quickOpenRecent": "Legutóbbi gyors megnyitása...", "closeMessages": "Értesítések törlése", + "openIssueReporter": "Hibajelentő megnyitása", "reportIssueInEnglish": "Probléma jelentése", "reportPerformanceIssue": "Teljesítményproblémák jelentése", "keybindingsReference": "Billentyűparancs-referencia", @@ -52,21 +52,5 @@ "displayLanguage": "Meghatározza a VSCode felületének nyelvét.", "doc": "Az elérhető nyelvek listája a következő címen tekinthető meg: {0}", "restart": "Az érték módosítása után újra kell indítani a VSCode-ot.", - "fail.createSettings": "Nem sikerült a(z) '{0}' létrehozás ({1}).", - "openLogsFolder": "Naplómappa megnyitása", - "showLogs": "Naplók megjelenítése...", - "mainProcess": "Fő", - "sharedProcess": "Megosztott", - "rendererProcess": "Megjelenítő", - "extensionHost": "Kiegészítő gazdafolyamata", - "selectProcess": "Válasszon folyamatot!", - "setLogLevel": "Naplózási szint beállítása", - "trace": "Nyomkövetés", - "debug": "Hibakeresés", - "info": "Információ", - "warn": "Figyelmeztetés", - "err": "Hiba", - "critical": "Kritikus", - "off": "Kikapcsolva", - "selectLogLevel": "Naplózási szint beállítása" + "fail.createSettings": "Nem sikerült a(z) '{0}' létrehozás ({1})." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json index ffdce8089b5..e6f6299231e 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Nézet", "help": "Súgó", "file": "Fájl", - "developer": "Fejlesztői", "workspaces": "Munkaterületek", + "developer": "Fejlesztői", + "workbenchConfigurationTitle": "Munkaterület", "showEditorTabs": "Meghatározza, hogy a megnyitott szerkesztőablakok telején megjelenjenek-e a fülek", "workbench.editor.labelFormat.default": "Fájl nevének megjelenítése. Ha a fülek engedélyezve vannak, és két egyező nevű fájl van egy csoportban, az elérési útjuk eltérő része lesz hozzáfűzve a névhez. Ha a fülek le vannak tiltva, a fájl munkaterület könyvtárához képest relatív elérési útja jelenik meg, ha a szerkesztőablak aktív.", "workbench.editor.labelFormat.short": "A fájl nevének megjelenítése a könyvtár nevével együtt.", @@ -20,23 +21,23 @@ "showIcons": "Meghatározza, hogy a megnyitott szerkesztőablakok ikonnal együtt jelenjenek-e meg. A működéshez szükséges egy ikontéma engedélyezése is.", "enablePreview": "Meghatározza, hogy a megnyitott szerkesztőablakok előnézetként jelenjenek-e meg. Az előnézetként használt szerkesztőablakok újra vannak hasznosítva, amíg meg nem tartja őket a felhasználó (pl. dupla kattintás vagy szerkesztés esetén), és dőlt betűvel jelenik meg a címsoruk.", "enablePreviewFromQuickOpen": "Meghatározza, hogy a gyors megnyitás során megnyitott szerkesztőablakok előnézetként jelenjenek-e meg. Az előnézetként használt szerkesztőablakok újra vannak hasznosítva, amíg meg nem tartja őket a felhasználó (pl. dupla kattintás vagy szerkesztés esetén).", + "closeOnFileDelete": "Meghatározza, hogy bezáródjanak-e azok a szerkesztőablakok, melyekben olyan fájl van megnyitva, amelyet töröl vagy átnevez egy másik folyamat. A beállítás letiltása esetén a szerkesztőablak nyitva marad módosított állapotban ilyen esemény után. Megjegyzés: az alkalmazáson belüli törlések esetén mindig bezáródik a szerkesztőablakok, a módosított fájlok pedig soha nem záródnak be, hogy az adatok megmaradjanak.", "editorOpenPositioning": "Meghatározza, hogy hol nyíljanak meg a szerkesztőablakok. A 'left' vagy 'right' használata esetén az aktív szerkesztőablaktól jobbra vagy balra nyílnak meg az újak. 'first' vagy 'last' esetén a szerkesztőablakok a jelenleg aktív ablaktól függetlenül nyílnak meg.", "revealIfOpen": "Meghatározza, hogy egy szerkesztőablak fel legyen-e fedve, ha már meg van nyitva a látható csoportok bármelyiképben. Ha le van tiltva, akkor egy új szerkesztőablak nyílik az aktív szerkesztőablak-csoportban. Ha engedélyezve van, akkor a már megnyitott szerkesztőablak lesz felfedve egy új megnyitása helyett. Megjegyzés: vannak esetek, amikor ez a beállítás figyelmen kívül van hagyva, pl. ha egy adott szerkesztőablak egy konkrét csoportban vagy a jelenleg aktív csoport mellett van menyitva.", + "swipeToNavigate": "Navigálás a nyitott fájlok között háromujjas, vízszintes húzással.", "commandHistory": "Meghatározza, hogy hány legutóbb használt parancs jelenjen meg a parancskatalógus előzményeinek listájában. Az előzmények kikapcsolásához állítsa az értéket nullára.", "preserveInput": "Meghatározza, hogy a legutóbb beírt parancs automatikusan helyre legyen-e állítva a parancskatalógus következő megnyitása során.", "closeOnFocusLost": "Meghatározza, hogy a gyors megnyitás automatikusan bezáródjon-e amint elveszíti a fókuszt.", "openDefaultSettings": "Meghatározza, hogy a beállítások megnyitásakor megnyíljon-e egy szerkesztő az összes alapértelmezett beállítással.", "sideBarLocation": "Meghatározza az oldalsáv helyét. Az oldalsáv megjelenhet a munkaterület bal vagy jobb oldalán.", + "panelDefaultLocation": "Meghatározza a panel alapértelmezett pozícióját. A panel a munkaterület alján vagy jobb oldalán jelenhet meg.", "statusBarVisibility": "Meghatározza, hogy megjelenjen-e az állapotsor a munkaterület alján.", "activityBarVisibility": "Meghatározza, hogy megjelenjen-e a tevékenységsáv a munkaterületen.", - "closeOnFileDelete": "Meghatározza, hogy bezáródjanak-e azok a szerkesztőablakok, melyekben olyan fájl van megnyitva, amelyet töröl vagy átnevez egy másik folyamat. A beállítás letiltása esetén a szerkesztőablak nyitva marad módosított állapotban ilyen esemény után. Megjegyzés: az alkalmazáson belüli törlések esetén mindig bezáródik a szerkesztőablakok, a módosított fájlok pedig soha nem záródnak be, hogy az adatok megmaradjanak.", - "enableNaturalLanguageSettingsSearch": "Meghatározza, hogy engedélyezve van-e a természetes nyelvi keresési mód a beállításoknál.", "fontAliasing": "Meghatározza a munkaterületen megjelenő betűtípusok élsimítási módszerét.\n- default: Szubpixeles betűsimítás. A legtöbb nem-retina típusú kijelzőn ez adja a legélesebb szöveget.\n- antialiased: A betűket pixelek, és nem szubpixelek szintjén simítja. A betűtípus vékonyabbnak tűnhet összességében.\n- none: Letiltja a betűtípusok élsimítését. A szövegek egyenetlen, éles szélekkel jelennek meg.", "workbench.fontAliasing.default": "Szubpixeles betűsimítás. A legtöbb nem-retina típusú kijelzőn ez adja a legélesebb szöveget.", "workbench.fontAliasing.antialiased": "A betűket pixelek, és nem szubpixelek szintjén simítja. A betűtípus vékonyabbnak tűnhet összességében.", "workbench.fontAliasing.none": "Letiltja a betűtípusok élsimítését. A szövegek egyenetlen, éles szélekkel jelennek meg.", - "swipeToNavigate": "Navigálás a nyitott fájlok között háromujjas, vízszintes húzással.", - "workbenchConfigurationTitle": "Munkaterület", + "enableNaturalLanguageSettingsSearch": "Meghatározza, hogy engedélyezve van-e a természetes nyelvi keresési mód a beállításoknál.", "windowConfigurationTitle": "Ablak", "window.openFilesInNewWindow.on": "A fájlok új ablakban nyílnak meg", "window.openFilesInNewWindow.off": "A fájlok abban az ablakban nyílnak meg, ahol a mappájuk meg van nyitva vagy a legutoljára aktív ablakban", diff --git a/i18n/hun/src/vs/workbench/electron-browser/window.i18n.json b/i18n/hun/src/vs/workbench/electron-browser/window.i18n.json index 3f8ae5cf9dd..59e05312870 100644 --- a/i18n/hun/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/hun/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Kivágás", "copy": "Másolás", "paste": "Beillesztés", - "selectAll": "Összes kijelölése" + "selectAll": "Összes kijelölése", + "runningAsRoot": "Nem ajánlott a {0} 'root'-két futtatása." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json b/i18n/hun/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json index 1631851aee5..ef8b1ac13eb 100644 --- a/i18n/hun/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json @@ -5,7 +5,7 @@ // Do not edit this file. It is machine generated. { "wordWrapMigration.ok": "OK", - "wordWrapMigration.dontShowAgain": "Ne jelenjen meg újra", + "wordWrapMigration.dontShowAgain": "Ne jelenítse meg újra", "wordWrapMigration.openSettings": "Beállítások megnyitása", "wordWrapMigration.prompt": "Az `editor.wrappingColumn` beállítás elavult az `editor.wordWrap` bevezetése miatt." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index fa1bc4e164b..c02cc939c66 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "A hibakeresési eszköztár háttérszíne." + "debugToolBarBackground": "A hibakeresési eszköztár háttérszíne.", + "debugToolBarBorder": "A hibakeresési eszköztár keretszíne." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index a54b3a8b776..06dec99b6e3 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,8 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "JSON-sémakonfigurációk a 'launch.json' validálásához.", "vscode.extension.contributes.debuggers.windows": "Windows-specifikus beállítások.", "vscode.extension.contributes.debuggers.windows.runtime": "A Windows által használt futtatókörnyezet.", - "vscode.extension.contributes.debuggers.osx": "OS X-specifikus beállítások.", - "vscode.extension.contributes.debuggers.osx.runtime": "Az OSX által használt futtatókörnyezet.", + "vscode.extension.contributes.debuggers.osx": "macOS-specifikus beállítások.", + "vscode.extension.contributes.debuggers.osx.runtime": "A macOS által használt futtatókörnyezet.", "vscode.extension.contributes.debuggers.linux": "Linux-specifikus beállítások.", "vscode.extension.contributes.debuggers.linux.runtime": "A Linux által használt futtatókörnyezet.", "vscode.extension.contributes.breakpoints": "Töréspontokat szolgáltat.", diff --git a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 8e82d560ff0..9708ac70e9b 100644 --- a/i18n/hun/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "hibakereső", - "debug.terminal.not.available.error": "Az integrált terminál nem elérhető" + "debug.terminal.title": "hibakereső" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index a33718b8e73..b8ed67afeb5 100644 --- a/i18n/hun/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Új parancssor megnyitása", "globalConsoleActionMacLinux": "Új terminál megnyitása", "scopedConsoleActionWin": "Megnyitás a parancssorban", - "scopedConsoleActionMacLinux": "Megnyitás a terminálban", - "openFolderInIntegratedTerminal": "Megnyitás a terminálban" + "scopedConsoleActionMacLinux": "Megnyitás a terminálban" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index a03a32613a6..0ad54ad8b33 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Ez a kiegészítő a közelmúltban megnyitott fájlok alapján ajánlott.", + "neverShowAgain": "Ne jelenjen meg újra", + "close": "Bezárás", "workspaceRecommendation": "Ez a kiegészítő az aktuális munkaterület felhasználói által ajánlott.", + "fileBasedRecommendation": "Ez a kiegészítő a közelmúltban megnyitott fájlok alapján ajánlott.", "exeBasedRecommendation": "Ez a kiegészítő azért ajánlott, mert a következő telepítve van: {0}.", "reallyRecommended2": "Ehhez a fájltípushoz a(z) '{0}' kiegészítő ajánlott.", "reallyRecommendedExtensionPack": "Ehhez a fájltípushoz a(z) '{0}' kiegészítőcsomag ajánlott.", "showRecommendations": "Ajánlatok megjelenítése", "install": "Telepítés", - "neverShowAgain": "Ne jelenítse meg újra", - "close": "Bezárás", + "showLanguageExtensions": "A piactéren található olyan kiegészítő, ami segíthet a(z) '.{0}' fájloknál", + "searchMarketplace": "Keresés a piactéren", "workspaceRecommended": "A munkaterülethez vannak javasolt kiegészítők", "installAll": "Összes telepítése", "ignoreExtensionRecommendations": "Figyelmen kívül akarja hagyni az összes javasolt kiegészítőt?", diff --git a/i18n/hun/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/hun/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index 4769b5168e9..73fb02efab6 100644 --- a/i18n/hun/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "Kiegészítő telepítése VSIX-ből...", + "installingMarketPlaceExtension": "Kiegészítő telepítése a piactérről...", + "uninstallingExtension": "Kiegészítő eltávolítása...", "enableDependeciesConfirmation": "A(z) '{0}' engedélyezésével annak függőségei is engedélyezve lesznek. Szeretné folytatni?", "enable": "Igen", "doNotEnable": "Nem", diff --git a/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..652267823c8 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Munkaterület", + "feedbackVisibility": "Meghatározza az állapotsoron megjelenő, visszajelzés tweetelése (mosoly) gomb láthatóságát." +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index d2b7c3c88fa..5bf2f90ef1e 100644 --- a/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "Hiányzó funkció kérése", "tell us why?": "Mondja el, hogy miért", "commentsHeader": "Visszajelzés", + "showFeedback": "Visszajelzésre szolgáló mosoly gomb megjelenítése az állapotsoron", "tweet": "Tweer", "character left": "karakter maradt", "characters left": "karakter maradt", diff --git a/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..d2ae286b72e --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "Elrejtés" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index d032a29e684..d115d415af9 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "Fájl", "revealInSideBar": "Megjelenítés az oldalsávon", "acceptLocalChanges": "A lemezen lévő tartalom felülírása a saját módosításokkal", - "revertLocalChanges": "Saját módosítások elvetése és a lemezen lévő tartalom visszaállítása" + "revertLocalChanges": "Saját módosítások elvetése és a lemezen lévő tartalom visszaállítása", + "copyPathOfActive": "Aktív fájl elérési útjának másolása", + "saveAllInGroup": "Összes mentése a csoportban", + "saveFiles": "Összes fájl mentése", + "revert": "Fájl visszaállítása", + "compareActiveWithSaved": "Aktív fájl összehasonlítása a mentett változattal", + "closeEditor": "Szerkesztőablak bezárása", + "view": "Nézet", + "openToSide": "Megnyitás oldalt", + "revealInWindows": "Megjelenítés a fájlkezelőben", + "revealInMac": "Megjelenítés a Finderben", + "openContainer": "Tartalmazó mappa megnyitása", + "copyPath": "Elérési út másolása", + "saveAll": "Összes mentése", + "compareWithSaved": "Összehasonlítás a mentett változattal", + "compareWithSelected": "Összehasonlítás a kiválasztottal", + "compareSource": "Kijelölés összehasonlításhoz", + "compareSelected": "Kiválasztottak összehasonlítása", + "close": "Bezárás", + "closeOthers": "Többi bezárása", + "closeUnmodified": "Nem módosultak bezárása", + "closeAll": "Összes bezárása", + "deleteFile": "Végleges törlés" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 559fe056a7d..7c5ad91feba 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Újrapróbálkozás", - "rename": "Átnevezés", "newFile": "Új fájl", "newFolder": "Új mappa", + "rename": "Átnevezés", + "delete": "Törlés", + "copyFile": "Másolás", + "pasteFile": "Beillesztés", + "retry": "Újrapróbálkozás", "openFolderFirst": "Mappák vagy fájlok létrehozásához először nyisson meg egy mappát!", "newUntitledFile": "Új, névtelen fájl", "createNewFile": "Új fájl", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "Áthelyezés a lo&&mtárba", "deleteButtonLabelTrash": "Áthelyezés a &&kukába", "deleteButtonLabel": "&&Törlés", + "dirtyMessageFilesDelete": "Olyan fájlokat készül törölni, amelyek nem mentett változtatásokat tartalmaznak. Folytatja?", "dirtyMessageFolderOneDelete": "Törölni készül egy olyan mappát, melyben egy nem mentett változtatásokat tartalmazó fájl van. Folytatja?", "dirtyMessageFolderDelete": "Törölni készül egy olyan mappát, melyben {0} nem mentett változtatásokat tartalmazó fájl van. Folytatja?", "dirtyMessageFileDelete": "Törölni készül egy olyan fájlt, amely nem mentett változtatásokat tartalmaz. Folytatja?", "dirtyWarning": "A módosítások elvesznek, ha nem menti őket.", + "confirmMoveTrashMessageMultiple": "Törli a következő {0} fájlt?", "confirmMoveTrashMessageFolder": "Törli a(z) '{0}' nevű mappát és a teljes tartalmát?", "confirmMoveTrashMessageFile": "Törli a(z) '{0}' nevű fájlt?", "undoBin": "Helyreállíthatja a lomtárból.", "undoTrash": "Helyreállíthatja a kukából.", "doNotAskAgain": "Ne kérdezze meg újra", - "confirmDeleteMessageFolder": "Törli a(z) {0} mappát és a teljes tartalmát?", - "confirmDeleteMessageFile": "Véglegesen törli a következőt: {0}?", + "confirmDeleteMessageMultiple": "Véglegesen törli a következő {0} fájlt?", + "confirmDeleteMessageFolder": "Törli a(z) '{0}' nevű mappát és annak teljes tartalmát? ", + "confirmDeleteMessageFile": "Véglegesen törli a(z) '{0}' nevű fájlt?", "irreversible": "A művelet nem vonható vissza!", "permDelete": "Végleges törlés", - "delete": "Törlés", "importFiles": "Fájlok importálása", "confirmOverwrite": "A célmappában már van ilyen nevű mappa vagy fájl. Le szeretné cserélni?", "replaceButtonLabel": "&&Csere", - "copyFile": "Másolás", - "pasteFile": "Beillesztés", + "fileDeleted": "A fájl időközben törölve lett vagy át lett helyezve", + "fileIsAncestor": "A másolandó fájl a célmappa szülője", "duplicateFile": "Duplikálás", - "openToSide": "Megnyitás oldalt", - "compareSource": "Kijelölés összehasonlításhoz", "globalCompareFile": "Aktív fájl összehasonlítása...", "openFileToCompare": "Fájlok összehasonlításához elősször nyisson meg egy fájlt.", - "compareWith": "'{0}' összehasonlítása a következővel: '{1}'", - "compareFiles": "Fájlok összehasonlítása", "refresh": "Frissítés", - "save": "Mentés", - "saveAs": "Mentés másként...", - "saveAll": "Összes mentése", "saveAllInGroup": "Összes mentése a csoportban", - "saveFiles": "Összes fájl mentése", - "revert": "Fájl visszaállítása", "focusOpenEditors": "Váltás a megnyitott szerkesztőablakok nézetre", "focusFilesExplorer": "Váltás a fájlkezelőre", "showInExplorer": "Aktív fájl megjelenítése az oldalsávon", @@ -56,20 +52,11 @@ "refreshExplorer": "Fájlkezelő frissítése", "openFileInNewWindow": "Aktív fájl megnyitása új ablakban", "openFileToShowInNewWindow": "Fájl új ablakban történő megnyitásához először nyisson meg egy fájlt", - "revealInWindows": "Megjelenítés a fájlkezelőben", - "revealInMac": "Megjelenítés a Finderben", - "openContainer": "Tartalmazó mappa megnyitása", - "revealActiveFileInWindows": "Aktív fájl megjelenítése a Windows Intézőben", - "revealActiveFileInMac": "Aktív fájl megjelenítése a Finderben", - "openActiveFileContainer": "Aktív fájlt tartalmazó mappa megnyitása", "copyPath": "Elérési út másolása", - "copyPathOfActive": "Aktív fájl elérési útjának másolása", "emptyFileNameError": "Meg kell adni egy fájl vagy mappa nevét.", "fileNameExistsError": "Már létezik **{0}** nevű fájl vagy mappa ezen a helyszínen. Adjon meg egy másik nevet!", "invalidFileNameError": "A(z) **{0}** név nem érvényes fájl- vagy mappanév. Adjon meg egy másik nevet!", "filePathTooLongError": "A(z) **{0}** név egy olyan elérési utat eredményez, ami túl hosszú. Adjon meg egy másik nevet!", - "compareWithSaved": "Aktív fájl összehasonlítása a mentett változattal", - "modifiedLabel": "{0} (a lemezen) ↔ {1}", "compareWithClipboard": "Aktív fájl összehasonlítása a vágólap tartalmával", "clipboardComparisonLabel": "Vágólap ↔ {0}" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index dd9057b1fa4..57192b1bc98 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Fájlok elérési útjának másolásához elősször nyisson meg egy fájlt", - "openFileToReveal": "Fájlok felfedéséhez elősször nyisson meg egy fájlt" + "revealInWindows": "Megjelenítés a fájlkezelőben", + "revealInMac": "Megjelenítés a Finderben", + "openContainer": "Tartalmazó mappa megnyitása", + "saveAs": "Mentés másként...", + "save": "Mentés", + "saveAll": "Összes mentése", + "removeFolderFromWorkspace": "Mappa eltávolítása a munkaterületről", + "genericRevertError": "Nem sikerült a(z) '{0}' visszaállítása: {1}", + "modifiedLabel": "{0} (a lemezen) ↔ {1}", + "openFileToReveal": "Fájlok felfedéséhez elősször nyisson meg egy fájlt", + "openFileToCopy": "Fájlok elérési útjának másolásához elősször nyisson meg egy fájlt" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 22341f239a2..c8272df7913 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "Szerkesztőablak", "formatOnSave": "Fájlok formázása mentéskor. Az adott nyelvhez rendelkezésre kell állni formázónak, nem lehet beállítva automatikus mentés, és a szerkesztő nem állhat éppen lefelé.", "explorerConfigurationTitle": "Fájlkezelő", - "openEditorsVisible": "A megnyitott szerkesztőablakok panelen megjelenített szerkesztőablakok száma. Állítsa 0-ra, ha el szeretné rejteni a panelt.", - "dynamicHeight": "Meghatározza, hogy a megnyitott szerkesztőablakok szakasz magassága automatikusan illeszkedjen a megnyitott elemek számához vagy sem.", + "openEditorsVisible": "A megnyitott szerkesztőablakok panelen megjelenített szerkesztőablakok száma.", "autoReveal": "Meghatározza, hogy a fájlkezelőben automatikusan fel legyenek fedve és ki legyenek jelölve a fájlok, amikor megnyitják őket.", "enableDragAndDrop": "Meghatározza, hogy a fájlkezelőben áthelyezhetők-e a fájlok és mappák húzással.", "confirmDragAndDrop": "Meghatározza, hogy a fájlkezelő kérjen-e megerősítést fájlok és mappák húzással történő áthelyezése esetén.", diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 0bb33fdc628..da61a7106fd 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Használja a jobbra lévő szerkesztői eszköztáron található műveleteket a saját módosítások **visszavonására** vagy **írja felül** a lemezen lévő tartalmat a változtatásokkal", - "discard": "Elvetés", + "overwriteElevated": "Felülírás rendszergazdaként...", + "saveElevated": "Újrapróbálkozás rendszergazdaként...", "overwrite": "Felülírás", "retry": "Újrapróbálkozás", - "readonlySaveError": "Nem sikerült menteni a(z) '{0}' fájlt: a fájl írásvédett. Válassza a 'Felülírás' lehetőséget a védelem eltávolításához.", + "discard": "Elvetés", + "readonlySaveErrorAdmin": "Nem sikerült menteni a(z) '{0}' fájlt: a fájl írásvédett. Válassza a 'Felülírás rendszergazdaként' lehetőséget a védelem eltávolításához!", + "readonlySaveError": "Nem sikerült menteni a(z) '{0}' fájlt: a fájl írásvédett. Válassza a 'Felülírás' lehetőséget a védelem eltávolításának megkísérléséhez!", + "permissionDeniedSaveError": "Nem sikerült menteni a(z) '{0}' fájlt: nincs megfelelő jogosultság. Válassza az 'Újrapróbálkozás rendszergazdaként' lehetőséget az újrapróbálkozáshoz adminisztrátorként!", "genericSaveError": "Hiba a(z) '{0}' mentése közben: {1}", "staleSaveError": "Nem sikerült menteni a(z) '{0}' fájlt: a lemezen lévő tartalom újabb. Kattintson az **Összehasonlítás*** gombra a helyi és a lemezen lévő változat összehasonlításához.", "compareChanges": "Összehasonlítás", diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index e00a7141ecf..a171c2f9995 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,7 +10,8 @@ "dropFolder": "Szeretné hozzáadni a mappát a munkaterülethez?", "addFolders": "Mappák hozzá&&adása", "addFolder": "Mappa hozzá&&adása", - "confirmMove": "Biztosan át szeretné helyezni a következőt: '{0}'?", + "confirmMultiMove": "Át szeretné helyezni a következő {0} fájlt?", + "confirmMove": "Át szeretné helyezni a(z) '{0}' nevű fájlt?", "doNotAskAgain": "Ne kérdezze meg újra", "moveButtonLabel": "&&Áthelyezés", "confirmOverwriteMessage": "A célmappában már létezik '{0}' nevű elem. Le szeretné cserélni?", diff --git a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 99cf9cb13e7..4e9c224f2c9 100644 --- a/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Megnyitott szerkesztőablakok", "openEditosrSection": "Megnyitott szerkesztőablakok szakasz", - "dirtyCounter": "{0} nincs mentve", - "saveAll": "Összes mentése", - "closeAllUnmodified": "Nem módosultak bezárása", - "closeAll": "Összes bezárása", - "compareWithSaved": "Összehasonlítás a mentett változattal", - "close": "Bezárás", - "closeOthers": "Többi bezárása" + "dirtyCounter": "{0} nincs mentve" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..a647b02e9cb --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "Napló (elsődleges)", + "sharedLog": "Napló (megosztott)", + "rendererLog": "Napló (ablak)", + "extensionsLog": "Napló (kiegészítő gazdafolyamata)", + "developer": "Fejlesztői" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..fde9c01e66f --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Naplómappa megnyitása", + "showLogs": "Naplók megjelenítése...", + "mainProcess": "Elsődleges", + "sharedProcess": "Megosztott", + "rendererProcess": "Ablak", + "extensionHost": "Kiegészítő gazdafolyamata", + "selectProcess": "Válasszon folyamatot!", + "openLogFile": "Naplófájl megnyitása...", + "setLogLevel": "Naplózási szint beállítása", + "trace": "Nyomkövetés", + "debug": "Hibakeresés", + "info": "Információ", + "warn": "Figyelmeztetés", + "err": "Hiba", + "critical": "Kritikus", + "off": "Kikapcsolva", + "selectLogLevel": "Naplózási szint beállítása" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/hun/src/vs/workbench/parts/markers/common/messages.i18n.json index 1ecd95e356c..12347f91b9e 100644 --- a/i18n/hun/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Nézet", - "problems.view.toggle.label": "Problémák be- és kikapcsolása", - "problems.view.focus.label": "Váltás a problémákra", + "problems.view.toggle.label": "Problémák be- és kikapcsolása (hiba, figyelmeztetés, információ)", + "problems.view.focus.label": "Váltás a problémákra (hiba, figyelmeztetés, információ)", "problems.panel.configuration.title": "Problémák-nézet", "problems.panel.configuration.autoreveal": "Meghatározza, hogy a problémák nézet automatikusan felfedje-e a fájlokat, amikor megnyitja őket.", "markers.panel.title.problems": "Problémák", diff --git a/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..5cbaa37bf16 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Kimenet", + "logViewer": "Naplófájl-megjelenítő", + "viewCategory": "Nézet", + "clearOutput.label": "Kimenet törlése" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/hun/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..c164d86f883 --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} – Kimenet", + "channel": "A(z) '{0}' kimeneti csatornája" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 5f23e1e85aa..878fe224656 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -17,6 +17,7 @@ "resetLabel": "Billentyűparancs visszaállítása", "showConflictsLabel": "Konfliktusok megjelenítése", "copyLabel": "Másolás", + "copyCommandLabel": "Parancs másolása", "error": "'{0}' hiba a billentyűparancsok szerkesztése közben. Nyissa meg a 'keybindings.json' fájlt, és ellenőrizze!", "command": "Parancs", "keybinding": "Billentyűparancs", diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 9b9670df23c..dd151493ad8 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 illeszkedő beállítás", "settingsFound": "{0} illeszkedő beállítás", "totalSettingsMessage": "Összesen {0} beállítás", + "nlpResult": "Természetes nyelvi keresés eredményei", + "filterResult": "Szűrt találatok", "defaultSettings": "Alapértelmezett beállítások", "defaultFolderSettings": "Alapértelmezett mappabeállítások", "defaultEditorReadonly": "A jobb oldalon lévő szerkesztőablak tartalmának módosításával írhatja felül az alapértelmezett beállításokat.", diff --git a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index ef9a96afe7b..3a1caa89fed 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Próbálja ki a természetes nyelvi keresést!", "defaultSettings": "A jobb oldalon lévő szerkesztőablakban elhelyezett beállítások felülírják az alapértelmezett beállításokat.", "noSettingsFound": "Beállítás nem található.", "settingsSwitcherBarAriaLabel": "Beállításkapcsoló", "userSettings": "Felhasználói beállítások", "workspaceSettings": "Munkaterület-beállítások", - "folderSettings": "Mappabeálíltások", - "enableFuzzySearch": "Természetes nyelvi keresés engedélyezése" + "folderSettings": "Mappabeálíltások" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/hun/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 1fd4f23c9d2..35cc39622d0 100644 --- a/i18n/hun/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Gyakran használt", - "mostRelevant": "Legfontosabb", "defaultKeybindingsHeader": "A billentyűparancsok fájlban elhelyezett billentyűparancsok felülírják az alapértelmezett beállításokat" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 7e61210cdf7..cd538504f47 100644 --- a/i18n/hun/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Nézet", "commandsHandlerDescriptionDefault": "Parancsok megjelenítése és futtatása", "gotoLineDescriptionMac": "Sor megkeresése", "gotoLineDescriptionWin": "Sor megkeresése", diff --git a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 4f8b481dc00..39ce0536498 100644 --- a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "Git megjelenítése", "source control": "Verziókezelő rendszer", "toggleSCMViewlet": "Verziókezelő megjelenítése", - "view": "Nézet" + "view": "Nézet", + "scmConfigurationTitle": "VKR (SCM)", + "alwaysShowProviders": "Mindig megjelenjen-e a verziókezelő rendszerek szakasz.", + "diffDecorations": "Vezérli a szerkesztőablakban megjelenő, változásokat jelölő dekorátorokat.", + "inputCounter": "Meghatározza, hogy mikor jelenjen meg a bemeneti karakterszámláló." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 821a91e9b57..aa865d6ba59 100644 --- a/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "Verziókezelő rendszerek", "hideRepository": "Elrejtés", + "commitMessageInfo": "{0} karakter a jelenlegi sorban", + "commitMessageCountdown": "{0} karakter maradt az aktuális sorban", + "commitMessageWarning": " {0} karakterrel több, mint {1} az aktuális sorban", "installAdditionalSCMProviders": "További verziókezelő rendszerek telepítése...", "no open repo": "Nincs aktív verziókezelő rendszer.", "source control": "Verziókezelő rendszer", diff --git a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 9f5f0bf4d8b..ce4480e2eb9 100644 --- a/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Előző keresőkifejezés megjelenítése", "showSearchViewlet": "Keresés megjelenítése", "findInFiles": "Keresés a fájlokban", - "findInFilesWithSelectedText": "Keresés a fájlokban a kijelölt szöveg alapján", "replaceInFiles": "Csere a fájlokban", - "replaceInFilesWithSelectedText": "Csere a fájlokban a kijelölt szöveg alapján", "RefreshAction.label": "Frissítés", "CollapseDeepestExpandedLevelAction.label": "Összes bezárása", "ClearSearchResultsAction.label": "Törlés", diff --git a/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index e1fb57e6aa6..e928937e0a8 100644 --- a/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Keresés mappában...", + "findInWorkspace": "Keresés a munkaterületen...", "showTriggerActions": "Szimbólum megkeresése a munkaterületen...", "name": "Keresés", "search": "Keresés", + "showSearchViewlet": "Keresés megjelenítése", "view": "Nézet", + "findInFiles": "Keresés a fájlokban", "openAnythingHandlerDescription": "Fájl megkeresése", "openSymbolDescriptionNormal": "Szimbólum megkeresése a munkaterületen", - "searchOutputChannelTitle": "Keresés", "searchConfigurationTitle": "Keresés", "exclude": "Globális minták konfigurálása fájlok és mappák keresésből való kizárásához. Örökli az összes globális mintát a fliex.exclude beállításból.", "exclude.boolean": "A globális minta, amire illesztve lesznek a fájlok elérési útjai. A minta engedélyezéséhez vagy letiltásához állítsa igaz vagy hamis értékre.", @@ -18,5 +21,6 @@ "useRipgrep": "Meghatározza, hogy a szövegben és fájlokban való kereséshez a ripgrep van-e használva.", "useIgnoreFiles": "Meghatározza, hogy a .gitignore és .ignore fájlok használva legyenek-e a kereséshez.", "search.quickOpen.includeSymbols": "Meghatározza, hogy a fájlok gyors megnyitásánál megjelenjenek-e a globális szimbólumkereső találatai.", - "search.followSymlinks": "Meghatározza, hogy keresés során követve legyenek-e a szimbolikus linkek." + "search.followSymlinks": "Meghatározza, hogy keresés során követve legyenek-e a szimbolikus linkek.", + "search.smartCase": "Figyelmen kívül hagyja a kis- és nagybetűket, ha a minta csak kisbetűkből áll, ellenkező esetben kis- és nagybetűérzékenyen keres" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..4d54491cc1e --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.scope": "(globális)", + "global.1": "(({0})", + "new.global": "Új globális kódrészlet-fájl...", + "group.global": "Létező kódrészletek", + "new.global.sep": "Új kódrészletek", + "openSnippet.pickLanguage": "Válasszon hozzon létre egy kódrészlet-fájlt!", + "openSnippet.label": "Felhasználói kódrészletek konfigurálása", + "preferences": "Beállítások" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 12f3a6365e8..61cbea48eca 100644 --- a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Kódrészlet nyelvének kiválasztása", - "openSnippet.errorOnCreate": "A(z) {0} nem hozható létre", - "openSnippet.label": "Felhasználói kódrészletek megnyitása", - "preferences": "Beállítások", "snippetSchema.json.default": "Üres kódrészlet", "snippetSchema.json": "Felhasználói kódrészlet-konfiguráció", "snippetSchema.json.prefix": "A kódrészlet IntelliSense-ben történő kiválasztásánál használt előtag", "snippetSchema.json.body": "A kódrészlet tartalma. Kurzorpozíciók definiálásához használja a '$1' és '${1:defaultText}' jelölőket, a '$0' pedig a végső kurzorpozíció. Változónevek a '${varName}' és '${varName:defaultText}' formában definiálhatók, pl.: 'Ez a fájl: $TM_FILENAME'.", - "snippetSchema.json.description": "A kódrészlet leírása" + "snippetSchema.json.description": "A kódrészlet leírása", + "snippetSchema.json.scope": "Azok nyelvek nevei, amelyekhez a kódrészlet tartozik, pl. 'typescript,javascript'." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..ac8bcd025bd --- /dev/null +++ b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Felhasználói kódrészlet" +} \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index b86aeaf6994..3931f7acd24 100644 --- a/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Ismeretlen nyelv található a következőben: `contributes.{0}.language`. A megadott érték: {1}", "invalid.path.0": "Hiányzó karakterlánc a `contributes.{0}.path`-ban. A megadott érték: {1}", + "invalid.language.0": "Nyelv elhagyása esetén a `contributes.{0}.path` értékének egy `.code-snippets`-fájlnak kell lennie. A megadott érték: {1}", + "invalid.language": "Ismeretlen nyelv található a következőben: `contributes.{0}.language`. A megadott érték: {1}", "invalid.path.1": "A `contributes.{0}.path` ({1}) nem a kiegészítő mappáján belül található ({2}). Emiatt előfordulhat, hogy a kiegészítő nem lesz hordozható.", "vscode.extension.contributes.snippets": "Kódrészleteket szolgáltat.", "vscode.extension.contributes.snippets-language": "Azon nyelv azonosítója, amely számára szolgáltatva van ez a kódrészlet.", "vscode.extension.contributes.snippets-path": "A kódrészlet-fájl elérési útja. Az elérési út relatív a kiegészítő mappájához, és általában a következővel kezdődik: './snippets/',", "badVariableUse": "A(z) '{0}' kiegészítőben egy vagy több kódrészlet nagy valószínűséggel keveri a kódrészletváltozók és a kódrészlet-helyjelölők fogalmát (további információ a következő oldalon található: https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax)", "badFile": "A(z) \"{0}\" kódrészletet tartalmazó fájlt nem sikerült beolvasni.", - "source.snippet": "Felhasználói kódrészlet", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 4d4b7d5d7cf..525d9caef57 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -13,7 +13,8 @@ "terminal.integrated.shellArgs.osx": "OS X-terminál esetén használt parancssori argumentumok.", "terminal.integrated.shell.windows": "A terminál által használt shell elérési útja Windowson. A Windows beépített shelljei (cmd, PowerShell vagy Bash on Ubuntu) használata esetén kell megadni.", "terminal.integrated.shellArgs.windows": "Windows-terminál esetén használt parancssori argumentumok.", - "terminal.integrated.rightClickCopyPaste": "Ha be van állítva, megakadályozza a helyi menü megjelenését a terminálon történő jobb kattintás esetén. Helyette másol, ha van kijelölés, és beilleszt, ha nincs.", + "terminal.integrated.rightClickCopyPaste": "Ha be van kapcsolva, megakadályozza, hogy megjelenjen a helyi menü a terminálon történő jobb kattintás esetén. Ehelyett másol, ha van kijelölés, és beilleszt, ha nincs.", + "terminal.integrated.copyOnSelection": "Ha be van kapcsolva, a terminálban kijelölt szöveg a vágólapra lesz másolva.", "terminal.integrated.fontFamily": "Meghatározza a terminál betűtípusát. Alapértelmezett értéke az editor.fontFamily értéke.", "terminal.integrated.fontSize": "Meghatározza a terminálban használt betű méretét, pixelekben.", "terminal.integrated.lineHeight": "Meghatározza a terminál sormagasságát. A tényleges méret a megadott szám és a terminál betűméretének szorzatából jön ki.", @@ -24,10 +25,12 @@ "terminal.integrated.setLocaleVariables": "Meghatározza, hogy a lokálváltozók be vannak-e állítva a terminál indításánál. Alapértelmezett értéke igaz OS X-en, hamis más platformokon.", "terminal.integrated.cwd": "Explicit elérési út, ahol a terminál indítva lesz. Ez a shellfolyamat munkakönyvtára (cwd) lesz. Ez a beállítás nagyon hasznos olyan munkaterületeken, ahol a gyökérkönyvtár nem felel meg munkakönyvtárnak.", "terminal.integrated.confirmOnExit": "Meghatározza, hogy megerősítést kér-e az alkalamzás, ha van aktív terminál-munkafolyamat.", + "terminal.integrated.enableBell": "Meghatározza, hogy engedélyezve van-e a csengő a terminálba.", "terminal.integrated.commandsToSkipShell": "Olyan parancsazonosítók listája, melyek nem lesznek elküldve a shellnek, és ehelyett mindig a Code kezeli le őket. Ez lehetővé teszi, hogy az olyan billentyűparancsok, melyeket normál esetben a shell dolgozna fel, ugyanúgy működjenek, mint mikor a terminálon nincs fókusz. Például ilyen a gyorsmegnyitás indításához használt Ctrl+P.", "terminal.integrated.env.osx": "A VS Code folyamatához hozzáadott környezeti változókat tartalmazó objektum, amit az OS X-es terminál használ.", "terminal.integrated.env.linux": "A VS Code folyamatához hozzáadott környezeti változókat tartalmazó objektum, amit a linuxos terminál használ.", "terminal.integrated.env.windows": "A VS Code folyamatához hozzáadott környezeti változókat tartalmazó objektum, amit a windowsos terminál használ.", + "terminal.integrated.showExitAlert": "A `A terminálfolyamat a következő kilépési kóddal állt le` üzenet megjelenítése, ha a kilépési kód nem nulla.", "terminalCategory": "Terminál", "viewCategory": "Nézet" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index c671a91c989..8f1350c0d3c 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -14,6 +14,8 @@ "workbench.action.terminal.deleteWordRight": "Jobbra lévő szó törlése", "workbench.action.terminal.new": "Új integrált terminál létrehozása", "workbench.action.terminal.new.short": "Új terminál", + "workbench.action.terminal.newWorkspacePlaceholder": "Az aktuális munkakönyvtár kiválasztása az új terminálhoz", + "workbench.action.terminal.newInActiveWorkspace": "Új integrált terminál létrehozása (az aktív munkaterületen)", "workbench.action.terminal.focus": "Váltás a terminálra", "workbench.action.terminal.focusNext": "Váltás a következő terminálra", "workbench.action.terminal.focusPrevious": "Váltás az előző terminálra", diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index 3471cfec5dc..ff1983f42c6 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -9,5 +9,5 @@ "terminalCursor.foreground": "A terminál kurzorának előtérszíne.", "terminalCursor.background": "A terminál kurzorának háttérszíne. Lehetővé teszik az olyan karakterek színének módosítását, amelyek fölött egy blokk-típusú kurzor áll.", "terminal.selectionBackground": "A terminálban kijelölt tartalom háttérszíne.", - "terminal.ansiColor": "A(z) '{0}' ANSI-szín a terminálban." + "terminal.ansiColor": "'{0}' ANSI-szín a terminálban." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 45f5c16180a..1a4fb7a15a1 100644 --- a/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,7 @@ "terminal.integrated.chooseWindowsShellInfo": "Megváltoztathatja az alapértelmezett terminált a testreszabás gomb választásával.", "customize": "Testreszabás", "cancel": "Mégse", - "never again": "Rendben, ne jelenítse meg újra", + "never again": "Rendben, ne jelenjen meg újra", "terminal.integrated.chooseWindowsShell": "Válassza ki a preferált terminál shellt! Ez később módosítható a beállításokban.", "terminalService.terminalCloseConfirmationSingular": "Van egy aktív terminálmunkamenet. Szeretné megszakítani?", "terminalService.terminalCloseConfirmationPlural": "{0} aktív terminálmunkamenet van. Szeretné megszakítani?" diff --git a/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 79c64944348..6315a5d17bd 100644 --- a/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/hun/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -13,7 +13,7 @@ "read the release notes": "Üdvözöljük a {0} v{1} verziójában. Szeretné megtekinteni a kiadási jegyzéket?", "licenseChanged": "A licencfeltételek változtak. Olvassa végig!", "license": "Licenc elolvasása", - "neveragain": "Soha ne jelenítse meg újra", + "neveragain": "Ne jelenítse meg újra", "64bitisavailable": "Elérhető a {0} 64-bites Windowsra készült változata!", "learn more": "További információ", "updateIsReady": "Új {0}-frissítés érhető el.", @@ -23,6 +23,7 @@ "commandPalette": "Parancskatalógus...", "settings": "Beállítások", "keyboardShortcuts": "Billentyűparancsok", + "userSnippets": "Felhasználói kódrészletek", "selectTheme.label": "Színtéma", "themes.selectIconTheme.label": "Fájlikontéma", "not available": "A frissítések nem érhetők el", diff --git a/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index f77948f5276..e2deab2db4e 100644 --- a/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "A fájl egy könyvtár", + "fileNotModifiedError": "A fájl azóta nem módosult", "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként" } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json index 91ce4d8f750..fcbe399cbac 100644 --- a/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "A fájl túl nagy a megnyitáshoz", "fileNotFoundError": "Fájl nem található ({0})", "fileBinaryError": "A fájl binárisnak tűnik és nem nyitható meg szövegként", + "filePermission": "Engedély megtagadva a fájl írására ({0})", "fileExists": "A létrehozandó fájl már létezik ({0})", "fileMoveConflict": "Nem lehet áthelyezni vagy másolni. A fájl már létezik a célhelyen.", "unableToMoveCopyError": "Nem lehet áthelyezni vagy másolni. A fájl felülírná a mappát, amiben található.", diff --git a/i18n/hun/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/hun/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index 6928f2f1935..38b057d0682 100644 --- a/i18n/hun/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "A billentyűparancs aktiválási feltétele.", "keybindings.json.args": "A végrehajtandó parancs számára átadott argumentumok", "keyboardConfigurationTitle": "Billentyűzet", - "dispatch": "Meghatározza, hogy a billentyűleütések észleléséhez a `code` (ajánlott) vagy `keyCode` esemény legyen használva." + "dispatch": "Meghatározza, hogy a billentyűleütések észleléséhez a `code` (ajánlott) vagy `keyCode` esemény legyen használva.", + "touchbar.enabled": "Ha elérhető, engedélyezi a macOS érintősávgombokat a billentyűzeten." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/hun/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index a411a51ba59..5a0ddc8c042 100644 --- a/i18n/hun/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Szeretné menteni a(z) {0} fájlban elvégzett módosításokat?", "saveChangesMessages": "Szeretné menteni a következő {0} fájlban elvégzett módosításokat?", - "moreFile": "...1 további fájl nincs megjelenítve", - "moreFiles": "...{0} további fájl nincs megjelenítve", "saveAll": "Ö&&sszes mentése", "save": "Menté&&s", "dontSave": "&&Ne mentse", diff --git a/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index d67776bc433..afe4cf7833a 100644 --- a/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "Nincsenek fájlikonok", "iconThemeError": "A fájlikontéma ismeretlen vagy nincs telepítve.", "workbenchColors": "Felülírja az aktuális színtémában definiált színeket.", - "editorColors": "Felülírja az aktuális színtémában definiált, szerkesztőablakhoz kapcsolódó színeket és betűstílusokat.", "editorColors.comments": "Meghatározza a megjegyzések színét és stílusát.", "editorColors.strings": "Meghatározza a sztringliterálok színét és stílusát.", "editorColors.keywords": "Meghatározza a kulcsszavak színét és stílusát.", @@ -19,5 +18,6 @@ "editorColors.types": "Meghatározza a típusdeklarációk és -referenciák színét és stílusát.", "editorColors.functions": "Meghatározza a függvénydeklarációk és -referenciák színét és stílusát.", "editorColors.variables": "Meghatározza a változódeklarációk és -referenciák színét és stílusát.", - "editorColors.textMateRules": "Színek és stílusok beállítása textmate témázási szabályok alapján (haladó)." + "editorColors.textMateRules": "Színek és stílusok beállítása textmate témázási szabályok alapján (haladó).", + "editorColors": "Felülírja az aktuális színtémában definiált, szerkesztőablakhoz kapcsolódó színeket és betűstílusokat." } \ No newline at end of file diff --git a/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 068445ae82b..3c7eb68f49e 100644 --- a/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/hun/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Nem sikerült írni a munkaterület konfigurációs fájljába. Nyissa meg a fájlt, javítsa a benne található hibákat és figyelmeztetéseket, majd próbálja újra!", "errorWorkspaceConfigurationFileDirty": "Nem sikerült írni a munkaterület konfigurációs fájljába, mert módosítva lett. Mentse, majd próbálja újra!", "openWorkspaceConfigurationFile": "Munkaterület konfigurációs fájljának megnyitása", - "close": "Bezárás", - "enterWorkspace.close": "Bezárás", - "enterWorkspace.dontShowAgain": "Ne jelenítse meg újra", - "enterWorkspace.moreInfo": "További információ", - "enterWorkspace.prompt": "Tudjon meg többet arról, hogyan dolgozhat egyszerre több mappával a VS Code-ban!" + "close": "Bezárás" } \ No newline at end of file diff --git a/i18n/ita/extensions/git/out/autofetch.i18n.json b/i18n/ita/extensions/git/out/autofetch.i18n.json index b51df7e140d..96f76ecafff 100644 --- a/i18n/ita/extensions/git/out/autofetch.i18n.json +++ b/i18n/ita/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Sì", + "read more": "Altre informazioni", "no": "No", - "not now": "Non ora", - "suggest auto fetch": "Vorresti attivare il fetching automatico di repository Git?" + "not now": "Chiedimelo in seguito", + "suggest auto fetch": "Desideri che Code esegua `git fetch` periodicamente?" } \ No newline at end of file diff --git a/i18n/ita/extensions/git/out/commands.i18n.json b/i18n/ita/extensions/git/out/commands.i18n.json index b544cb5ca24..167af56bf54 100644 --- a/i18n/ita/extensions/git/out/commands.i18n.json +++ b/i18n/ita/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nQuesta operazione è IRREVERSIBILE. Il working set corrente andrà PERSO PER SEMPRE.", "yes discard tracked": "Rimuovi 1 file di cui viene tenuta traccia", "yes discard tracked multiple": "Rimuovi {0} file di cui viene tenuta traccia", + "unsaved files single": "Il seguente file non è stato salvato: {0}\n\nVuoi salvarlo prima di eseguirne il commit? ", + "unsaved files": "Ci sono {0} file non ancora salvati.\n\nVuoi salvarli prima di eseguirne il commit? ", + "save and commit": "Salva tutto & esegui Commit", + "commit": "Esegui il Commit comunque", "no staged changes": "Non ci sono modifiche in stage di cui eseguire il commit.\n\nSI desidera mettere in stage automaticamente tutte le modifiche ed eseguirne il commit direttamente?", "always": "Sempre", "no changes": "Non ci sono modifiche di cui eseguire il commit.", @@ -64,12 +68,12 @@ "no remotes to pull": "Il repository non contiene elementi remoti configurati come origini del pull.", "pick remote pull repo": "Selezionare un repository remoto da cui effettuare il pull del ramo", "no remotes to push": "Il repository non contiene elementi remoti configurati come destinazione del push.", - "push with tags success": "Il push con tag è riuscito.", "nobranch": "Estrarre un ramo per eseguire il push in un elemento remoto.", + "confirm publish branch": "La branch '{0}' non ha una branch corrispondente a monte. Desideri pubblicarla?", + "ok": "OK", + "push with tags success": "Il push con tag è riuscito.", "pick remote": "Selezionare un repository remoto in cui pubblicare il ramo '{0}':", "sync is unpredictable": "Questa azione consentirà di effettuare il push e il pull di commit da e verso '{0}'.", - "ok": "OK", - "never again": "OK, non visualizzare più", "no remotes to publish": "Il repository non contiene elementi remoti configurati come destinazione della pubblicazione.", "no changes stash": "Non ci sono modifiche da accantonare.", "provide stash message": "Specificare un messaggio di accantonamento (facoltativo)", diff --git a/i18n/ita/extensions/git/package.i18n.json b/i18n/ita/extensions/git/package.i18n.json index 9e6cd77fdcb..5d58b8449e0 100644 --- a/i18n/ita/extensions/git/package.i18n.json +++ b/i18n/ita/extensions/git/package.i18n.json @@ -54,12 +54,12 @@ "command.stashPopLatest": "Preleva accantonamento più recente", "config.enabled": "Indica se GIT è abilitato", "config.path": "Percorso dell'eseguibile di GIT", + "config.autoRepositoryDetection": "Se i repository devono essere rilevati automaticamente", "config.autorefresh": "Indica se l'aggiornamento automatico è abilitato", "config.autofetch": "Indica se il recupero automatico è abilitato", "config.enableLongCommitWarning": "Indica se visualizzare un avviso in caso di messaggi di commit lunghi", "config.confirmSync": "Conferma prima di sincronizzare i repository GIT", "config.countBadge": "Controlla il contatore delle notifiche git. Con `all` vengono conteggiate tutte le modifiche. Con `tracked` vengono conteggiate solo le revisioni. Con `off` il contatore è disattivato.", - "config.checkoutType": "Controlla il tipo di branch mostrati eseguendo il comando `Checkout in...`. `all` mostra tutti i refs, `local` mostra solamente i branch locali, `tags` mostra solamente i tag e `remote` mostra solamente i branch remoti.", "config.ignoreLegacyWarning": "Ignora l'avvertimento legacy di Git", "config.ignoreMissingGitWarning": "Ignora il messaggio di avviso quando manca Git", "config.ignoreLimitWarning": "Ignora il messaggio di avviso quando ci sono troppi cambiamenti in un repository", diff --git a/i18n/ita/extensions/typescript/out/commands.i18n.json b/i18n/ita/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..e771e7a4a9e --- /dev/null +++ b/i18n/ita/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Aprire una cartella in Visual Studio Code per usare un progetto TypeScript o JavaScript", + "typescript.projectConfigUnsupportedFile": "Non è stato possibile determinare il progetto TypeScript o JavaScript. Il tipo di file non è supportato", + "typescript.projectConfigCouldNotGetInfo": "Non è stato possibile determinare il progetto TypeScript o JavaScript", + "typescript.noTypeScriptProjectConfig": "Il file non fa parte di un progetto TypeScript", + "typescript.noJavaScriptProjectConfig": "Il file non fa parte di un progetto JavaScript", + "typescript.configureTsconfigQuickPick": "Configura tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configura jsconfig.json", + "typescript.projectConfigLearnMore": "Altre informazioni" +} \ No newline at end of file diff --git a/i18n/ita/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/ita/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/ita/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/ita/src/vs/base/browser/ui/resourceviewer/resourceViewer.i18n.json b/i18n/ita/src/vs/base/browser/ui/resourceviewer/resourceViewer.i18n.json index 6e295ef1e2c..8baf1308a26 100644 --- a/i18n/ita/src/vs/base/browser/ui/resourceviewer/resourceViewer.i18n.json +++ b/i18n/ita/src/vs/base/browser/ui/resourceviewer/resourceViewer.i18n.json @@ -6,7 +6,7 @@ { "imgMeta": "{0}x{1} {2}", "largeImageError": "L'immagine è troppo grande per essere visualizzata nell'editor", - "resourceOpenExternalButton": "Aprire immagine utilizzando un programma esterno?", + "resourceOpenExternalButton": "Aprire l'immagine utilizzando un programma esterno?", "nativeBinaryError": "Il file non verrà visualizzato nell'editor perché è binario, è molto grande o usa una codifica testo non supportata.", "sizeB": "{0} B", "sizeKB": "{0} KB", diff --git a/i18n/ita/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/ita/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/ita/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/base/node/ps.i18n.json b/i18n/ita/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..9b7eb442bac --- /dev/null +++ b/i18n/ita/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Raccolta informazioni su CPU e memoria in corso. Potrebbe impiegare qualche secondo." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json index 99d10858e07..d740e2e557d 100644 --- a/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/ita/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "I numeri di riga vengono visualizzati come numeri assoluti.", "lineNumbers.relative": "I numeri di riga vengono visualizzati come distanza in linee alla posizione del cursore.", "lineNumbers.interval": "I numeri di riga vengono visualizzati ogni 10 righe.", - "lineNumbers": "Controlla la visualizzazione dei numeri di riga. I valori possibili sono 'on', 'off' e 'relativi'.", + "lineNumbers": "Controlla la visualizzazione dei numeri di riga. I valori possibili sono 'on', 'off', 'relativi' ed 'intervallo'.", "rulers": "Mostra righelli verticali dopo un certo numero di caratteri a spaziatura fissa. Utilizza più valori per più righelli. Nessun righello viene disegnati se la matrice è vuota", "wordSeparators": "Caratteri che verranno usati come separatori di parola quando si eseguono operazioni o spostamenti correlati a parole", "tabSize": "Il numero di spazi corrispondenti ad un carattere Tab. Questa impostazione viene sottoposta a override in base al contenuto dei file quando 'editor.detectIndentation' è 'on'.", @@ -40,9 +40,6 @@ "wordWrapColumn": "Controlla la colonna di wrapping dell'editor quando il valore di `editor.wordWrap` è 'wordWrapColumn' o 'bounded'.", "wrappingIndent": "Controlla il rientro delle righe con ritorno a capo. Può essere uno dei valori seguenti: 'none', 'same' o 'indent'.", "mouseWheelScrollSensitivity": "Moltiplicatore da usare sui valori `deltaX` e `deltaY` degli eventi di scorrimento della rotellina del mouse", - "multiCursorModifier.ctrlCmd": "Rappresenta il tasto 'Control' (ctrl) su Windows e Linux e il tasto 'Comando' (cmd) su OSX.", - "multiCursorModifier.alt": "Rappresenta il tasto 'Alt' su Windows e Linux e il tasto 'Opzione' su OSX.", - "multiCursorModifier": "Il modificatore da utilizzare per aggiungere molteplici cursori con il mouse. 'ctrlCmd' rappresenta il tasto 'Control' su Windows e Linux e il tasto 'Comando' su OSX. I gesti del mouse Vai a definizione e Apri il Link si adatteranno in modo da non entrare in conflitto con il modificatore multi-cursore.", "quickSuggestions.strings": "Abilita i suggerimenti rapidi all'interno di stringhe.", "quickSuggestions.comments": "Abilita i suggerimenti rapidi all'interno di commenti.", "quickSuggestions.other": "Abilita i suggerimenti rapidi all'esterno di stringhe e commenti.", @@ -72,6 +69,7 @@ "cursorBlinking": "Controlla lo stile di animazione del cursore. I valori possibili sono: 'blink', 'smooth', 'phase', 'expand' e 'solid'", "mouseWheelZoom": "Ingrandisce il carattere dell'editor quando si usa la rotellina del mouse e si tiene premuto CTRL", "cursorStyle": "Controlla lo stile del cursore. I valori accettati sono 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'", + "lineCursorWidth": "Controlla la larghezza del cursore quando editor.cursorSyle è impostato a 'line'", "fontLigatures": "Abilita i caratteri legatura", "hideCursorInOverviewRuler": "Controlla se il cursore deve essere nascosto nel righello delle annotazioni.", "renderWhitespace": "Consente di controllare in che modo l'editor deve eseguire il rendering dei caratteri di spazio vuoto. Le opzioni possibili sono: 'none', 'boundary' e 'all'. Con l'opzione 'boundary' non viene eseguito il rendering di singoli spazi tra le parole.", diff --git a/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json index bd8958bdf97..57a55fb4bfd 100644 --- a/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/ita/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "Colore di sfondo per l'evidenziazione della riga alla posizione del cursore.", "lineHighlightBorderBox": "Colore di sfondo per il bordo intorno alla riga alla posizione del cursore.", - "rangeHighlight": "Colore di sfondo degli intervalli evidenziati, ad esempio dalle funzionalità Quick Open e Trova.", + "rangeHighlight": "Colore di sfondo degli intervalli evidenziati, ad esempio dalle funzionalità Quick Open e Trova. il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "caret": "Colore del cursore dell'editor.", "editorCursorBackground": "Colore di sfondo del cursore editor. Permette di personalizzare il colore di un carattere quando sovrapposto da un blocco cursore.", "editorWhitespaces": "Colore dei caratteri di spazio vuoto nell'editor.", diff --git a/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 2d24c4f96ea..5fb4bad149e 100644 --- a/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Vai a errore o avviso successivo", - "markerAction.previous.label": "Vai a errore o avviso precedente", + "markerAction.next.label": "Vai al problema successivo (Errore, Avviso, Informazioni)", + "markerAction.previous.label": "Vai al problema precedente (Errore, Avviso, Info)", "editorMarkerNavigationError": "Colore per gli errori del widget di spostamento tra marcatori dell'editor.", "editorMarkerNavigationWarning": "Colore per gli avvisi del widget di spostamento tra marcatori dell'editor.", "editorMarkerNavigationInfo": "Colore delle informazioni del widget di navigazione marcatori dell'editor.", diff --git a/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index d57627a559a..b8a49a5af0b 100644 --- a/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/ita/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Colore di sfondo di un simbolo durante l'accesso in lettura, ad esempio durante la lettura di una variabile.", - "wordHighlightStrong": "Colore di sfondo di un simbolo durante l'accesso in scrittura, ad esempio durante la scrittura in una variabile.", + "wordHighlight": "Colore di sfondo di un simbolo durante l'accesso in lettura, ad esempio durante la lettura di una variabile. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "wordHighlightStrong": "Colore di sfondo di un simbolo durante l'accesso in scrittura, per esempio durante la scrittura di una variabile. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "overviewRulerWordHighlightForeground": "Colore del marcatore del righello delle annotazioni per le evidenziazioni dei simboli.", "overviewRulerWordHighlightStrongForeground": "Colore del marcatore del righello delle annotazioni per le evidenziazioni dei simboli di accesso in scrittura.", "wordHighlight.next.label": "Vai al prossimo simbolo evidenziato", diff --git a/i18n/ita/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/ita/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 32a58ae4a61..f8e28e396b6 100644 --- a/i18n/ita/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/ita/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}` non è un identificatore di menu valido", "missing.command": "La voce di menu fa riferimento a un comando `{0}` che non è definito nella sezione 'commands'.", "missing.altCommand": "La voce di menu fa riferimento a un comando alternativo `{0}` che non è definito nella sezione 'commands'.", - "dupe.command": "La voce di menu fa riferimento allo stesso comando come comando predefinito e come comando alternativo", - "nosupport.altCommand": "I comandi alternativi sono attualmente supportati solo nel gruppo 'navigation' del menu 'editor/title'" + "dupe.command": "La voce di menu fa riferimento allo stesso comando come comando predefinito e come comando alternativo" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/environment/node/argv.i18n.json b/i18n/ita/src/vs/platform/environment/node/argv.i18n.json index 194dc9d937c..9dd58076c04 100644 --- a/i18n/ita/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/ita/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,35 @@ "diff": "Confronta due file tra loro.", "add": "Aggiunge la cartella o le cartelle all'ultima finestra attiva.", "goto": "Apre un file nel percorso alla posizione specificata di riga e carattere.", - "locale": "Impostazioni locali da usare, ad esempio en-US o it-IT.", "newWindow": "Forza una nuova istanza di Code.", - "performance": "Eseguire l'avvio con il comando 'Developer: Startup Performance' abilitato.", - "prof-startup": "Esegui il profiler della CPU durante l'avvio", - "inspect-extensions": "Consentire il debug e profiling delle estensioni. Controllare gli strumenti di sviluppo per l'uri di connessione.", - "inspect-brk-extensions": "Consentire il debug e profiling delle estensioni con l'host di estensione in pausa dopo inizio. Controllare gli strumenti di sviluppo per l'uri di connessione.", "reuseWindow": "Forza l'apertura di un file o di una cartella nell'ultima finestra attiva.", - "userDataDir": "Consente di specificare la directory in cui si trovano i dati utente. Utile quando viene eseguito come root.", - "log": "Livello di logging da utilizzare. Il valore predefinito è 'info'. I valori consentiti sono 'critical, 'error', 'warn', 'info', 'debug', 'trace', 'off'.", - "verbose": "Visualizza l'output dettagliato (implica --wait).", "wait": "Attendere la chiusura dei file prima della restituzione.", + "locale": "Impostazioni locali da usare, ad esempio en-US o it-IT.", + "userDataDir": "Consente di specificare la directory in cui si trovano i dati utente. Utile quando viene eseguito come root.", + "version": "Visualizza la versione.", + "help": "Visualizza la sintassi.", "extensionHomePath": "Impostare il percorso radice per le estensioni.", "listExtensions": "Elenca le estensioni installate.", "showVersions": "Mostra le versioni delle estensioni installate, quando si usa --list-extension.", "installExtension": "Installa un'estensione.", "uninstallExtension": "Disinstalla un'estensione.", "experimentalApis": "Abilita funzionalità di API proposte per un'estensione specifica.", - "disableExtensions": "Disabilita tutte le estensioni installate.", - "disableGPU": "Disabilita l'accelerazione hardware della GPU.", + "verbose": "Visualizza l'output dettagliato (implica --wait).", + "log": "Livello di logging da utilizzare. Il valore predefinito è 'info'. I valori consentiti sono 'critical, 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Stampare le informazioni di utilizzo e diagnostica di processo.", - "version": "Visualizza la versione.", - "help": "Visualizza la sintassi.", + "performance": "Eseguire l'avvio con il comando 'Developer: Startup Performance' abilitato.", + "prof-startup": "Esegui il profiler della CPU durante l'avvio", + "disableExtensions": "Disabilita tutte le estensioni installate.", + "inspect-extensions": "Consentire il debug e profiling delle estensioni. Controllare gli strumenti di sviluppo per l'uri di connessione.", + "inspect-brk-extensions": "Consentire il debug e profiling delle estensioni con l'host di estensione in pausa dopo inizio. Controllare gli strumenti di sviluppo per l'uri di connessione.", + "disableGPU": "Disabilita l'accelerazione hardware della GPU.", + "uploadLogs": "Caricamento dei log della sessione corrente verso un punto di comunicazione sicuro.", "usage": "Utilizzo", "options": "opzioni", "paths": "percorsi", - "optionsUpperCase": "Opzioni" + "stdinWindows": "Per leggere l'output da un altro programma, aggiungere alla fine '-' (ad esempio 'echo Hello World | {0} -')", + "stdinUnix": "Per leggere da stdin, aggiungere alla fine '-' (ad esempio 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Opzioni", + "extensionsManagement": "Gestione delle estensioni", + "troubleshooting": "Risoluzione dei problemi" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index f8230336461..973c52b94e0 100644 --- a/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/ita/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Estensione non valida: package.json non è un file JSON.", - "restartCodeLocal": "Riavviare Code prima di reinstallare {0}.", + "restartCode": "Riavviare Code prima di reinstallare {0}.", "installingOutdatedExtension": "Una versione più recente di questa estensione è già installata. Vuoi eseguire l'override di questa con la versione precedente?", "override": "Eseguire l'override", "cancel": "Annulla", - "notFoundCompatible": "Impossibile installare perché non è stata trovata l'estensione '{0}' compatibile con la versione corrente '{1}' di VS Code.", - "quitCode": "Impossibile installare perché un'istanza obsoleta dell'estensione è ancora in esecuzione. Si prega di uscire e riavviare VS Code prima di reinstallare.", - "exitCode": "Impossibile installare perché un'istanza obsoleta dell'estensione è ancora in esecuzione. Si prega di uscire e riavviare VS Code prima di reinstallare.", + "errorInstallingDependencies": "Errore durante l'installazione delle dipendenze. {0}", + "notFoundCompatible": "Impossibile installare '{0}'; non è presente alcuna versione compatibile con VS Code '{1}'.", "notFoundCompatibleDependency": "Impossibile installare perché non è stata trovata l'estensione dipendente '{0}' compatibile con la versione corrente '{1}' di VS Code.", + "quitCode": "Impossibile installare l'estensione. Riavviare VS Code prima di procedere ad un nuovo setup.", + "exitCode": "Impossibile installare l'estensione. Riavviare VS Code prima di procedere ad un nuovo setup.", "uninstallDependeciesConfirmation": "Disinstallare solo '{0}' o anche le relative dipendenze?", "uninstallOnly": "Solo", "uninstallAll": "Tutto", diff --git a/i18n/ita/src/vs/platform/list/browser/listService.i18n.json b/i18n/ita/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..1866903b33e --- /dev/null +++ b/i18n/ita/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Area di lavoro" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/message/common/message.i18n.json b/i18n/ita/src/vs/platform/message/common/message.i18n.json index c623cd2a9bb..2822182506c 100644 --- a/i18n/ita/src/vs/platform/message/common/message.i18n.json +++ b/i18n/ita/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Chiudi", "later": "In seguito", - "cancel": "Annulla" + "cancel": "Annulla", + "moreFile": "...1 altro file non visualizzato", + "moreFiles": "...{0} altri file non visualizzati" } \ No newline at end of file diff --git a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json index 6505e976a25..28433311cf7 100644 --- a/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ita/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "Colore bordo dei widget dell'editor. Il colore viene utilizzato solo se il widget sceglie di avere un bordo e se il colore non è sottoposto a override da un widget.", "editorSelectionBackground": "Colore della selezione dell'editor.", "editorSelectionForeground": "Colore del testo selezionato per il contrasto elevato.", - "editorInactiveSelection": "Colore della selezione in un editor inattivo.", - "editorSelectionHighlight": "Colore delle aree con lo stesso contenuto della selezione.", + "editorInactiveSelection": "Colore della selezione in un editor non attivo. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "editorSelectionHighlight": "Colore delle aree con lo stesso contenuto della selezione. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "editorFindMatch": "Colore della corrispondenza di ricerca corrente.", - "findMatchHighlight": "Colore delle altre corrispondenze di ricerca.", - "findRangeHighlight": "Colore dell'intervallo di ricerca.", - "hoverHighlight": "Evidenziazione sotto la parola per cui è visualizzata un'area sensibile al passaggio del mouse.", + "findMatchHighlight": "Colore degli altri risultati della ricerca. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "findRangeHighlight": "Colore dell'intervallo limite della ricerca. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "hoverHighlight": "Evidenziazione sotto la parola per cui è visualizzata un'area sensibile al passaggio del mouse. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "hoverBackground": "Colore di sfondo dell'area sensibile al passaggio del mouse dell'editor.", "hoverBorder": "Colore del bordo dell'area sensibile al passaggio del mouse dell'editor.", "activeLinkForeground": "Colore dei collegamenti attivi.", @@ -76,12 +76,12 @@ "diffEditorRemoved": "Colore di sfondo del testo che è stato rimosso.", "diffEditorInsertedOutline": "Colore del contorno del testo che è stato inserito.", "diffEditorRemovedOutline": "Colore del contorno del testo che è stato rimosso.", - "mergeCurrentHeaderBackground": "Sfondo intestazione corrente in conflitti di merge in linea.", - "mergeCurrentContentBackground": "Sfondo contenuto corrente in conflitti di merge in linea.", - "mergeIncomingHeaderBackground": "Sfondo intestazione modifica in ingresso in conflitti di merge in linea.", - "mergeIncomingContentBackground": "Sfondo contenuto modifica in ingresso in conflitti di merge in linea.", - "mergeCommonHeaderBackground": "Sfondo dell'intestazione dell'antenato comune nei conflitti di merge in linea.", - "mergeCommonContentBackground": "Sfondo del contenuto dell'antenato comune nei conflitti di merge in linea.", + "mergeCurrentHeaderBackground": "Sfondo intestazione corrente in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeCurrentContentBackground": "Sfondo contenuto corrente in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeIncomingHeaderBackground": "Sfondo intestazione modifica in ingresso in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeIncomingContentBackground": "Sfondo contenuto modifica in ingresso in conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeCommonHeaderBackground": "Sfondo dell'intestazione dell'antenato comune nei conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", + "mergeCommonContentBackground": "Sfondo del contenuto dell'antenato comune nei conflitti di merge in linea. Il colore non deve essere opaco per evitare di nascondere le decorazioni sottostanti.", "mergeBorder": "Colore bordo su intestazioni e sulla barra di divisione di conflitti di merge in linea.", "overviewRulerCurrentContentForeground": "Colore primo piano righello panoramica attuale per i conflitti di merge in linea.", "overviewRulerIncomingContentForeground": "Colore primo piano del righello panoramica modifiche in arrivo per i conflitti di merge in linea.", diff --git a/i18n/ita/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/ita/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..c6ca6920d97 --- /dev/null +++ b/i18n/ita/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "la proprietà `{0}` è obbligatoria e deve essere di tipo `string`", + "optstring": "la proprietà `{0}` può essere omessa o deve essere di tipo `string`" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..4bc65098ea9 --- /dev/null +++ b/i18n/ita/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Esecuzione del salvataggio partecipanti..." +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/ita/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 04c4b11db8c..aac2c8ae46e 100644 --- a/i18n/ita/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/ita/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -4,7 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "treeView.notRegistered": "Nessuna visualizzazione di struttura ad albero con ID '{0}' registrata.", - "treeItem.notFound": "Nessun elemento di struttura ad albero con id '{0}' trovato.", - "treeView.duplicateElement": "L'elemento {0} è già registrato" + "treeView.notRegistered": "Nessuna visualizzazione di struttura ad albero con ID '{0}' registrata." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/ita/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 4f3f7993c31..e851ba0b17e 100644 --- a/i18n/ita/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Attiva/Disattiva posizione della barra laterale", "view": "Visualizza" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 0a58dca9eaa..b30eb5b862d 100644 --- a/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Apri file...", "openFolder": "Apri cartella...", "openFileFolder": "Apri...", - "addFolderToWorkspace": "Aggiungi cartella all'area di lavoro...", - "add": "&&Aggiungi", - "addFolderToWorkspaceTitle": "Aggiungi cartella all'area di lavoro", "globalRemoveFolderFromWorkspace": "Rimuovi cartella dall'area di lavoro...", - "removeFolderFromWorkspace": "Rimuovi cartella dall'area di lavoro", - "openFolderSettings": "Apri impostazioni cartella", "saveWorkspaceAsAction": "Salva area di lavoro come...", "save": "&&Salva", "saveWorkspace": "Salva area di lavoro", "openWorkspaceAction": "Apri area di lavoro...", "openWorkspaceConfigFile": "Apri file di configurazione dell'area di lavoro", - "openFolderAsWorkspaceInNewWindow": "Apre la cartella come area di lavoro in una nuova finestra", - "workspaceFolderPickerPlaceholder": "Selezionare la cartella dell'area di lavoro" + "openFolderAsWorkspaceInNewWindow": "Apre la cartella come area di lavoro in una nuova finestra" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/ita/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..e07a448e23d --- /dev/null +++ b/i18n/ita/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Aggiungi cartella all'area di lavoro...", + "add": "&&Aggiungi", + "addFolderToWorkspaceTitle": "Aggiungi cartella all'area di lavoro" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index aa914d12c1d..8430880ec80 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,17 @@ "groupThreePicker": "Mostra editor nel terzo gruppo", "allEditorsPicker": "Mostra tutti gli editor aperti", "view": "Visualizza", - "file": "File" + "file": "File", + "close": "Chiudi", + "closeOthers": "Chiudi altri", + "closeRight": "Chiudi a destra", + "closeAllUnmodified": "Chiudi non modificati", + "closeAll": "Chiudi tutto", + "keepOpen": "Mantieni aperto", + "showOpenedEditors": "Mostra editor aperti", + "keepEditor": "Mantieni editor", + "closeEditorsInGroup": "Chiudi tutti gli editor del gruppo", + "closeUnmodifiedEditors": "Chiudi editor non modificati del gruppo", + "closeOtherEditors": "Chiudi gli altri editor", + "closeRightEditors": "Chiudi editor a destra" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 00de0aab7d6..5ff06b5baf6 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Chiudi editor", "revertAndCloseActiveEditor": "Ripristina e chiudi editor", "closeEditorsToTheLeft": "Chiudi editor a sinistra", - "closeEditorsToTheRight": "Chiudi editor a destra", "closeAllEditors": "Chiudi tutti gli editor", - "closeUnmodifiedEditors": "Chiudi editor non modificati del gruppo", "closeEditorsInOtherGroups": "Chiudi editor in altri gruppi", - "closeOtherEditorsInGroup": "Chiudi gli altri editor", - "closeEditorsInGroup": "Chiudi tutti gli editor del gruppo", "moveActiveGroupLeft": "Sposta gruppo di editor a sinistra", "moveActiveGroupRight": "Sposta gruppo di editor a destra", "minimizeOtherEditorGroups": "Riduci a icona gli altri gruppi di editor", "evenEditorGroups": "Imposta stessa larghezza per gruppo di editor", "maximizeEditor": "Ingrandisci gruppo di editor e nascondi barra laterale", - "keepEditor": "Mantieni editor", "openNextEditor": "Apri editor successivo", "openPreviousEditor": "Apri editor precedente", "nextEditorInGroup": "Apri editor successivo del gruppo", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Mostra editor nel primo gruppo", "showEditorsInSecondGroup": "Mostra editor nel secondo gruppo", "showEditorsInThirdGroup": "Mostra editor nel terzo gruppo", - "showEditorsInGroup": "Mostra editor nel gruppo", "showAllEditors": "Mostra tutti gli editor", "openPreviousRecentlyUsedEditorInGroup": "Apri editor precedente usato di recente nel gruppo", "openNextRecentlyUsedEditorInGroup": "Apri editor successivo usato di recente nel gruppo", diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 0e49511fa54..023619e8620 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Consente di spostare l'editor attivo per schede o gruppi", "editorCommand.activeEditorMove.arg.name": "Argomento per spostamento editor attivo", - "editorCommand.activeEditorMove.arg.description": "Proprietà degli argomenti:\n\t* 'to': valore stringa che specifica dove eseguire lo spostamento.\n\t* 'by': valore stringa che specifica l'unità per lo spostamento, ovvero per scheda o per gruppo.\n\t* 'value': valore numerico che specifica il numero di posizioni o una posizione assoluta per lo spostamento.", - "commandDeprecated": "Il comando **{0}** è stato rimosso. In alternativa, usare **{1}**", - "openKeybindings": "Configura tasti di scelta rapida" + "editorCommand.activeEditorMove.arg.description": "Proprietà degli argomenti:\n\t* 'to': valore stringa che specifica dove eseguire lo spostamento.\n\t* 'by': valore stringa che specifica l'unità per lo spostamento, ovvero per scheda o per gruppo.\n\t* 'value': valore numerico che specifica il numero di posizioni o una posizione assoluta per lo spostamento." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 1efc298b02c..4476182db18 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -10,7 +10,5 @@ "editableEditorWithInputAriaLabel": "{0}. Editor di confronto file di testo", "editableEditorAriaLabel": "Editor di confronto file di testo.", "navigate.next.label": "Revisione successiva", - "navigate.prev.label": "Revisione precedente", - "inlineDiffLabel": "Passa alla visualizzazione inline", - "sideBySideDiffLabel": "Passa alla visualizzazione affiancata" + "navigate.prev.label": "Revisione precedente" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index db72fb32688..12d1b76075f 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Chiudi", - "closeOthers": "Chiudi altri", - "closeRight": "Chiudi a destra", - "closeAll": "Chiudi tutto", - "closeAllUnmodified": "Chiudi non modificati", - "keepOpen": "Mantieni aperto", - "showOpenedEditors": "Mostra editor aperti", "araLabelEditorActions": "Azioni editor" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 5a69f46955d..d4f0af0c2c3 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Non supportata]", + "userIsAdmin": "[Amministratore]", + "userIsSudo": "[Superutente]", "devExtensionWindowTitlePrefix": "[Host di sviluppo estensione]" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/ita/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index f5ecae5746b..8b6ad71cd4e 100644 --- a/i18n/ita/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/ita/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -3,6 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. -{ - "hideView": "Nascondi da barra laterale" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/common/theme.i18n.json b/i18n/ita/src/vs/workbench/common/theme.i18n.json index c2344ccce6a..fb8298647d6 100644 --- a/i18n/ita/src/vs/workbench/common/theme.i18n.json +++ b/i18n/ita/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "Colore di sfondo delle schede attive. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabInactiveBackground": "Colore di sfondo delle schede inattive. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", + "tabHoverBackground": "Colore di sfondo al passaggio del mouse sulle schede. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", + "tabUnfocusedHoverBackground": "Colore di sfondo al passaggio del mouse sulle schede in un gruppo non attivo. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabBorder": "Bordo per separare le schede l'una dall'altra. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabActiveBorder": "Bordo per evidenziare le schede attive. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabActiveUnfocusedBorder": "Bordo per evidenziare le schede attive in un gruppo con stato non attivo. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", + "tabHoverBorder": "Bordo da utilizzare per evidenziare la scheda al passaggio del mouse. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", + "tabUnfocusedHoverBorder": "Bordo da utilizzare per evidenziare la scheda non attiva al passaggio del mouse. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabActiveForeground": "Colore di primo piano delle schede attive in un gruppo attivo. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabInactiveForeground": "Colore di primo piano delle schede inattive in un gruppo attivo. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", "tabUnfocusedActiveForeground": "Colore primo piano delle schede attive in un gruppo con stato non attivo. Le schede sono i contenitori degli editor nell'area degli editor. È possibile aprire più schede in un gruppo di editor e possono esistere più gruppi di editor.", @@ -16,7 +20,7 @@ "editorGroupBackground": "Colore di sfondo di un gruppo di editor. I gruppi di editor sono contenitori di editor. Il colore di sfondo viene visualizzato quando si trascinano i gruppi di editor in un'altra posizione.", "tabsContainerBackground": "Colore di sfondo dell'intestazione del titolo di gruppo di editor, quando le schede sono abilitate. I gruppi di editor sono i contenitori degli editor.", "tabsContainerBorder": "Colore del bordo dell'intestazione del titolo di gruppo di editor, quando le schede sono abilitate. I gruppi di editor sono i contenitori degli editor.", - "editorGroupHeaderBackground": "Colore di sfondo dell'intestazione del titolo dell'editor quando le schede sono disabilitate. I gruppi di editor sono contenitori di editor.", + "editorGroupHeaderBackground": "Colore di sfondo dell'intestazione del titolo dell'editor quando le schede sono disabilitate (`\"workbench.editor.showTabs\": false`). I gruppi di editor sono contenitori di editor.", "editorGroupBorder": "Colore per separare più gruppi di editor l'uno dall'altro. I gruppi di editor sono i contenitori degli editor.", "editorDragAndDropBackground": "Colore di sfondo quando si trascinano gli editor. Il colore dovrebbe avere una trasparenza impostata in modo che il contenuto dell'editor sia ancora visibile.", "panelBackground": "Colore di sfondo dei pannelli. I pannelli sono visualizzati sotto l'area degli editor e contengono visualizzazioni quali quella di output e del terminale integrato.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "Colore del bordo della barra di stato che la separa dalla barra laterale e dall'editor quando non ci sono cartelle aperte. La barra di stato è visualizzata nella parte inferiore della finestra.", "statusBarItemActiveBackground": "Colore di sfondo degli elementi della barra di stato quando si fa clic. La barra di stato è visualizzata nella parte inferiore della finestra.", "statusBarItemHoverBackground": "Colore di sfondo degli elementi della barra di stato al passaggio del mouse. La barra di stato è visualizzata nella parte inferiore della finestra.", - "statusBarProminentItemBackground": "Colore di sfondo degli elementi rilevanti della barra di stato. Gli elementi rilevanti spiccano rispetto ad altre voci della barra di stato. La barra di stato è visualizzata nella parte inferiore della finestra.", - "statusBarProminentItemHoverBackground": "Colore di sfondo degli elementi rilevanti della barra di stato al passaggio del mouse. Gli elementi rilevanti spiccano rispetto ad altre voci della barra di stato. La barra di stato è visualizzata nella parte inferiore della finestra.", + "statusBarProminentItemBackground": "Colore di sfondo degli elementi rilevanti della barra di stato. Gli elementi rilevanti spiccano rispetto ad altre voci della barra di stato. Per vedere un esempio, cambiare la modalità `Toggle Tab Key Moves Focus` nella barra dei comandi. La barra di stato è visualizzata nella parte inferiore della finestra.", + "statusBarProminentItemHoverBackground": "Colore di sfondo degli elementi rilevanti della barra di stato al passaggio del mouse. Gli elementi rilevanti spiccano rispetto ad altre voci della barra di stato. Per vedere un esempio, cambiare la modalità `Toggle Tab Key Moves Focus` nella barra dei comandi. La barra di stato è visualizzata nella parte inferiore della finestra.", "activityBarBackground": "Colore di sfondo della barra attività. La barra attività viene visualizzata nella parte inferiore sinistra/destra e consente il passaggio tra diverse visualizzazioni della barra laterale", "activityBarForeground": "Colore primo piano della barra attività (ad es. quello utilizzato per le icone). La barra attività viene mostrata all'estrema sinistra o destra e permette di alternare le visualizzazioni della barra laterale.", "activityBarBorder": "Colore del bordo della barra attività che la separa dalla barra laterale. La barra di attività viene mostrata all'estrema sinistra o destra e permette di alternare le visualizzazioni della barra laterale.", diff --git a/i18n/ita/src/vs/workbench/common/views.i18n.json b/i18n/ita/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..ed1c7bde950 --- /dev/null +++ b/i18n/ita/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Nel percorso `{1}` è già registrata una visualizzazione con ID `{0}` " +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json index ac85b55822e..9ae1266d1f0 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Chiudi editor", "closeWindow": "Chiudi finestra", "closeWorkspace": "Chiudi area di lavoro", "noWorkspaceOpened": "In questa istanza non ci sono attualmente aree di lavoro aperte da chiudere.", @@ -52,21 +51,5 @@ "displayLanguage": "Definisce la lingua visualizzata di VSCode.", "doc": "Per un elenco delle lingue supportate, vedere {0}.", "restart": "Se si modifica il valore, è necessario riavviare VSCode.", - "fail.createSettings": "Non è possibile creare '{0}' ({1}).", - "openLogsFolder": "Apri cartella dei log", - "showLogs": "Mostra log...", - "mainProcess": "Principale", - "sharedProcess": "Condiviso", - "rendererProcess": "Renderer", - "extensionHost": "Host dell'estensione", - "selectProcess": "Seleziona il processo", - "setLogLevel": "Imposta livello log", - "trace": "Analisi", - "debug": "Debug", - "info": "Informazioni", - "warn": "Avviso", - "err": "Errore", - "critical": "Errori critici", - "off": "Disattivato", - "selectLogLevel": "Seleziona il livello log" + "fail.createSettings": "Non è possibile creare '{0}' ({1})." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json index 14e407b8a5d..103d383af16 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Visualizza", "help": "Guida", "file": "File", - "developer": "Sviluppatore", "workspaces": "Aree di lavoro", + "developer": "Sviluppatore", + "workbenchConfigurationTitle": "Area di lavoro", "showEditorTabs": "Controlla se visualizzare o meno gli editor aperti in schede.", "workbench.editor.labelFormat.default": "Visualizza il nome del file. Quando le schede sono abilitate e due file hanno lo stesso nome in un unico gruppo, vengono aggiunte le sezioni distintive del percorso di ciascun file. Quando le schede sono disabilitate, se l'editor è attivo, viene visualizzato il percorso relativo alla radice dell'area di lavoro.", "workbench.editor.labelFormat.short": "Visualizza il nome del file seguito dal relativo nome di directory.", @@ -20,8 +21,10 @@ "showIcons": "Controlla se visualizzare o meno un'icona per gli editor aperti. Richiede l'abilitazione anche di un tema dell'icona.", "enablePreview": "Controlla se gli editor aperti vengono visualizzati come anteprima. Le anteprime editor vengono riutilizzate finché vengono mantenute (ad esempio tramite doppio clic o modifica) e vengono visualizzate in corsivo.", "enablePreviewFromQuickOpen": "Controlla se gli editor aperti da Quick Open vengono visualizzati come anteprima. Le anteprime editor vengono riutilizzate finché vengono mantenute, ad esempio tramite doppio clic o modifica.", + "closeOnFileDelete": "Controlla se gli editor che visualizzano un file devono chiudersi automaticamente quando il file viene eliminato o rinominato da un altro processo. Se si disabilita questa opzione, in una simile circostanza l'editor verrà aperto e i file risulteranno modificati ma non salvati. Nota: se si elimina il file dall'interno dell'applicazione, l'editor verrà sempre chiuso e i file modificati ma non salvati non verranno mai chiusi allo scopo di salvaguardare i dati.", "editorOpenPositioning": "Controlla la posizione in cui vengono aperti gli editor. Selezionare 'sinistra' o 'destra' per aprire gli editor a sinistra o a destra di quello attualmente attivo. Selezionare 'primo' o 'ultimo' per aprire gli editor indipendentemente da quello attualmente attivo.", "revealIfOpen": "Controlla se un editor viene visualizzato in uno qualsiasi dei gruppi visibili se viene aperto. Se l'opzione è disabilitata, un editor verrà aperto preferibilmente nel gruppo di editor attualmente attivo. Se è abilitata, un editor già aperto verrà visualizzato e non aperto di nuovo nel gruppo di editor attualmente attivo. Nota: in alcuni casi questa impostazione viene ignorata, ad esempio quando si forza l'apertura di un editor in un gruppo specifico oppure a lato del gruppo attualmente attivo.", + "swipeToNavigate": "Scorrere orizzontalmente con tre dita per spostarsi tra i file aperti.", "commandHistory": "Controlla il numero di comandi utilizzati di recente da mantenere nella cronologia. Impostare a 0 per disabilitare la cronologia dei comandi.", "preserveInput": "Controlla se l'ultimo input digitato nel riquadro comandi deve essere ripristinato alla successiva riapertura del riquadro.", "closeOnFocusLost": "Controlla se Quick Open deve essere chiuso automaticamente quando perde lo stato attivo.", @@ -29,14 +32,11 @@ "sideBarLocation": "Controlla la posizione della barra laterale. Può essere visualizzata a sinistra o a destra del workbench.", "statusBarVisibility": "Controlla la visibilità della barra di stato nella parte inferiore del workbench.", "activityBarVisibility": "Controlla la visibilità della barra attività nel workbench.", - "closeOnFileDelete": "Controlla se gli editor che visualizzano un file devono chiudersi automaticamente quando il file viene eliminato o rinominato da un altro processo. Se si disabilita questa opzione, in una simile circostanza l'editor verrà aperto e i file risulteranno modificati ma non salvati. Nota: se si elimina il file dall'interno dell'applicazione, l'editor verrà sempre chiuso e i file modificati ma non salvati non verranno mai chiusi allo scopo di salvaguardare i dati.", - "enableNaturalLanguageSettingsSearch": "Controlla se abilitare la modalità di ricerca in linguaggio naturale per le impostazioni.", "fontAliasing": "Controlla il metodo di aliasing dei caratteri nell'area di lavoro.\n- impostazione predefinita: anti-aliasing dei caratteri a livello di sub-pixel. Nella maggior parte delle visualizzazioni non retina consentirà di ottenere un testo con il massimo contrasto.\n- anti-aliasing: anti-aliasing dei caratteri a livello di pixel, invece che a livello di sub-pixel. Consente di visualizzare i caratteri più chiari.\n- nessuno: disabilita l'anti-aliasing dei caratteri. Il testo verrà visualizzato con contorni irregolari.", "workbench.fontAliasing.default": "Anti-aliasing dei caratteri a livello di sub-pixel. Nella maggior parte delle visualizzazioni non retina consentirà di ottenere un testo con il massimo contrasto.", "workbench.fontAliasing.antialiased": "Anti-aliasing dei caratteri a livello di pixel, invece che a livello di sub-pixel. Consente di visualizzare i caratteri più chiari.", "workbench.fontAliasing.none": "Disabilita l'anti-aliasing dei caratteri. Il testo verrà visualizzato con contorni irregolari. ", - "swipeToNavigate": "Scorrere orizzontalmente con tre dita per spostarsi tra i file aperti.", - "workbenchConfigurationTitle": "Area di lavoro", + "enableNaturalLanguageSettingsSearch": "Controlla se abilitare la modalità di ricerca in linguaggio naturale per le impostazioni.", "windowConfigurationTitle": "Finestra", "window.openFilesInNewWindow.on": "I file verranno aperti in una nuova finestra", "window.openFilesInNewWindow.off": "I file verranno aperti nella finestra con la cartella dei file aperta o nell'ultima finestra attiva", diff --git a/i18n/ita/src/vs/workbench/electron-browser/window.i18n.json b/i18n/ita/src/vs/workbench/electron-browser/window.i18n.json index 8c2277fae11..a589565cc73 100644 --- a/i18n/ita/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/ita/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Taglia", "copy": "Copia", "paste": "Incolla", - "selectAll": "Seleziona tutto" + "selectAll": "Seleziona tutto", + "runningAsRoot": "Non è consigliabile eseguire {0} come utente root." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index 2e0a0d42956..dad36665ecd 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "Colore di sfondo della barra degli strumenti di debug." + "debugToolBarBackground": "Colore di sfondo della barra degli strumenti di debug.", + "debugToolBarBorder": "Colore del bordo della barra degli strumenti di debug." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 7729690837e..250efcc3000 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "Configurazioni dello schema JSON per la convalida di 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Impostazioni specifiche di Windows.", "vscode.extension.contributes.debuggers.windows.runtime": "Runtime usato per Windows.", - "vscode.extension.contributes.debuggers.osx": "Impostazioni specifiche di OS X.", - "vscode.extension.contributes.debuggers.osx.runtime": "Runtime usato per OS X.", "vscode.extension.contributes.debuggers.linux": "Impostazioni specifiche di Linux.", "vscode.extension.contributes.debuggers.linux.runtime": "Runtime usato per Linux.", "vscode.extension.contributes.breakpoints": "Punti di interruzione per contributes.", diff --git a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 7e90f64d82a..94d7c45f7eb 100644 --- a/i18n/ita/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "oggetto del debug", - "debug.terminal.not.available.error": "Il terminale integrato non è disponibile" + "debug.terminal.title": "oggetto del debug" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 1b150a45b5f..5f819964e72 100644 --- a/i18n/ita/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Apri nuovo prompt dei comandi", "globalConsoleActionMacLinux": "Apri nuovo terminale", "scopedConsoleActionWin": "Apri nel prompt dei comandi", - "scopedConsoleActionMacLinux": "Apri nel terminale", - "openFolderInIntegratedTerminal": "Apri nel terminale" + "scopedConsoleActionMacLinux": "Apri nel terminale" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index ec5fd33a3b1..fbdc3b5e322 100644 --- a/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Questa estensione è raccomandata in base ai file aperti di recente.", + "neverShowAgain": "Non visualizzare più questo messaggio", + "close": "Chiudi", "workspaceRecommendation": "Questa estensione è consigliata dagli utenti dell'area di lavoro corrente.", + "fileBasedRecommendation": "Questa estensione è raccomandata in base ai file aperti di recente.", "exeBasedRecommendation": "Questa estensione è consigliata perché avete installato {0}.", "reallyRecommended2": "Per questo tipo di file è consigliabile utilizzare l'estensione '{0}'.", "reallyRecommendedExtensionPack": "Per questo tipo di file è consigliabile usare il pacchetto di estensione '{0}'.", "showRecommendations": "Mostra gli elementi consigliati", "install": "Installa", - "neverShowAgain": "Non visualizzare più questo messaggio", - "close": "Chiudi", "workspaceRecommended": "Per questa area di lavoro sono disponibili estensioni consigliate.", "installAll": "Installa tutto", "ignoreExtensionRecommendations": "Ignorare tutti i suggerimenti per le estensioni?", diff --git a/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..1866903b33e --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Area di lavoro" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 979ee1896bb..a1c5eca5548 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,25 @@ "filesCategory": "File", "revealInSideBar": "Visualizza nella barra laterale", "acceptLocalChanges": "Utilizzare le modifiche e sovrascrivere il contenuto del disco", - "revertLocalChanges": "Annullare le modifiche e tornare al contenuto sul disco" + "revertLocalChanges": "Annullare le modifiche e tornare al contenuto sul disco", + "copyPathOfActive": "Copia percorso del file attivo", + "saveAllInGroup": "Salva tutto nel gruppo", + "saveFiles": "Salva tutti i file", + "revert": "Ripristina file", + "compareActiveWithSaved": "Confronta file attivo con file salvato", + "closeEditor": "Chiudi editor", + "view": "Visualizza", + "openToSide": "Apri lateralmente", + "revealInWindows": "Visualizza in Esplora risorse", + "revealInMac": "Visualizza in Finder", + "openContainer": "Apri cartella superiore", + "copyPath": "Copia percorso", + "saveAll": "Salva tutto", + "compareWithSaved": "Confronta con file salvato", + "compareSource": "Seleziona per il confronto", + "close": "Chiudi", + "closeOthers": "Chiudi altri", + "closeUnmodified": "Chiudi non modificati", + "closeAll": "Chiudi tutto", + "deleteFile": "Elimina definitivamente" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 7d23a38e703..14358d0abb2 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Riprova", - "rename": "Rinomina", "newFile": "Nuovo file", "newFolder": "Nuova cartella", + "rename": "Rinomina", + "delete": "Elimina", + "copyFile": "Copia", + "pasteFile": "Incolla", + "retry": "Riprova", "openFolderFirst": "Aprire prima di tutto una cartella per creare file o cartelle al suo interno.", "newUntitledFile": "Nuovo file senza nome", "createNewFile": "Nuovo file", @@ -28,26 +31,14 @@ "confirmDeleteMessageFile": "Eliminare definitivamente '{0}'?", "irreversible": "Questa azione è irreversibile.", "permDelete": "Elimina definitivamente", - "delete": "Elimina", "importFiles": "Importa file", "confirmOverwrite": "Nella cartella di destinazione esiste già un file o una cartella con lo stesso nome. Sovrascrivere?", "replaceButtonLabel": "&&Sostituisci", - "copyFile": "Copia", - "pasteFile": "Incolla", "duplicateFile": "Duplicato", - "openToSide": "Apri lateralmente", - "compareSource": "Seleziona per il confronto", "globalCompareFile": "Confronta file attivo con...", "openFileToCompare": "Aprire prima un file per confrontarlo con un altro file.", - "compareWith": "Confronta '{0}' con '{1}'", - "compareFiles": "Confronta file", "refresh": "Aggiorna", - "save": "Salva", - "saveAs": "Salva con nome...", - "saveAll": "Salva tutto", "saveAllInGroup": "Salva tutto nel gruppo", - "saveFiles": "Salva tutti i file", - "revert": "Ripristina file", "focusOpenEditors": "Stato attivo su visualizzazione editor aperti", "focusFilesExplorer": "Stato attivo su Esplora file", "showInExplorer": "Visualizza file attivo nella barra laterale", @@ -56,20 +47,11 @@ "refreshExplorer": "Aggiorna Explorer", "openFileInNewWindow": "Apri file attivo in un'altra finestra", "openFileToShowInNewWindow": "Aprire prima un file per visualizzarlo in un'altra finestra", - "revealInWindows": "Visualizza in Esplora risorse", - "revealInMac": "Visualizza in Finder", - "openContainer": "Apri cartella superiore", - "revealActiveFileInWindows": "Visualizza file attivo in Esplora risorse", - "revealActiveFileInMac": "Visualizza file attivo in Finder", - "openActiveFileContainer": "Apri cartella che contiene il file attivo", "copyPath": "Copia percorso", - "copyPathOfActive": "Copia percorso del file attivo", "emptyFileNameError": "È necessario specificare un nome file o un nome di cartella.", "fileNameExistsError": "In questo percorso esiste già un file o una cartella **{0}**. Scegliere un nome diverso.", "invalidFileNameError": "Il nome **{0}** non è valido per un nome file o un nome di cartella. Scegliere un nome diverso.", "filePathTooLongError": "Con il nome **{0}** il percorso diventa troppo lungo. Scegliere un nome più breve.", - "compareWithSaved": "Confronta file attivo con file salvato", - "modifiedLabel": "{0} (su disco) ↔ {1}", "compareWithClipboard": "Confronta il file attivo con gli appunti", "clipboardComparisonLabel": "Appunti ↔ {0}" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index a02c62cce4f..4e2f71fcbb4 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Aprire prima un file per copiarne il percorso", - "openFileToReveal": "Aprire prima un file per visualizzarlo" + "revealInWindows": "Visualizza in Esplora risorse", + "revealInMac": "Visualizza in Finder", + "openContainer": "Apri cartella superiore", + "saveAs": "Salva con nome...", + "save": "Salva", + "saveAll": "Salva tutto", + "removeFolderFromWorkspace": "Rimuovi cartella dall'area di lavoro", + "openFileToReveal": "Aprire prima un file per visualizzarlo", + "openFileToCopy": "Aprire prima un file per copiarne il percorso" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 6fb07e8966e..bf53e0bc960 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "Editor", "formatOnSave": "Formatta un file durante il salvataggio. Deve essere disponibile un formattatore, il file non deve essere salvato automaticamente e l'editor non deve essere in fase di chiusura.", "explorerConfigurationTitle": "Esplora file", - "openEditorsVisible": "Numero di editor visualizzati nel riquadro degli editor aperti. Impostarlo su 0 per nascondere il riquadro.", - "dynamicHeight": "Controlla se l'altezza della sezione degli editor aperti deve essere adattata o meno dinamicamente al numero di elementi.", "autoReveal": "Controlla se Esplora risorse deve rivelare automaticamente e selezionare i file durante l'apertura.", "enableDragAndDrop": "Controlla se Esplora risorse deve consentire lo spostamento di file e cartelle tramite trascinamento della selezione.", "confirmDragAndDrop": "Controlla se Esplora risorse deve chiedere conferma prima di spostare file e cartelle tramite trascinamento della selezione.", diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 49ebceb9611..8052e44e9f3 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,9 @@ // Do not edit this file. It is machine generated. { "userGuide": "Usare le azioni della barra degli strumenti dell'editor a destra per **annullare** le modifiche o per **sovrascrivere** il contenuto su disco con le modifiche", - "discard": "Rimuovi", "overwrite": "Sovrascrivi", "retry": "Riprova", - "readonlySaveError": "Non è stato possibile salvare '{0}': il file è protetto da scrittura. Selezionare 'Sovrascrivi' per rimuovere la protezione.", + "discard": "Rimuovi", "genericSaveError": "Non è stato possibile salvare '{0}': {1}", "staleSaveError": "Non è stato possibile salvare '{0}': il contenuto sul disco è più recente. Fare clic su **Confronta** per confrontare la versione corrente con quella sul disco.", "compareChanges": "Confronta", diff --git a/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 5627c56823f..f7d56641c92 100644 --- a/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Editor aperti", "openEditosrSection": "Sezione Editor aperti", - "dirtyCounter": "{0} non salvati", - "saveAll": "Salva tutto", - "closeAllUnmodified": "Chiudi non modificati", - "closeAll": "Chiudi tutto", - "compareWithSaved": "Confronta con file salvato", - "close": "Chiudi", - "closeOthers": "Chiudi altri" + "dirtyCounter": "{0} non salvati" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..458e7226595 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "developer": "Sviluppatore" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..88a2d7b7487 --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Apri cartella dei log", + "showLogs": "Mostra log...", + "mainProcess": "Principale", + "sharedProcess": "Condiviso", + "rendererProcess": "Finestra", + "extensionHost": "Host dell'estensione", + "selectProcess": "Seleziona il processo", + "setLogLevel": "Imposta livello log", + "trace": "Analisi", + "debug": "Debug", + "info": "Informazioni", + "warn": "Avviso", + "err": "Errore", + "critical": "Errori critici", + "off": "Disattivato", + "selectLogLevel": "Seleziona il livello log" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/ita/src/vs/workbench/parts/markers/common/messages.i18n.json index 5e585c6ea40..0337b4edbb1 100644 --- a/i18n/ita/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Visualizza", - "problems.view.toggle.label": "Attiva/disattiva problemi", - "problems.view.focus.label": "Problemi di Focus", "problems.panel.configuration.title": "Visualizzazione Problemi", "problems.panel.configuration.autoreveal": "Controlla se la visualizzazione Problemi deve visualizzare automaticamente i file durante l'apertura", "markers.panel.title.problems": "Problemi", diff --git a/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..99ba0e6815c --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Output", + "viewCategory": "Visualizza", + "clearOutput.label": "Cancella output" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/ita/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 7c1a3a7d309..4669fa3cd56 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Prova la ricerca in linguaggio naturale.", "defaultSettings": "Inserire le impostazioni nell'editor di lato destro per eseguire l'override.", "noSettingsFound": "Non sono state trovate impostazioni.", "settingsSwitcherBarAriaLabel": "Selezione impostazioni", "userSettings": "Impostazioni utente", "workspaceSettings": "Impostazioni area di lavoro", - "folderSettings": "Impostazioni cartella", - "enableFuzzySearch": "Abilita la ricerca in linguaggio naturale" + "folderSettings": "Impostazioni cartella" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/ita/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index c4cdd4ead33..7149b64d24f 100644 --- a/i18n/ita/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Più usate", - "mostRelevant": "Più rilevanti", "defaultKeybindingsHeader": "Per sovrascrivere i tasti di scelta rapida, inserirli nel file dei tasti di scelta rapida." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 13929c1fa4b..9d39d9c9b41 100644 --- a/i18n/ita/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Visualizza", "commandsHandlerDescriptionDefault": "Mostra ed esegui comandi", "gotoLineDescriptionMac": "Vai alla riga", "gotoLineDescriptionWin": "Vai alla riga", diff --git a/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 44389863a65..7bc3bea7022 100644 --- a/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,6 @@ "toggleGitViewlet": "Mostra GIT", "source control": "Controllo del codice sorgente", "toggleSCMViewlet": "Mostra Gestione controllo servizi", - "view": "Visualizza" + "view": "Visualizza", + "scmConfigurationTitle": "Gestione controllo servizi" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json index ebff6e3002a..406201bbecb 100644 --- a/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Mostra il termine di ricerca precedente", "showSearchViewlet": "Mostra Cerca", "findInFiles": "Cerca nei file", - "findInFilesWithSelectedText": "Cerca nei file con il testo selezionato", "replaceInFiles": "Sostituisci nei file", - "replaceInFilesWithSelectedText": "Sostituisci nei file con il testo selezionato", "RefreshAction.label": "Aggiorna", "CollapseDeepestExpandedLevelAction.label": "Comprimi tutto", "ClearSearchResultsAction.label": "Cancella", diff --git a/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 25315a7f99e..cd92af0e23c 100644 --- a/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Trova nella cartella...", + "findInWorkspace": "Trova nell'area di lavoro...", "showTriggerActions": "Vai al simbolo nell'area di lavoro...", "name": "Cerca", "search": "Cerca", + "showSearchViewlet": "Mostra Cerca", "view": "Visualizza", + "findInFiles": "Cerca nei file", "openAnythingHandlerDescription": "Vai al file", "openSymbolDescriptionNormal": "Vai al simbolo nell'area di lavoro", - "searchOutputChannelTitle": "Cerca", "searchConfigurationTitle": "Cerca", "exclude": "Consente di configurare i criteri GLOB per escludere file e cartelle nelle ricerche. Eredita tutti i criteri GLOB dall'impostazione files.exclude.", "exclude.boolean": "Criterio GLOB da usare per trovare percorsi file. Impostare su True o False per abilitare o disabilitare il criterio.", diff --git a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..32dc45ab7fd --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "Preferenze" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 7cea9caafc3..356ac5c6fe2 100644 --- a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Seleziona il linguaggio per il frammento", - "openSnippet.errorOnCreate": "Non è possibile creare {0}", - "openSnippet.label": "Apri frammenti di codice utente", - "preferences": "Preferenze", "snippetSchema.json.default": "Frammento vuoto", "snippetSchema.json": "Configurazione del frammento utente", "snippetSchema.json.prefix": "Prefisso da usare quando si seleziona il frammento in IntelliSense", diff --git a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..fee95f06a2c --- /dev/null +++ b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Frammento utente" +} \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index d130ea84c16..02cfa9b88ab 100644 --- a/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Il linguaggio in `contributes.{0}.language` è sconosciuto. Valore specificato: {1}", "invalid.path.0": "È previsto un valore stringa in `contributes.{0}.path`. Valore specificato: {1}", + "invalid.language": "Il linguaggio in `contributes.{0}.language` è sconosciuto. Valore specificato: {1}", "invalid.path.1": "Valore previsto di `contributes.{0}.path` ({1}) da includere nella cartella dell'estensione ({2}). L'estensione potrebbe non essere più portatile.", "vscode.extension.contributes.snippets": "Frammenti per contributes.", "vscode.extension.contributes.snippets-language": "Identificatore di linguaggio per cui si aggiunge come contributo questo frammento.", "vscode.extension.contributes.snippets-path": "Percorso del file snippets. È relativo alla cartella delle estensioni e in genere inizia con './snippets/'.", "badVariableUse": "Uno o più frammenti dall'estensione '{0}' confondono molto probabilmente variabili-frammento e segnaposto-frammento (Vedere https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax per maggiori dettagli)", "badFile": "Non è stato possibile leggere il file di frammento \"{0}\".", - "source.snippet": "Frammento utente", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index 6d85a595027..2d53dad9156 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "Il colore di primo piano del terminale.", "terminalCursor.foreground": "Colore di primo piano del cursore del terminale.", "terminalCursor.background": "Colore di sfondo del cursore del terminale. Permette di personalizzare il colore di un carattere quando sovrapposto da un blocco cursore.", - "terminal.selectionBackground": "Colore di sfondo di selezione del terminale.", - "terminal.ansiColor": "Colore ANSI '{0}' nel terminale." + "terminal.selectionBackground": "Colore di sfondo di selezione del terminale." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 6055f7da096..f695d8b57b2 100644 --- a/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "È possibile modificare la shell di terminale di default selezionando il pulsante Personalizza.", "customize": "Personalizza", "cancel": "Annulla", - "never again": "OK, non visualizzare più", "terminal.integrated.chooseWindowsShell": "Seleziona la shell di terminale preferita - è possibile modificare questa impostazione dopo", "terminalService.terminalCloseConfirmationSingular": "C'è una sessione di terminale attiva. Terminarla?", "terminalService.terminalCloseConfirmationPlural": "Ci sono {0} sessioni di terminale attive. Terminarle?" diff --git a/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 46c966a637e..7d586fdfcf4 100644 --- a/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/ita/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "Riquadro comandi...", "settings": "Impostazioni", "keyboardShortcuts": "Scelte rapide da tastiera", + "userSnippets": "Frammenti utente", "selectTheme.label": "Tema colori", "themes.selectIconTheme.label": "Tema icona file", "not available": "Aggiornamenti non disponibili", diff --git a/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 6952c245dd7..fb6e0553811 100644 --- a/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "Il File è una Directory", + "fileNotModifiedError": "File non modificato dal giorno", "fileBinaryError": "Il file sembra essere binario e non può essere aperto come file di testo" } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/ita/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index c6f9ca63862..11826e9bcfb 100644 --- a/i18n/ita/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Salvare le modifiche apportate a {0}?", "saveChangesMessages": "Salvare le modifiche apportate ai file seguenti di {0}?", - "moreFile": "...1 altro file non visualizzato", - "moreFiles": "...{0} altri file non visualizzati", "saveAll": "&&Salva tutto", "save": "&&Salva", "dontSave": "&&Non salvare", diff --git a/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index c8e3f4e44d8..7ff89ea80bd 100644 --- a/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Sostituisce i colori del tema colori attualmente selezionato.", - "editorColors": "Sostituisce i colori dell'editor e lo stile dei font nel tema colori attualmente selezionato.", "editorColors.comments": "Imposta i colori e gli stili per i commenti", "editorColors.strings": "Imposta i colori e gli stili per i valori letterali stringa.", "editorColors.keywords": "Imposta i colori e gli stili per le parole chiave.", @@ -19,5 +18,6 @@ "editorColors.types": "Imposta i colori e gli stili per i riferimenti e le dichiarazioni di tipo.", "editorColors.functions": "Imposta i colori e gli stili per i riferimenti e le dichiarazioni di funzioni.", "editorColors.variables": "Imposta i colori e gli stili per i riferimenti e le dichiarazioni di variabili.", - "editorColors.textMateRules": "Imposta i colori e gli stili usando le regole di creazione temi di TextMate (impostazione avanzata)." + "editorColors.textMateRules": "Imposta i colori e gli stili usando le regole di creazione temi di TextMate (impostazione avanzata).", + "editorColors": "Sostituisce i colori dell'editor e lo stile dei font nel tema colori attualmente selezionato." } \ No newline at end of file diff --git a/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 83c0f4d81a8..af0e885e44b 100644 --- a/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/ita/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Impossibile scrivere nel file di configurazione dell'area di lavoro. Si prega di aprire il file per correggere eventuali errori/avvisi e riprovare.", "errorWorkspaceConfigurationFileDirty": "Impossibile scrivere nel file di configurazione dell'area di lavoro, perché il file è sporco. Si prega di salvarlo e riprovare.", "openWorkspaceConfigurationFile": "Apri file di configurazione dell'area di lavoro", - "close": "Chiudi", - "enterWorkspace.close": "Chiudi", - "enterWorkspace.dontShowAgain": "Non visualizzare più questo messaggio", - "enterWorkspace.moreInfo": "Altre informazioni", - "enterWorkspace.prompt": "Ulteriori informazioni su come lavorare con più cartelle in VS Code." + "close": "Chiudi" } \ No newline at end of file diff --git a/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json b/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json index f8b65e69685..905556c139c 100644 --- a/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json +++ b/i18n/jpn/extensions/configuration-editing/out/settingsDocumentHelper.i18n.json @@ -22,7 +22,7 @@ "fileDescription": "特定のファイル拡張子を持つすべてのファイルと一致します。", "filesLabel": "複数の拡張子のファイル", "filesDescription": "いずれかのファイル拡張子を持つすべてのファイルと一致します。", - "derivedLabel": "同じ名前の兄弟があるファイル", + "derivedLabel": "同じ名前の同種のファイル", "derivedDescription": "名前が同じで拡張子が異なる兄弟を持つファイルと一致します。", "topFolderLabel": "特定の名前のフォルダー (最上位)", "topFolderDescription": "特定の名前の最上位にあるフォルダーと一致します。", @@ -32,7 +32,7 @@ "folderDescription": "任意の場所にある特定の名前のフォルダーと一致します。", "falseDescription": "パターンを無効にします。", "trueDescription": "パターンを有効にします。", - "siblingsDescription": "名前が同じで拡張子が異なる兄弟を持つファイルと一致します。", + "siblingsDescription": "名前が同じで異なる拡張子を持つ同種のファイルと一致します。", "languageSpecificEditorSettings": "言語固有のエディター設定", "languageSpecificEditorSettingsDescription": "言語に対するエディター設定を上書きします" } \ No newline at end of file diff --git a/i18n/jpn/extensions/css/package.i18n.json b/i18n/jpn/extensions/css/package.i18n.json index 5ff9ba2550a..4716b3c9ee1 100644 --- a/i18n/jpn/extensions/css/package.i18n.json +++ b/i18n/jpn/extensions/css/package.i18n.json @@ -5,24 +5,24 @@ // Do not edit this file. It is machine generated. { "css.title": "CSS", - "css.lint.argumentsInColorFunction.desc": "正しくないパラメーターの数", - "css.lint.boxModel.desc": "パディングまたは枠線を使用する場合は幅または高さを使用しないでください", - "css.lint.compatibleVendorPrefixes.desc": "ベンダー固有のプレフィックスを使用する場合は、他のすべてのベンダー固有のプロパティも必ず含めてください", + "css.lint.argumentsInColorFunction.desc": "無効なパラメーター数値", + "css.lint.boxModel.desc": "padding や border を使用するときに width や height を使用しないでください", + "css.lint.compatibleVendorPrefixes.desc": "ベンダー プレフィックス を使用するときは、他すべてのベンダー プレフィックスも必ず含めてください", "css.lint.duplicateProperties.desc": "重複するスタイル定義を使用しないでください", "css.lint.emptyRules.desc": "空の規則セットを使用しないでください", - "css.lint.float.desc": "'float' は使用しないでください。float を使用すると、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", + "css.lint.float.desc": "'float' の使用を避けてください。float は脆弱な CSS につながり、レイアウトの一部が変更されたときに CSS が破損しやすくなります。", "css.lint.fontFaceProperties.desc": "@font-face 規則で 'src' プロパティと 'font-family' プロパティを定義する必要があります", - "css.lint.hexColorLength.desc": "16 進数の色には、3 つまたは 6 つの 16 進数が含まれる必要があります", + "css.lint.hexColorLength.desc": "Hex には 3 つまたは 6 つの 16 進数が含まれる必要があります", "css.lint.idSelector.desc": "セレクターには ID を含めないでください。これらの規則と HTML の結合が密接すぎます。", "css.lint.ieHack.desc": "IE ハックは、IE7 以前をサポートする場合にのみ必要です", "css.lint.important.desc": "!important は使用しないでください。これは CSS 全体の特定性が制御不能になり、リファクタリングが必要なことを示しています。", "css.lint.importStatement.desc": "複数の Import ステートメントを同時に読み込むことはできません", - "css.lint.propertyIgnoredDueToDisplay.desc": "表示によりプロパティが無視されます。たとえば、'display: inline' の場合、width、height、margin-top、margin-bottom、および float のプロパティには効果がありません", + "css.lint.propertyIgnoredDueToDisplay.desc": "display によってプロパティを無視します。例: 'display: inline' の場合、width、height、margin-top、margin-bottom、float プロパティには効果がありません。", "css.lint.universalSelector.desc": "ユニバーサル セレクター (*) を使用すると処理速度が低下することが分かっています", "css.lint.unknownProperties.desc": "不明なプロパティ。", "css.lint.unknownVendorSpecificProperties.desc": "不明なベンダー固有のプロパティ。", "css.lint.vendorPrefix.desc": "ベンダー固有のプレフィックスを使用する場合は、標準のプロパティも含めます", - "css.lint.zeroUnits.desc": "0 の単位は必要ありません", + "css.lint.zeroUnits.desc": "0 に単位は必要ありません", "css.trace.server.desc": "VS Code と CSS 言語サーバー間の通信をトレースします。", "css.validate.title": "CSS の検証と問題の重大度を制御します。", "css.validate.desc": "すべての検証を有効または無効にします", diff --git a/i18n/jpn/extensions/git/out/autofetch.i18n.json b/i18n/jpn/extensions/git/out/autofetch.i18n.json index a4b33109cea..4dcee36f0c2 100644 --- a/i18n/jpn/extensions/git/out/autofetch.i18n.json +++ b/i18n/jpn/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "はい", + "read more": "詳細を参照", "no": "いいえ", - "not now": "あとで", - "suggest auto fetch": "Git リポジトリの自動フェッチを有効にしますか?" + "not now": "後で通知する", + "suggest auto fetch": "Code が定期的に `git fetch` を実行してもよろしいですか?" } \ No newline at end of file diff --git a/i18n/jpn/extensions/git/out/commands.i18n.json b/i18n/jpn/extensions/git/out/commands.i18n.json index e73b6d879f2..5411af2ba63 100644 --- a/i18n/jpn/extensions/git/out/commands.i18n.json +++ b/i18n/jpn/extensions/git/out/commands.i18n.json @@ -13,7 +13,7 @@ "cancel tooltip": "クローンのキャンセル", "cloning": "Git リポジトリを複製しています...", "openrepo": "リポジトリを開く", - "proposeopen": "複製したリポジトリを開きますか?", + "proposeopen": "クローンしたリポジトリを開きますか?", "init": "Git リポジトリを初期化するワークスペース フォルダーを選択してください", "init repo": "リポジトリの初期化", "create repo": "リポジトリの初期化", @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nこの変更は元に戻すことはできません。現在のワーキング セットは永久に失われます。", "yes discard tracked": "1 つの追跡ファイルを破棄", "yes discard tracked multiple": "{0} 個の追跡ファイルを破棄", + "unsaved files single": "次のファイルが保存されていません: {0}。\n\nコミット前に保存しますか?", + "unsaved files": "{0} 個の保存されていないファイルがあります。\n\nコミット前に保存しますか?", + "save and commit": "すべて保存してコミットする", + "commit": "とにかくコミットする", "no staged changes": "コミットするステージされた変更がありません。\n\nすべての変更を自動的にステージして、直接コミットしますか?", "always": "常に行う", "no changes": "コミットする必要のある変更はありません。", @@ -64,11 +68,12 @@ "no remotes to pull": "リポジトリには、プル元として構成されているリモートがありません。", "pick remote pull repo": "リモートを選んで、ブランチを次からプルします:", "no remotes to push": "リポジトリには、プッシュ先として構成されているリモートがありません。", - "push with tags success": "タグが正常にプッシュされました。", "nobranch": "リモートにプッシュするブランチをチェックアウトしてください。", + "confirm publish branch": "'{0}' ブランチに上流ブランチはありません。このブランチを公開しますか?", + "ok": "OK", + "push with tags success": "タグが正常にプッシュされました。", "pick remote": "リモートを選んで、ブランチ '{0}' を次に公開します:", "sync is unpredictable": "このアクションはコミットを '{0}' との間でプッシュしたりプルしたりします。", - "ok": "OK", "never again": "OK、今後は表示しない", "no remotes to publish": "リポジトリには、発行先として構成されているリモートがありません。", "no changes stash": "スタッシュする変更がありません。", diff --git a/i18n/jpn/extensions/git/package.i18n.json b/i18n/jpn/extensions/git/package.i18n.json index 1574014e89e..bdc7a5612ed 100644 --- a/i18n/jpn/extensions/git/package.i18n.json +++ b/i18n/jpn/extensions/git/package.i18n.json @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "command.clone": "複製", + "command.clone": "クローン", "command.init": "リポジトリの初期化", "command.close": "リポジトリを閉じる", "command.refresh": "最新の情報に更新", @@ -52,8 +52,9 @@ "command.stash": "スタッシュ", "command.stashPop": "スタッシュを適用して削除...", "command.stashPopLatest": "最新のスタッシュを適用して削除", - "config.enabled": "Git が有効になっているかどうか", + "config.enabled": "Git を有効にするかどうか", "config.path": "Git 実行可能ファイルのパス", + "config.autoRepositoryDetection": "レポジトリを自動的に検出するかどうか", "config.autorefresh": "自動更新が有効かどうか", "config.autofetch": "自動フェッチが有効かどうか", "config.enableLongCommitWarning": "長いコミット メッセージについて警告するかどうか", @@ -72,5 +73,6 @@ "colors.deleted": "リソースを検出した場合の配色", "colors.untracked": "リソースを追跡しない場合の配色", "colors.ignored": "リソースを無視する場合の配色", - "colors.conflict": "リソースが競合する場合の配色" + "colors.conflict": "リソースが競合する場合の配色", + "colors.submodule": "サブモジュールの配色。" } \ No newline at end of file diff --git a/i18n/jpn/extensions/markdown/package.i18n.json b/i18n/jpn/extensions/markdown/package.i18n.json index 9c09de2d69a..5f1c24f35e0 100644 --- a/i18n/jpn/extensions/markdown/package.i18n.json +++ b/i18n/jpn/extensions/markdown/package.i18n.json @@ -19,6 +19,6 @@ "markdown.showSource.title": "ソースの表示", "markdown.styles.dec": "マークダウン プレビューから使用する CSS スタイル シートの URL またはローカル パスの一覧。相対パスは、エクスプローラーで開かれているフォルダーへの絶対パスと解釈されます。開かれているフォルダーがない場合、マークダウン ファイルの場所を基準としていると解釈されます。'\\' はすべて '\\\\' と入力する必要があります。", "markdown.showPreviewSecuritySelector.title": "プレビュー のセキュリティ設定を変更", - "markdown.trace.desc": "マークダウン拡張機能のデバッグログを有効にします。", + "markdown.trace.desc": "マークダウン拡張機能のデバッグ ログを有効にします。", "markdown.refreshPreview.title": "プレビューを更新" } \ No newline at end of file diff --git a/i18n/jpn/extensions/php/package.i18n.json b/i18n/jpn/extensions/php/package.i18n.json index 1e7a986fcec..77aae3a85d1 100644 --- a/i18n/jpn/extensions/php/package.i18n.json +++ b/i18n/jpn/extensions/php/package.i18n.json @@ -6,7 +6,7 @@ { "configuration.suggest.basic": "組み込みの PHP 言語候補機能を有効にするかどうかを設定します。このサポートによって、PHP グローバルと変数の候補が示されます。", "configuration.validate.enable": "組み込みの PHP 検証を有効/無効にします。", - "configuration.validate.executablePath": "PHP 実行可能ファイルを指します。", + "configuration.validate.executablePath": "PHP 実行可能ファイルを指定します。", "configuration.validate.run": "リンターを保存時に実行するか、入力時に実行するか。", "configuration.title": "PHP", "commands.categroy.php": "PHP", diff --git a/i18n/jpn/extensions/typescript/out/commands.i18n.json b/i18n/jpn/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..e996cf2c1a9 --- /dev/null +++ b/i18n/jpn/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "TypeScript または JavaScript プロジェクトを使用するには、VS Code でフォルダーを開いてください", + "typescript.projectConfigUnsupportedFile": "TypeScript または JavaScript のプロジェクトを判別できませんでした。サポートされていないファイルの種類です", + "typescript.projectConfigCouldNotGetInfo": "TypeScript または JavaScript のプロジェクトを判別できませんでした", + "typescript.noTypeScriptProjectConfig": "ファイルは TypeScript プロジェクトの一部ではない", + "typescript.noJavaScriptProjectConfig": "ファイルは JavaScript プロジェクトの一部ではない", + "typescript.configureTsconfigQuickPick": "tsconfig.json を構成する", + "typescript.configureJsconfigQuickPick": "jsconfig.json を構成する", + "typescript.projectConfigLearnMore": "詳細情報" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/jpn/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..4c0d77d1fd0 --- /dev/null +++ b/i18n/jpn/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (ファイルの中のすべてを修正する)" +} \ No newline at end of file diff --git a/i18n/jpn/extensions/typescript/package.i18n.json b/i18n/jpn/extensions/typescript/package.i18n.json index 837e11b2972..0b964b94699 100644 --- a/i18n/jpn/extensions/typescript/package.i18n.json +++ b/i18n/jpn/extensions/typescript/package.i18n.json @@ -37,7 +37,7 @@ "typescript.referencesCodeLens.enabled": "TypeScript ファイル内で CodeLens の参照を有効/無効にします。TypeScript 2.0.6 以上が必要です。", "typescript.implementationsCodeLens.enabled": "CodeLens の実装を有効/無効にします。TypeScript 2.2.0 以上が必要です。", "typescript.openTsServerLog.title": "TS サーバーのログを開く", - "typescript.restartTsServer": "TS サーバーを再起動する", + "typescript.restartTsServer": "TS サーバーを再起動", "typescript.selectTypeScriptVersion.title": "TypeScript のバージョンの選択", "typescript.reportStyleChecksAsWarnings": "スタイルチェックレポートを警告扱いとする", "jsDocCompletion.enabled": " 自動 JSDoc コメントを有効/無効にします", diff --git a/i18n/jpn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/jpn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/jpn/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/base/node/ps.i18n.json b/i18n/jpn/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..94b9be48727 --- /dev/null +++ b/i18n/jpn/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "CPU とメモリーの情報を収集しています。これには数秒かかる場合があります。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/code/electron-main/menus.i18n.json b/i18n/jpn/src/vs/code/electron-main/menus.i18n.json index 8a7dad6df22..3de2dd195d0 100644 --- a/i18n/jpn/src/vs/code/electron-main/menus.i18n.json +++ b/i18n/jpn/src/vs/code/electron-main/menus.i18n.json @@ -97,7 +97,7 @@ "miMoveSidebarRight": "サイド バーを右へ移動(&&M)", "miMoveSidebarLeft": "サイド バーを左へ移動(&&M)", "miTogglePanel": "パネルの切り替え(&&P)", - "miHideStatusbar": "ステータス バーを非表示にする(&&H)", + "miHideStatusbar": "ステータス バーを非表示(&&H)", "miShowStatusbar": "ステータス バーの表示(&&S)", "miHideActivityBar": "アクティビティ バーを非表示にする(&&A)", "miShowActivityBar": "アクティビティ バーを表示する(&&A)", @@ -146,7 +146,7 @@ "miEnableAllBreakpoints": "すべてのブレークポイントを有効にする", "miDisableAllBreakpoints": "すべてのブレークポイントを無効にする(&&L)", "miRemoveAllBreakpoints": "すべてのブレークポイントを削除する(&&R)", - "miInstallAdditionalDebuggers": "その他のデバッガーをインストールします(&&I)...", + "miInstallAdditionalDebuggers": "追加のデバッガーをインストール(&&I)...", "mMinimize": "最小化", "mZoom": "ズーム", "mBringToFront": "すべてを前面に配置", diff --git a/i18n/jpn/src/vs/code/node/cliProcessMain.i18n.json b/i18n/jpn/src/vs/code/node/cliProcessMain.i18n.json index 17e8239c8b5..36f86e4b3e5 100644 --- a/i18n/jpn/src/vs/code/node/cliProcessMain.i18n.json +++ b/i18n/jpn/src/vs/code/node/cliProcessMain.i18n.json @@ -10,7 +10,7 @@ "successVsixInstall": "拡張機能 '{0}' が正常にインストールされました。", "cancelVsixInstall": "拡張機能 '{0}' のインストールをキャンセルしました。", "alreadyInstalled": "拡張機能 '{0}' は既にインストールされています。", - "foundExtension": "マーケットプレースで '{0}' が見つかりました。", + "foundExtension": "Marketplace で '{0}' が見つかりました。", "installing": "インストールしています...", "successInstall": "拡張機能 '{0}' v{1} が正常にインストールされました!", "uninstalling": "{0} をアンインストールしています...", diff --git a/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json index ccf74d0af32..8a9677dc258 100644 --- a/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/jpn/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "行番号は、絶対数として表示されます。", "lineNumbers.relative": "行番号は、カーソル位置までの行数として表示されます。", "lineNumbers.interval": "行番号は 10 行ごとに表示されます。", - "lineNumbers": "行番号の表示を制御します。使用可能な値は、'on'、'off'、および 'relative' です。", + "lineNumbers": "行番号の表示を制御します。使用可能な値は、'on'、'off'、'relative'、'interval' です。", "rulers": "等幅フォントの特定番号の後ろに垂直ルーラーを表示します。複数のルーラーには複数の値を使用します。配列が空の場合はルーラーを表示しません。", "wordSeparators": "単語に関連したナビゲーションまたは操作を実行するときに、単語の区切り文字として使用される文字", "tabSize": "1 つのタブに相当するスペースの数。`editor.detectIndentation` がオンの場合、この設定はファイル コンテンツに基づいて上書きされます。", @@ -40,9 +40,9 @@ "wordWrapColumn": "'editor.wordWrap' が 'wordWrapColumn' または 'bounded' の場合に、エディターの折り返し桁を制御します。", "wrappingIndent": "折り返し行のインデントを制御します。'none'、'same'、または 'indent' のいずれかを指定できます。", "mouseWheelScrollSensitivity": "マウス ホイール スクロール イベントの `deltaX` と `deltaY` で使用される乗数", - "multiCursorModifier.ctrlCmd": "Windows および Linux 上の `Control` と OSX 上の `Command` にマップします。", - "multiCursorModifier.alt": "Windows および Linux 上の `Alt` と OSX 上の `Option` にマップします。", - "multiCursorModifier": "マウスで複数のカーソルを追加するときに使用する修飾キーです。`ctrlCmd` は Windows および Linux 上の `Control` キーと OSX 上の `Command` キーにマップします。「定義に移動」や「リンクを開く」のマウス操作は、マルチカーソルの修飾キーと競合しないように適用されます。", + "multiCursorModifier.ctrlCmd": "Windows および Linux 上の `Control` キーと macOS 上の `Command` キーに割り当てます。", + "multiCursorModifier.alt": "Windows および Linux 上の `Alt` キーと macOS 上の `Option` キーに割り当てます。", + "multiCursorModifier": "マウスを使用して複数のカーソルを追加するときに使用する修飾キーです。`ctrlCmd` は Windows および Linux 上の `Control` キーと macOS 上の `Command` キーに割り当てます。「定義に移動」や「リンクを開く」のマウス操作は、マルチカーソルの修飾キーと競合しないように適用されます。", "quickSuggestions.strings": "文字列内でクイック候補を有効にします。", "quickSuggestions.comments": "コメント内でクイック候補を有効にします。", "quickSuggestions.other": "文字列およびコメント外でクイック候補を有効にします。", @@ -72,6 +72,7 @@ "cursorBlinking": "カーソルのアニメーション スタイルを制御します。指定できる値は 'blink'、'smooth'、'phase'、'expand'、'solid' です", "mouseWheelZoom": "Ctrl キーを押しながらマウス ホイールを使用してエディターのフォントをズームします", "cursorStyle": "カーソルのスタイルを制御します。指定できる値は 'block'、'block-outline'、'line'、'line-thin'、'underline'、'underline-thin' です", + "lineCursorWidth": "editor.cursorStyle が 'line' に設定されている場合、カーソルの幅を制御する", "fontLigatures": "フォントの合字を使用します", "hideCursorInOverviewRuler": "概要ルーラーでカーソルを非表示にするかどうかを制御します。", "renderWhitespace": "エディターで空白文字を表示する方法を制御します。'none'、'boundary' および 'all' が使用可能です。'boundary' オプションでは、単語間の単一スペースは表示されません。", diff --git a/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json index ccbe80f4d39..89993cc3618 100644 --- a/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/jpn/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "カーソル位置の行を強調表示する背景色。", "lineHighlightBorderBox": "カーソル位置の行の境界線を強調表示する背景色。", - "rangeHighlight": "Quick Open 機能や検索機能などによって強調表示された範囲の背景色。", + "rangeHighlight": "Quick Open 機能や検索機能などによって強調表示された範囲の背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", "caret": "エディターのカーソルの色。", "editorCursorBackground": "選択された文字列の背景色です。選択された文字列の背景色をカスタマイズ出来ます。", "editorWhitespaces": "エディターのスペース文字の色。", diff --git a/i18n/jpn/src/vs/editor/contrib/folding/folding.i18n.json b/i18n/jpn/src/vs/editor/contrib/folding/folding.i18n.json index c6a310be421..1c780e8f0a3 100644 --- a/i18n/jpn/src/vs/editor/contrib/folding/folding.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/folding/folding.i18n.json @@ -13,5 +13,5 @@ "unfoldAllMarkerRegions.label": "すべての領域を展開", "foldAllAction.label": "すべて折りたたみ", "unfoldAllAction.label": "すべて展開", - "foldLevelAction.label": "折りたたみレベル {0}" + "foldLevelAction.label": "レベル {0} で折りたたむ" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 53ea71a9d4e..37cec91d1cd 100644 --- a/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "次のエラーまたは警告へ移動", - "markerAction.previous.label": "前のエラーまたは警告へ移動", + "markerAction.next.label": "次の問題 (エラー、警告、情報) へ移動", + "markerAction.previous.label": "前の問題 (エラー、警告、情報) へ移動", "editorMarkerNavigationError": "エディターのマーカー ナビゲーション ウィジェットのエラーの色。", "editorMarkerNavigationWarning": "エディターのマーカー ナビゲーション ウィジェットの警告の色。", "editorMarkerNavigationInfo": "エディターのマーカー ナビゲーション ウィジェットの情報の色。", diff --git a/i18n/jpn/src/vs/editor/contrib/multicursor/multicursor.i18n.json b/i18n/jpn/src/vs/editor/contrib/multicursor/multicursor.i18n.json index 0df6dca88c6..22250151607 100644 --- a/i18n/jpn/src/vs/editor/contrib/multicursor/multicursor.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/multicursor/multicursor.i18n.json @@ -7,10 +7,10 @@ "mutlicursor.insertAbove": "カーソルを上に挿入", "mutlicursor.insertBelow": "カーソルを下に挿入", "mutlicursor.insertAtEndOfEachLineSelected": "カーソルを行末に挿入", - "addSelectionToNextFindMatch": "選択した項目を次の一致項目に追加", - "addSelectionToPreviousFindMatch": "選んだ項目を前の一致項目に追加する", + "addSelectionToNextFindMatch": "選択項目を次の一致項目に追加", + "addSelectionToPreviousFindMatch": "選択項目を次の一致項目に追加", "moveSelectionToNextFindMatch": "最後に選択した項目を次の一致項目に移動", - "moveSelectionToPreviousFindMatch": "最後に選んだ項目を前の一致項目に移動する", - "selectAllOccurrencesOfFindMatch": "一致するすべての出現箇所を選択します", + "moveSelectionToPreviousFindMatch": "最後に選択した項目を前の一致項目に移動", + "selectAllOccurrencesOfFindMatch": "一致するすべての出現箇所を選択", "changeAll.label": "すべての出現箇所を変更" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json b/i18n/jpn/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json index 63cb6013496..6b75d7b1bbe 100644 --- a/i18n/jpn/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggle.tabMovesFocus": "Tab キーを切り替えるとフォーカスが移動します" + "toggle.tabMovesFocus": "TAB キーのフォーカス移動を切り替え" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 8eac21c6979..9ecf4479aa8 100644 --- a/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/jpn/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "変数の読み取りなど読み取りアクセス中のシンボルの背景色。", - "wordHighlightStrong": "変数への書き込みなど書き込みアクセス中のシンボルの背景色。", + "wordHighlight": "変数の読み取りなど読み取りアクセス中のシンボルの背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "wordHighlightStrong": "変数への書き込みなど書き込みアクセス中のシンボルの背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", "overviewRulerWordHighlightForeground": "シンボルを強調表示するときの概要ルーラーのマーカー色。", "overviewRulerWordHighlightStrongForeground": "書き込みアクセス シンボルを強調表示するときの概要ルーラーのマーカー色。", "wordHighlight.next.label": "次のシンボル ハイライトに移動", diff --git a/i18n/jpn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/jpn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 981e3bb87da..2a2b18aa6b8 100644 --- a/i18n/jpn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/jpn/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}` は有効なメニュー識別子ではありません", "missing.command": "メニュー項目が、'commands' セクションで定義されていないコマンド `{0}` を参照しています。", "missing.altCommand": "メニュー項目が、'commands' セクションで定義されていない alt コマンド `{0}` を参照しています。", - "dupe.command": "メニュー項目において、既定と alt コマンドが同じコマンドを参照しています", - "nosupport.altCommand": "申し訳ございません。現在、alt コマンドをサポートしているのは 'editor/title' メニューの 'navigation' グループのみです" + "dupe.command": "メニュー項目において、既定と alt コマンドが同じコマンドを参照しています" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json b/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json index e5dd71eb7e2..ef9379487ec 100644 --- a/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/jpn/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,36 @@ "diff": "2 つのファイルを比較します。", "add": "最後にアクティブだったウィンドウにフォルダーを追加します。", "goto": "指定した行と文字の位置にあるパスでファイルを開きます。", - "locale": "使用する国と地域 (例:en-US や zh-TW など)。", "newWindow": "新しい Code のインスタンスを強制します。", - "performance": "'Developer: Startup Performance' コマンドを有効にして開始します。", - "prof-startup": "起動中に CPU プロファイラーを実行する", - "inspect-extensions": "拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", - "inspect-brk-extensions": "起動後に一時停止されている拡張ホストとの拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", "reuseWindow": "最後のアクティブ ウィンドウにファイルまたはフォルダーを強制的に開きます。", - "userDataDir": "ユーザー データを保持するディレクトリを指定します。ルートで実行している場合に役立ちます。", - "log": "使用するログレベル。既定値は 'info' です。利用可能な値は 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off' です。", - "verbose": "詳細出力を表示します (--wait を含みます)。", "wait": "現在のファイルが閉じられるまで待機します。", + "locale": "使用する国と地域 (例:en-US や zh-TW など)。", + "userDataDir": "ユーザー データを保持するディレクトリを指定します。ルートで実行している場合に役立ちます。", + "version": "バージョンを表示します。", + "help": "使用法を表示します。", "extensionHomePath": "拡張機能のルート パスを設定します。", "listExtensions": "インストールされている拡張機能を一覧表示します。", "showVersions": "--list-extension と使用するとき、インストールされている拡張機能のバージョンを表示します。", "installExtension": "拡張機能をインストールします。", "uninstallExtension": "拡張機能をアンインストールします。", "experimentalApis": "拡張機能に対して Proposed API 機能を有効にします。", - "disableExtensions": "インストールされたすべての拡張機能を無効にします。", - "disableGPU": "GPU ハードウェア アクセラレータを無効にします。", + "verbose": "詳細出力を表示します (--wait を含みます)。", + "log": "使用するログレベル。既定値は 'info' です。利用可能な値は 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off' です。", "status": "プロセスの使用状況や診断情報を印刷します。", - "version": "バージョンを表示します。", - "help": "使用法を表示します。", + "performance": "'Developer: Startup Performance' コマンドを有効にして開始します。", + "prof-startup": "起動中に CPU プロファイラーを実行する", + "disableExtensions": "インストールされたすべての拡張機能を無効にします。", + "inspect-extensions": "拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", + "inspect-brk-extensions": "起動後に一時停止されている拡張ホストとの拡張機能のデバッグとプロファイリングを許可します。接続 URI を開発者ツールでチェックします。", + "disableGPU": "GPU ハードウェア アクセラレータを無効にします。", + "uploadLogs": "現在のセッションから安全なエンドポイントにログをアップロードします。", + "issue": "問題を報告します。", "usage": "使用法", "options": "オプション", "paths": "パス", - "optionsUpperCase": "オプション" + "stdinWindows": "別のプログラムから出力を読み取るには、'-' を付け足してください (例: 'echo Hello World | {0} -')", + "stdinUnix": "stdin から読み取るには、'-' を付け足してください (例: 'ps aux | grep code | {0} -')", + "optionsUpperCase": "オプション", + "extensionsManagement": "拡張機能の管理", + "troubleshooting": "トラブルシューティング" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 9901a3c82e4..9b169d44885 100644 --- a/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/jpn/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "正しくない拡張機能: package.json は JSON ファイルではありません。", - "restartCodeLocal": "{0} を再インストールする前に、Code を再起動してください。", + "restartCode": "{0} を再インストールする前に、Code を再起動してください。", "installingOutdatedExtension": "この拡張機能の新しいバージョンが既にインストールされています。古いバージョンでこれを上書きしますか?", "override": "上書き", "cancel": "キャンセル", - "notFoundCompatible": "VS Code の現在のバージョン '{1}' と互換性を持つ拡張機能 '{0}' が見つからないため、インストールできません。", - "quitCode": "拡張機能の古いインスタンスがまだ実行中であるため、インストールできません。再インストール前に VS Code の終了と起動を実施してください。", - "exitCode": "拡張機能の古いインスタンスがまだ実行中であるため、インストールできません。再インストール前に VS Code の終了と起動を実施してください。", + "errorInstallingDependencies": "依存関係のインストール中にエラーが発生しました。{0}", + "notFoundCompatible": "'{0}' をインストールできません。VS Code '{1}' と互換性がある利用可能なバージョンがありません。", "notFoundCompatibleDependency": "VS Code の現在のバージョン '{1}' と互換性を持つ、依存関係がある拡張機能 '{0}' が見つからないため、インストールできません。", + "quitCode": "拡張機能をインストールできません。再インストールの前に VS Code の終了と起動を実施してください。", + "exitCode": "拡張機能をインストールできません。再インストールの前に VS Code の終了と起動を実施してください。", "uninstallDependeciesConfirmation": "'{0}' のみをアンインストールしますか、または依存関係もアンインストールしますか?", "uninstallOnly": "限定", "uninstallAll": "すべて", diff --git a/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json b/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..bebbbaf4486 --- /dev/null +++ b/i18n/jpn/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "ワークベンチ", + "multiSelectModifier.ctrlCmd": "Windows および Linux 上の `Control` キーと macOS 上の `Command` キーに割り当てます。", + "multiSelectModifier.alt": "Windows および Linux 上の `Alt` キーと macOS 上の `Option` キーに割り当てます。", + "multiSelectModifier": "(tたとえば、サポートしている場合、ツリーやリストで) マウスを使用して項目を複数選択するときに使用する修飾キーです。`ctrlCmd` は Windows および Linux 上の `Control` キーと macOS 上の `Command` に割り当てます。「横に開く」のマウス操作をサポートしている場合、複数選択の修飾キーと競合しないように適応されます。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/message/common/message.i18n.json b/i18n/jpn/src/vs/platform/message/common/message.i18n.json index 85415e2c95f..15eee72cd0d 100644 --- a/i18n/jpn/src/vs/platform/message/common/message.i18n.json +++ b/i18n/jpn/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "閉じる", "later": "後続", - "cancel": "キャンセル" + "cancel": "キャンセル", + "moreFile": "...1 つの追加ファイルが表示されていません", + "moreFiles": "...{0} 個の追加ファイルが表示されていません" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json index 24c492550e3..46bb9caa152 100644 --- a/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/jpn/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "エディター ウィジェットの境界線色。ウィジェットに境界線があり、ウィジェットによって配色を上書きされていない場合でのみこの配色は使用されます。", "editorSelectionBackground": "エディターの選択範囲の色。", "editorSelectionForeground": "ハイ コントラストの選択済みテキストの色。", - "editorInactiveSelection": "非アクティブなエディターの選択範囲の色。", - "editorSelectionHighlight": "選択範囲と同じコンテンツの領域の色。", + "editorInactiveSelection": "非アクティブなエディターの選択範囲の色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "editorSelectionHighlight": "選択範囲と同じコンテンツの領域の色。下にある装飾を隠さないために、色は不透過であってはなりません。", "editorFindMatch": "現在の検索一致項目の色。", - "findMatchHighlight": "他の検索一致項目の色。", - "findRangeHighlight": "検索を制限する範囲の色。", - "hoverHighlight": "ホバーが表示されているワードの下を強調表示します。", + "findMatchHighlight": "他の検索一致項目の色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "findRangeHighlight": "検索を制限する範囲の色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "hoverHighlight": "ホバーが表示されているワードの下を強調表示します。下にある装飾を隠さないために、色は不透過であってはなりません。", "hoverBackground": "エディター ホバーの背景色。", "hoverBorder": "エディター ホバーの境界線の色。", "activeLinkForeground": "アクティブなリンクの色。", @@ -76,12 +76,12 @@ "diffEditorRemoved": "削除されたテキストの背景色。", "diffEditorInsertedOutline": "挿入されたテキストの輪郭の色。", "diffEditorRemovedOutline": "削除されたテキストの輪郭の色。", - "mergeCurrentHeaderBackground": "行内マージ競合の現在のヘッダー背景色。", - "mergeCurrentContentBackground": "行内マージ競合の現在のコンテンツ背景色。", - "mergeIncomingHeaderBackground": "行内マージ競合の入力側ヘッダー背景色。", - "mergeIncomingContentBackground": "行内マージ競合の入力側コンテンツ背景色。", - "mergeCommonHeaderBackground": "行内マージ競合の共通の祖先ヘッダー背景色。", - "mergeCommonContentBackground": "行内マージ競合の共通の祖先コンテンツ背景色。", + "mergeCurrentHeaderBackground": "行内マージ競合の現在のヘッダー背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "mergeCurrentContentBackground": "行内マージ競合の現在のコンテンツ背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "mergeIncomingHeaderBackground": "行内マージ競合の入力側ヘッダー背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "mergeIncomingContentBackground": "行内マージ競合の入力側コンテンツ背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "mergeCommonHeaderBackground": "行内マージ競合の共通の祖先ヘッダー背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", + "mergeCommonContentBackground": "行内マージ競合の共通の祖先コンテンツ背景色。下にある装飾を隠さないために、色は不透過であってはなりません。", "mergeBorder": "行内マージ競合のヘッダーとスプリッターの境界線の色。", "overviewRulerCurrentContentForeground": "行内マージ競合の現在の概要ルーラー前景色。", "overviewRulerIncomingContentForeground": "行内マージ競合の入力側の概要ルーラー前景色。", diff --git a/i18n/jpn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/jpn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..9178423f0e4 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirearray": "ローカリゼーションは配列にする必要があります", + "requirestring": " `{0}` プロパティは必須で、`string` 型でなければなりません", + "optstring": "`{0}` プロパティは省略するか、`string` 型にする必要があります", + "vscode.extension.contributes.localizations": "ローカリゼーションをエディターに提供します", + "vscode.extension.contributes.localizations.languageId": "表示文字列が翻訳される言語の id。", + "vscode.extension.contributes.localizations.languageName": "表示文字列が翻訳される言語名。", + "vscode.extension.contributes.localizations.translations": "提供されている言語のすべての翻訳ファイルを含むフォルダへの相対パス。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..e4fd63e4462 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Save Participants が実行中です..." +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/jpn/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 74c5f0eabd7..ee062e8f6d2 100644 --- a/i18n/jpn/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/jpn/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "ID '{0}' のツリー ビューは登録されていません。", - "treeItem.notFound": "ID '{0}' のツリー項目は見つかりませんでした。", - "treeView.duplicateElement": " {0} 要素は既に登録されています。" + "treeView.duplicateElement": "id [0] の要素はすでに登録されています。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/jpn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 4faa6069b27..9196d2adf6f 100644 --- a/i18n/jpn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "サイド バーの位置の切り替え", + "toggleSidebarPosition": "サイド バーの位置の切り替え", "view": "表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 60ed1228f04..69c30877972 100644 --- a/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "ファイルを開く...", "openFolder": "フォルダーを開く...", "openFileFolder": "開く...", - "addFolderToWorkspace": "ワークスペースにフォルダーを追加...", - "add": "追加(&&A)", - "addFolderToWorkspaceTitle": "ワークスペースにフォルダーを追加", "globalRemoveFolderFromWorkspace": "ワークスペースからフォルダーを削除...", - "removeFolderFromWorkspace": "ワークスペースからフォルダーを削除", - "openFolderSettings": "フォルダーの設定を開く", "saveWorkspaceAsAction": "名前を付けてワークスペースを保存...", "save": "保存(&&S)", "saveWorkspace": "ワークスペースを保存", "openWorkspaceAction": "ワークスペースを開く...", "openWorkspaceConfigFile": "ワークスペースの構成ファイルを開く", - "openFolderAsWorkspaceInNewWindow": "新しいウィンドウでワークスペースとしてフォルダーを開く", - "workspaceFolderPickerPlaceholder": "ワークスペース フォルダーを選択" + "openFolderAsWorkspaceInNewWindow": "新しいウィンドウでワークスペースとしてフォルダーを開く" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/jpn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..d1d72afcab9 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "ワークスペースにフォルダーを追加...", + "add": "追加(&&A)", + "addFolderToWorkspaceTitle": "ワークスペースにフォルダーを追加", + "workspaceFolderPickerPlaceholder": "ワークスペース フォルダーを選択" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 86cc5cdfa14..ef30ff122d1 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "3 番目のグループのエディターを表示する", "allEditorsPicker": "開いているエディターをすべて表示する", "view": "表示", - "file": "ファイル" + "file": "ファイル", + "close": "閉じる", + "closeOthers": "その他を閉じる", + "closeRight": "右側を閉じる", + "closeAllUnmodified": "未変更を閉じる", + "closeAll": "すべて閉じる", + "keepOpen": "開いたままにする", + "toggleInlineView": "インライン表示に切り替え", + "showOpenedEditors": "開いているエディターを表示", + "keepEditor": "エディターを保持", + "closeEditorsInGroup": "グループ内のすべてのエディターを閉じる", + "closeUnmodifiedEditors": "グループ内の未変更のエディターを閉じる", + "closeOtherEditors": "その他のエディターを閉じる", + "closeRightEditors": "右側のエディターを閉じる" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 9e1f0ccd5c3..3d1749e2a39 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "エディターを閉じる", "revertAndCloseActiveEditor": "元に戻してエディターを閉じる", "closeEditorsToTheLeft": "左側のエディターを閉じる", - "closeEditorsToTheRight": "右側のエディターを閉じる", "closeAllEditors": "すべてのエディターを閉じる", - "closeUnmodifiedEditors": "グループ内の未変更のエディターを閉じる", "closeEditorsInOtherGroups": "他のグループ内のエディターを閉じる", - "closeOtherEditorsInGroup": "その他のエディターを閉じる", - "closeEditorsInGroup": "グループ内のすべてのエディターを閉じる", "moveActiveGroupLeft": "エディター グループを左側に移動する", "moveActiveGroupRight": "エディター グループを右側に移動する", "minimizeOtherEditorGroups": "他のエディター グループを最小化する", "evenEditorGroups": "エディター グループの幅を等間隔に設定する", "maximizeEditor": "エディター グループを最大化してサイドバーを非表示にする", - "keepEditor": "エディターを保持", "openNextEditor": "次のエディターを開く", "openPreviousEditor": "以前のエディターを開く", "nextEditorInGroup": "グループ内で次のエディターを開く", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "最初のグループのエディターを表示する", "showEditorsInSecondGroup": "2 番目のグループでエディターを表示する", "showEditorsInThirdGroup": "3 番目のグループのエディターを表示する", - "showEditorsInGroup": "エディターをグループに表示する", "showAllEditors": "すべてのエディターを表示する", "openPreviousRecentlyUsedEditorInGroup": "グループ内の最近使用したエディターのうち前のエディターを開く", "openNextRecentlyUsedEditorInGroup": "グループ内の最近使用したエディターのうち次のエディターを開く", @@ -54,5 +48,8 @@ "moveEditorLeft": "エディターを左へ移動", "moveEditorRight": "エディターを右へ移動", "moveEditorToPreviousGroup": "エディターを前のグループに移動", - "moveEditorToNextGroup": "エディターを次のグループに移動" + "moveEditorToNextGroup": "エディターを次のグループに移動", + "moveEditorToFirstGroup": "エディターを 1 番目のグループに移動", + "moveEditorToSecondGroup": "エディターを 2 番目のグループに移動", + "moveEditorToThirdGroup": "エディターを 3 番目のグループに移動" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 31949627cfd..faa2938621c 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "タブまたはグループ別にアクティブ エディターを移動する", "editorCommand.activeEditorMove.arg.name": "アクティブ エディターの Move 引数", - "editorCommand.activeEditorMove.arg.description": "引数プロパティ:\n\t* 'to': 移動先を指定する文字列値。\n\t* 'by': 移動の単位を指定する文字列値。タブ別またはグループ別。\n\t* 'value': 移動の位置数もしくは絶対位置を指定する数値。", - "commandDeprecated": "コマンド **{0}** は削除されました。代わりに **{1}** を使用できます", - "openKeybindings": "ショートカット キーの構成" + "editorCommand.activeEditorMove.arg.description": "引数プロパティ:\n\t* 'to': 移動先を指定する文字列値。\n\t* 'by': 移動の単位を指定する文字列値。タブ別またはグループ別。\n\t* 'value': 移動の位置数もしくは絶対位置を指定する数値。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index e5581c64d21..17ddb4365e0 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "テキスト ファイル比較エディター。", "navigate.next.label": "次の変更箇所", "navigate.prev.label": "前の変更箇所", - "inlineDiffLabel": "インライン表示に切り替え", - "sideBySideDiffLabel": "並べて表示に切り替え" + "toggleIgnoreTrimWhitespace.label": "末尾の空白文字のトリミングを無視する" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index c10bd2e7b60..f0f64f4f3ad 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "閉じる", - "closeOthers": "その他を閉じる", - "closeRight": "右側を閉じる", - "closeAll": "すべて閉じる", - "closeAllUnmodified": "未変更を閉じる", - "keepOpen": "開いたままにする", - "showOpenedEditors": "開いているエディターを表示", "araLabelEditorActions": "エディター操作" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 5c96f185104..2ac16cc30bc 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[サポート対象外]", + "userIsAdmin": "[管理者]", + "userIsSudo": "[スーパー ユーザー]", "devExtensionWindowTitlePrefix": "[拡張機能開発ホスト]" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/jpn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index 39d2dcfed3e..2c65d714079 100644 --- a/i18n/jpn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/jpn/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "サイド バーから非表示" + "hideView": "非表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/common/theme.i18n.json b/i18n/jpn/src/vs/workbench/common/theme.i18n.json index a296fd913c1..61bc140d9d3 100644 --- a/i18n/jpn/src/vs/workbench/common/theme.i18n.json +++ b/i18n/jpn/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "アクティブ タブの背景色。タブはエディター領域におけるエディターのコンテナーです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", "tabInactiveBackground": "非アクティブ タブの背景色。タブはエディター領域におけるエディターのコンテナーです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", + "tabHoverBackground": "ホバー時のタブの背景色。タブはエディター領域におけるエディターのコンテナです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", + "tabUnfocusedHoverBackground": "ホバー時のフォーカスされていないグループ内のタブの背景色。タブはエディター領域におけるエディターのコンテナです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", "tabBorder": "タブ同士を分けるための境界線。タブはエディター領域内にあるエディターのコンテナーです。複数のタブを 1 つのエディター グループで開くことができます。複数のエディター グループがある可能性があります。", "tabActiveBorder": "アクティブなタブを強調表示するための境界線。タブはエディター領域内にあるエディターのコンテナーです。複数のタブを 1 つのエディター グループで開くことができます。複数のエディター グループがある可能性があります。", "tabActiveUnfocusedBorder": "フォーカスされていないグループ内のアクティブ タブを強調表示するための境界線。タブはエディター領域内にあるエディターのコンテナーです。複数のタブを 1 つのエディター グループで開くことができます。複数のエディター グループがある可能性があります。", + "tabHoverBorder": "ホバー時のタブを強調表示するための境界線。タブはエディター領域内にあるエディターのコンテナーです。複数のタブを 1 つのエディター グループで開くことができます。複数のエディター グループがある可能性があります。", + "tabUnfocusedHoverBorder": "ホバー時のフォーカスされていないグループ内のタブを強調表示するための境界線。タブはエディター領域内にあるエディターのコンテナーです。複数のタブを 1 つのエディター グループで開くことができます。複数のエディター グループがある可能性があります。", "tabActiveForeground": "アクティブ グループ内のアクティブ タブの前景色。タブはエディター領域におけるエディターのコンテナーです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", "tabInactiveForeground": "アクティブ グループ内の非アクティブ タブの前景色。タブはエディター領域におけるエディターのコンテナーです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", "tabUnfocusedActiveForeground": "フォーカスされていないグループ内のアクティブ タブの前景色。タブはエディター領域におけるエディターのコンテナーです。1 つのエディター グループで複数のタブを開くことができます。エディター グループを複数にすることもできます。", @@ -16,7 +20,7 @@ "editorGroupBackground": "エディター グループの背景色。エディター グループはエディターのコンテナーです。背景色はエディター グループをドラッグすると表示されます。", "tabsContainerBackground": "タブが有効な場合の エディター グループ タイトル ヘッダーの背景色。エディター グループはエディターのコンテナーです。", "tabsContainerBorder": "タブが有効な場合の エディター グループ タイトル ヘッダーの境界線色。エディター グループはエディターのコンテナーです。", - "editorGroupHeaderBackground": "タブが無効な場合の エディター グループ タイトル ヘッダーの背景色。エディター グループはエディターのコンテナーです。", + "editorGroupHeaderBackground": "タブが無効な場合 (`\"workbench.editor.showTabs\": false`) のエディター グループ タイトル ヘッダーの背景色。エディター グループはエディターのコンテナーです。", "editorGroupBorder": "複数のエディター グループを互いに分離するための色。エディター グループはエディターのコンテナーです。", "editorDragAndDropBackground": "エディターの周囲をドラッグしているときの背景色。エディターのコンテンツが最後まで輝くために、色は透過である必要があります。", "panelBackground": "パネルの背景色。パネルはエディター領域の下に表示され、出力や統合ターミナルなどのビューを含みます。", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "フォルダーを開いていないときにサイドバーとエディターを隔てるワークスペースのステータス バーの境界線の色。ステータス バーはウィンドウの下部に表示されます。 ", "statusBarItemActiveBackground": "クリック時のステータス バーの項目の背景色。ステータス バーはウィンドウの下部に表示されます。", "statusBarItemHoverBackground": "ホバーしたときのステータス バーの項目の背景色。ステータス バーはウィンドウの下部に表示されます。", - "statusBarProminentItemBackground": "ステータス バーの重要な項目の背景色。重要な項目は、重要性を示すために他のステータスバーの項目から際立っています。 ステータス バーはウィンドウの下部に表示されます。", - "statusBarProminentItemHoverBackground": "ホバーしたときのステータス バーの重要な項目の背景色。重要な項目は、重要性を示すために他のステータスバーの項目から際立っています。 ステータス バーはウィンドウの下部に表示されます。", + "statusBarProminentItemBackground": "ステータスバーで目立たせる項目の背景色。この項目は、重要性を示すために他のエントリーより目立って表示されます。コマンドパレットから `Toggle Tab Key Moves Focus` に切り替えると例を見ることができます。ステータスバーはウィンドウの下部に表示されます。", + "statusBarProminentItemHoverBackground": "ホバー中のステータスバーで目立たせる項目の背景色。この項目は、重要性を示すために他のエントリーより目立って表示されます。コマンドパレットから `Toggle Tab Key Moves Focus` に切り替えると例を見ることができます。ステータスバーはウィンドウの下部に表示されます。", "activityBarBackground": "アクティビティ バーの背景色。アクティビティ バーは左端または右端に表示され、サイド バーのビューを切り替えることができます。", "activityBarForeground": "アクティビティ バーの前景色 (例: アイコンの色)。アクティビティ バーは左端または右端に表示され、サイド バーのビューを切り替えることができます。", "activityBarBorder": "サイド バーと隔てるアクティビティ バーの境界線色。アクティビティ バーは左端または右端に表示され、サイド バーのビューを切り替えることができます。", diff --git a/i18n/jpn/src/vs/workbench/common/views.i18n.json b/i18n/jpn/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..3607a9f498a --- /dev/null +++ b/i18n/jpn/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "location `{1}` で id `{0}` のビューが既に登録されています" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json index e4698109a33..2c9fa4def7f 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "エディターを閉じる", "closeWindow": "ウィンドウを閉じる", "closeWorkspace": "ワークスペースを閉じる", "noWorkspaceOpened": "このインスタンスで現在開いているワークスペースがないので、閉じられません。", @@ -30,6 +29,7 @@ "openRecent": "最近開いた項目…", "quickOpenRecent": "最近使用したものを開く...", "closeMessages": "通知メッセージを閉じる", + "openIssueReporter": "問題のレポーターを開く", "reportIssueInEnglish": "問題の報告", "reportPerformanceIssue": "パフォーマンスの問題のレポート", "keybindingsReference": "キーボード ショートカットの参照", @@ -52,21 +52,5 @@ "displayLanguage": "VSCode の表示言語を定義します。", "doc": "サポートされている言語の一覧については、{0} をご覧ください。", "restart": "値を変更するには VS Code の再起動が必要です。", - "fail.createSettings": "'{0}' ({1}) を作成できません。", - "openLogsFolder": "ログ フォルダーを開く", - "showLogs": "ログの表示...", - "mainProcess": "メイン", - "sharedProcess": "共有", - "rendererProcess": "レンダラー", - "extensionHost": "拡張機能ホスト", - "selectProcess": "プロセスの選択", - "setLogLevel": "ログ レベルの設定", - "trace": "トレース", - "debug": "デバッグ", - "info": "情報", - "warn": "警告", - "err": "エラー", - "critical": "重大", - "off": "オフ", - "selectLogLevel": "ログ レベルを選択" + "fail.createSettings": "'{0}' ({1}) を作成できません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json index 2f2b510b284..c0540ea9122 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "表示", "help": "ヘルプ", "file": "ファイル", - "developer": "開発者", "workspaces": "ワークスペース", + "developer": "開発者", + "workbenchConfigurationTitle": "ワークベンチ", "showEditorTabs": "開いているエディターをタブに表示するかどうかを制御します。", "workbench.editor.labelFormat.default": "ファイルの名前を表示します。タブが有効かつ 1 つのグループ内の 2 つの同名ファイルがあるときに各ファイルのパスの区切り記号が追加されます。タブを無効にすると、エディターがアクティブな時にワークスペース フォルダーの相対パスが表示されます。", "workbench.editor.labelFormat.short": "ディレクトリ名に続けてファイル名を表示します。", @@ -20,23 +21,23 @@ "showIcons": "開いているエディターをアイコンで表示するかどうかを制御します。これには、アイコンのテーマを有効にする必要もあります。", "enablePreview": "開かれるエディターをプレビューとして表示するかどうかを制御します。プレビュー エディターは (例: ダブル クリックまたは編集などによって) 変更される時まで再利用し、斜体で表示します。", "enablePreviewFromQuickOpen": "Quick Open で開いたエディターをプレビューとして表示するかどうかを制御します。プレビュー エディターは、保持されている間、再利用されます (ダブルクリックまたは編集などによって)。", + "closeOnFileDelete": "ファイルを表示しているエディターを、ファイルが削除されるかその他のプロセスによって名前を変更された場合に、自動的に閉じるかどうかを制御します。これを無効にすると、このような場合にエディターはダーティで開かれたままになります。アプリケーション内で削除すると、必ずエディターは閉じられ、ダーティ ファイルは閉じられることがなく、データは保存されませんのでご注意ください。", "editorOpenPositioning": "エディターを開く場所を制御します。'left' または 'right' を選択すると現在アクティブになっているエディターの左または右にエディターを開きます。'first' または 'last' を選択すると現在アクティブになっているエディターとは別個にエディターを開きます。", "revealIfOpen": "任意の表示グループが開かれた場合に、そこにエディターを表示するかどうかを制御します。無効にした場合、エディターは現在のアクティブなエディター グループに優先して開かれます。有効にした場合は、現在のアクティブなエディター グループにもう一度開くのではなく、既に開いているエディターが表示されます。特定のグループ内や現在アクティブなグループの横に強制的にエディターを開いた場合などに、この設定が無視される場合もあることにご注意ください。", + "swipeToNavigate": "3 本の指で横方向にスワイプすると、開いているファイル間を移動できます。", "commandHistory": "コマンド パレットで最近使用したコマンド履歴を保持する数を制御します。0 に設定するとコマンド履歴を無効にします。", "preserveInput": "次回開いたとき、コマンド パレットの最後の入力を復元するかどうかを制御します。", "closeOnFocusLost": "フォーカスを失ったときに Quick Open を自動的に閉じるかどうかを制御します。", "openDefaultSettings": "設定を開くとすべての既定の設定を表示するエディターも開くかどうかを制御します。", "sideBarLocation": "サイド バーの位置を制御します。ワークベンチの左右のいずれかに表示できます。", + "panelDefaultLocation": "パネルの既定の位置を制御します。ワークベンチの下部または右のいずれかに表示できます。", "statusBarVisibility": "ワークベンチの下部にステータス バーを表示するかどうかを制御します。", "activityBarVisibility": "ワークベンチでのアクティビティ バーの表示をコントロールします。", - "closeOnFileDelete": "ファイルを表示しているエディターを、ファイルが削除されるかその他のプロセスによって名前を変更された場合に、自動的に閉じるかどうかを制御します。これを無効にすると、このような場合にエディターはダーティで開かれたままになります。アプリケーション内で削除すると、必ずエディターは閉じられ、ダーティ ファイルは閉じられることがなく、データは保存されませんのでご注意ください。", - "enableNaturalLanguageSettingsSearch": "設定で自然文検索モードを有効にするかどうかを制御します。", "fontAliasing": "ワークベンチのフォント エイリアシング方法を制御します。\n- default: サブピクセル方式でフォントを滑らかにします。ほとんどの非 Retina ディスプレイでもっとも鮮明なテキストを提供します\n- antialiased: サブピクセルとは対照的に、ピクセルのレベルでフォントを滑らかにします。フォント全体がより細く見えます\n- none: フォントのスムージングを無効にします。テキストをぎざぎざな尖ったエッジで表示します", "workbench.fontAliasing.default": "サブピクセル方式でフォントを滑らかにします。ほとんどの非 Retina ディスプレイでもっとも鮮明なテキストを提供します。", "workbench.fontAliasing.antialiased": "サブピクセルとは対照的に、ピクセルのレベルでフォントを滑らかにします。フォント全体がより細く見えるようになります。", "workbench.fontAliasing.none": "フォントのスムージングを無効にします。テキストをぎざぎざな尖ったエッジで表示します。", - "swipeToNavigate": "3 本の指で横方向にスワイプすると、開いているファイル間を移動できます。", - "workbenchConfigurationTitle": "ワークベンチ", + "enableNaturalLanguageSettingsSearch": "設定で自然文検索モードを有効にするかどうかを制御します。", "windowConfigurationTitle": "ウィンドウ", "window.openFilesInNewWindow.on": "新しいウィンドウでファイルを開きます", "window.openFilesInNewWindow.off": "ファイルのフォルダーが開かれていたウィンドウまたは最後のアクティブ ウィンドウでファイルを開きます", diff --git a/i18n/jpn/src/vs/workbench/electron-browser/window.i18n.json b/i18n/jpn/src/vs/workbench/electron-browser/window.i18n.json index 0813ed28598..b9e99cd4528 100644 --- a/i18n/jpn/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/jpn/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "切り取り", "copy": "コピー", "paste": "貼り付け", - "selectAll": "すべて選択" + "selectAll": "すべて選択", + "runningAsRoot": "{0} をルート ユーザーとして実行しないことを推奨します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json b/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json index 1c53dd86bdd..f1f6fe1ec7d 100644 --- a/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/accessibility.i18n.json @@ -22,5 +22,5 @@ "openDocMac": "command + H キーを押して、ブラウザー ウィンドウを今すぐ開き、アクセシビリティに関連する他の VS Code 情報を確認します。", "openDocWinLinux": "Ctrl + H キーを押して、ブラウザー ウィンドウを今すぐ開き、アクセシビリティに関連する他の VS Code 情報を確認します。", "outroMsg": "Esc キー か Shift+Esc を押すと、ヒントを消してエディターに戻ることができます。", - "ShowAccessibilityHelpAction": "アクセシビリティのヘルプを表示します" + "ShowAccessibilityHelpAction": "アクセシビリティのヘルプを表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.i18n.json b/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.i18n.json index 3b84ee3fdb4..ec3d813e1dc 100644 --- a/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "マルチ カーソルの修飾キーを切り替える" + "toggleLocation": "マルチカーソル修飾子の切り替え" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json index 57ba460378d..bf61b86ff83 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActions.i18n.json @@ -5,7 +5,7 @@ // Do not edit this file. It is machine generated. { "openLaunchJson": "{0} を開く", - "launchJsonNeedsConfigurtion": "'launch.json' を構成または修正してください", + "launchJsonNeedsConfigurtion": "'launch.json' の構成や修正", "noFolderDebugConfig": "高度なデバッグ構成を行うには、最初にフォルダーを開いてください。", "startDebug": "デバッグの開始", "startWithoutDebugging": "デバッグなしで開始", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index 8876044c17e..00d3b5a76c0 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "デバッグ ツール バーの背景色。" + "debugToolBarBackground": "デバッグ ツール バーの背景色。", + "debugToolBarBorder": "デバッグ ツール バーの境界線色。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json index f9530ecfb90..76d3254c4eb 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/browser/debugQuickOpen.i18n.json @@ -6,7 +6,7 @@ { "entryAriaLabel": "{0}、デバッグ", "debugAriaLabel": "実行する起動構成の名前を入力してください。", - "addConfigTo": "設定 ({0}) の追加 ...", + "addConfigTo": "構成 ({0}) の追加...", "addConfiguration": "構成の追加...", "noConfigurationsMatching": "一致するデバッグ構成はありません", "noConfigurationsFound": "デバッグ構成が見つかりません。'launch.json' ファイルを作成してください。" diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 84777c482b2..ac2caf3a825 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,8 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json' を検証するための JSON スキーマ構成。", "vscode.extension.contributes.debuggers.windows": "Windows 固有の設定。", "vscode.extension.contributes.debuggers.windows.runtime": "Windows で使用されるランタイム。", - "vscode.extension.contributes.debuggers.osx": "OS X 固有の設定。", - "vscode.extension.contributes.debuggers.osx.runtime": "OSX で使用されるランタイム。", + "vscode.extension.contributes.debuggers.osx": "macOS 固有の設定。", + "vscode.extension.contributes.debuggers.osx.runtime": "macOS で使用されるランタイム。", "vscode.extension.contributes.debuggers.linux": "Linux 固有の設定。", "vscode.extension.contributes.debuggers.linux.runtime": "Linux で使用されるランタイム。", "vscode.extension.contributes.breakpoints": "ブレークポイントを提供します。", diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/repl.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/repl.i18n.json index 3b2b57ca85d..010c65f0dc8 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/repl.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/repl.i18n.json @@ -8,5 +8,5 @@ "actions.repl.historyPrevious": "前の履歴", "actions.repl.historyNext": "次の履歴", "actions.repl.acceptInput": "REPL での入力を反映", - "actions.repl.copyAll": "デバッグ: コンソールをすべてコピーする" + "actions.repl.copyAll": "デバッグ: コンソールをすべてコピー" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 248289a591a..af2aec81915 100644 --- a/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "デバッグ対象", - "debug.terminal.not.available.error": "統合ターミナルを使用できません" + "debug.terminal.title": "デバッグ対象" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 2a9f118d084..ecb730ce4d3 100644 --- a/i18n/jpn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "新しいコマンド プロンプトを開く", "globalConsoleActionMacLinux": "新しいターミナルを開く", "scopedConsoleActionWin": "コマンド プロンプトで開く", - "scopedConsoleActionMacLinux": "ターミナルで開く", - "openFolderInIntegratedTerminal": "ターミナルで開く" + "scopedConsoleActionMacLinux": "ターミナルで開く" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index c381b702335..66ecd5fbfca 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "最近開いたファイルに基づいてこの拡張機能が推奨されます。", + "neverShowAgain": "今後は表示しない", + "close": "閉じる", "workspaceRecommendation": "現在のワークスペースのユーザーによってこの拡張機能が推奨されています。", + "fileBasedRecommendation": "最近開いたファイルに基づいてこの拡張機能が推奨されます。", "exeBasedRecommendation": "{0} がインストールされているため、この拡張機能を推奨します。", "reallyRecommended2": "このファイルの種類には拡張機能 '{0}' が推奨されます。", "reallyRecommendedExtensionPack": "このファイルの種類には拡張機能パック '{0}' が推奨されます。", "showRecommendations": "推奨事項を表示", "install": "インストール", - "neverShowAgain": "今後は表示しない", - "close": "閉じる", + "showLanguageExtensions": "'.{0}' ファイルに役立つ拡張機能が Marketplace にあります", + "searchMarketplace": "Marketplace を検索", "workspaceRecommended": "このワークスペースには拡張機能の推奨事項があります。", "installAll": "すべてインストール", "ignoreExtensionRecommendations": "すべての拡張機能の推奨事項を無視しますか?", diff --git a/i18n/jpn/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/jpn/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index eb5578bf82e..e3313b2824f 100644 --- a/i18n/jpn/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "VSIX から拡張機能をインストールしています...", + "installingMarketPlaceExtension": "マーケット プレースから拡張機能をインストールしています... ", + "uninstallingExtension": "拡張機能をアンインストールしています...", "enableDependeciesConfirmation": "'{0}' を有効にするとその依存関係も有効になります。続行しますか?", "enable": "はい", "doNotEnable": "いいえ", diff --git a/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..78d76e265f4 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "ワークベンチ", + "feedbackVisibility": "ワークベンチ下部にあるステータス バーで Twitter のフィードバック (スマイル) を表示するかどうかを制御します。" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index ba6b165a86a..8f7ff5b2b6f 100644 --- a/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "欠落している機能を要求する", "tell us why?": "理由をお知らせください", "commentsHeader": "コメント", + "showFeedback": "ステータス バーにフィードバックの笑顔文字を表示", "tweet": "ツイートする", "character left": "文字入力可", "characters left": "文字入力可", diff --git a/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..e31810d983c --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "非表示" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 76306159955..cea92a2d16e 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "ファイル", "revealInSideBar": "サイド バーに表示", "acceptLocalChanges": "変更を使用してディスクの内容を上書き", - "revertLocalChanges": "変更を破棄してディスク上の内容に戻る" + "revertLocalChanges": "変更を破棄してディスク上の内容に戻る", + "copyPathOfActive": "アクティブ ファイルのパスのコピー", + "saveAllInGroup": "グループ内のすべてを保存する", + "saveFiles": "すべてのファイルを保存", + "revert": "ファイルを元に戻す", + "compareActiveWithSaved": "保存済みファイルと作業中のファイルを比較", + "closeEditor": "エディターを閉じる", + "view": "表示", + "openToSide": "横に並べて開く", + "revealInWindows": "エクスプローラーで表示", + "revealInMac": "Finder で表示します", + "openContainer": "このアイテムのフォルダーを開く", + "copyPath": "パスのコピー", + "saveAll": "すべて保存", + "compareWithSaved": "保存済みと比較", + "compareWithSelected": "選択項目と比較", + "compareSource": "比較対象の選択", + "compareSelected": "選択項目の比較", + "close": "閉じる", + "closeOthers": "その他を閉じる", + "closeUnmodified": "未変更を閉じる", + "closeAll": "すべて閉じる", + "deleteFile": "完全に削除" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 2ef009f9c59..7754a978dc6 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "再試行", - "rename": "名前変更", "newFile": "新しいファイル", "newFolder": "新しいフォルダー", + "rename": "名前変更", + "delete": "削除", + "copyFile": "コピー", + "pasteFile": "貼り付け", + "retry": "再試行", "openFolderFirst": "フォルダー内にファイルやフォルダーを作成するには、フォルダーをまず開く必要があります。", "newUntitledFile": "無題の新規ファイル", "createNewFile": "新しいファイル", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "ごみ箱に移動(&&M)", "deleteButtonLabelTrash": "ゴミ箱に移動(&&M)", "deleteButtonLabel": "削除(&&D)", + "dirtyMessageFilesDelete": "保存されていない変更があるファイルを削除します。続行しますか?", "dirtyMessageFolderOneDelete": "保存されていない変更がある 1 個のファイルを含むフォルダーを削除します。続行しますか?", "dirtyMessageFolderDelete": "保存されていない変更があるファイルを {0} 個含むフォルダーを削除します。続行しますか?", "dirtyMessageFileDelete": "保存されていない変更があるファイルを削除します。続行しますか?", "dirtyWarning": "保存しないと変更内容が失われます。", + "confirmMoveTrashMessageMultiple": "次の {0} 個のファイルを削除してもよろしいですか?", "confirmMoveTrashMessageFolder": "'{0}' とその内容を削除しますか?", "confirmMoveTrashMessageFile": "'{0}' を削除しますか?", "undoBin": "ごみ箱から復元できます。", "undoTrash": "ゴミ箱から復元できます。", "doNotAskAgain": "再度表示しない", + "confirmDeleteMessageMultiple": "次の {0} 個のファイルを完全に削除してもよろしいですか?", "confirmDeleteMessageFolder": "'{0}' とその内容を完全に削除してもよろしいですか?", "confirmDeleteMessageFile": "'{0}' を完全に削除してもよろしいですか?", "irreversible": "このアクションは元に戻すことができません。", "permDelete": "完全に削除", - "delete": "削除", "importFiles": "ファイルのインポート", "confirmOverwrite": "保存先のフォルダーに同じ名前のファイルまたはフォルダーが既に存在します。置き換えてもよろしいですか?", "replaceButtonLabel": "置換(&&R)", - "copyFile": "コピー", - "pasteFile": "貼り付け", + "fileDeleted": "ファイルは削除されたか移動されています", + "fileIsAncestor": "コピーするファイルがコピー先フォルダの上位にあります", "duplicateFile": "重複", - "openToSide": "横に並べて開く", - "compareSource": "比較対象の選択", "globalCompareFile": "アクティブ ファイルを比較しています...", "openFileToCompare": "まずファイルを開いてから別のファイルと比較してください", - "compareWith": "'{0}' と '{1}' を比較", - "compareFiles": "ファイルの比較", "refresh": "最新の情報に更新", - "save": "保存", - "saveAs": "名前を付けて保存...", - "saveAll": "すべて保存", "saveAllInGroup": "グループ内のすべてを保存する", - "saveFiles": "すべてのファイルを保存", - "revert": "ファイルを元に戻す", "focusOpenEditors": "開いているエディターのビューにフォーカスする", "focusFilesExplorer": "ファイル エクスプローラーにフォーカスを置く", "showInExplorer": "アクティブ ファイルをサイド バーに表示", @@ -56,20 +52,11 @@ "refreshExplorer": "エクスプローラーを最新表示する", "openFileInNewWindow": "新しいウィンドウでアクティブ ファイルを開く", "openFileToShowInNewWindow": "まずファイルを開いてから新しいウィンドウで開きます", - "revealInWindows": "エクスプローラーで表示", - "revealInMac": "Finder で表示します", - "openContainer": "このアイテムのフォルダーを開く", - "revealActiveFileInWindows": "Windows エクスプローラーでアクティブ ファイルを表示する", - "revealActiveFileInMac": "Finder でアクティブ ファイルを表示する", - "openActiveFileContainer": "アクティブ ファイルを含んでいるフォルダーを開く", "copyPath": "パスのコピー", - "copyPathOfActive": "アクティブ ファイルのパスのコピー", "emptyFileNameError": "ファイルまたはフォルダーの名前を指定する必要があります。", "fileNameExistsError": "**{0}** というファイルまたはフォルダーはこの場所に既に存在します。別の名前を指定してください。", "invalidFileNameError": "名前 **{0}** がファイル名またはフォルダー名として無効です。別の名前を指定してください。", "filePathTooLongError": "名前 **{0}** のパスが長すぎます。名前を短くしてください。", - "compareWithSaved": "保存済みファイルと作業中のファイルを比較", - "modifiedLabel": "{0} (ローカル) ↔ {1}", "compareWithClipboard": "クリップボードとアクティブ ファイルを比較", "clipboardComparisonLabel": "クリップボード ↔ {0}" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index 4f2a963e359..108a656a68a 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "まずファイルを開いてからそのパスをコピーします", - "openFileToReveal": "まずファイルを開いてから表示します" + "revealInWindows": "エクスプローラーで表示", + "revealInMac": "Finder で表示します", + "openContainer": "このアイテムのフォルダーを開く", + "saveAs": "名前を付けて保存...", + "save": "保存", + "saveAll": "すべて保存", + "removeFolderFromWorkspace": "ワークスペースからフォルダーを削除", + "genericRevertError": "元へ戻すことに失敗しました '{0}': {1}", + "modifiedLabel": "{0} (ローカル) ↔ {1}", + "openFileToReveal": "まずファイルを開いてから表示します", + "openFileToCopy": "まずファイルを開いてからそのパスをコピーします" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 5461c0b3fa9..811c013e55b 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "エディター", "formatOnSave": "ファイルを保存するときにフォーマットしてください。フォーマッタを使用可能にして、ファイルを自動保存せず、エディターをシャットダウンしないでください。", "explorerConfigurationTitle": "エクスプローラー", - "openEditorsVisible": "[開いているエディター] ウィンドウに表示されているエディターの数。0 に設定するとウィンドウが非表示になります。", - "dynamicHeight": "開いているエディターのセクションの高さを要素の数に合わせて動的に調整するかどうかを制御します。", + "openEditorsVisible": "[開いているエディター] ウィンドウに表示するエディターの数。", "autoReveal": "エクスプローラーでファイルを開くとき、自動的にファイルの内容を表示して選択するかどうかを制御します。", "enableDragAndDrop": "ドラッグ アンド ドロップを使用したファイルとフォルダーの移動をエクスプローラーが許可するかどうかを制御します。", "confirmDragAndDrop": "ドラッグ アンド ドロップを使用したファイルやフォルダーの移動時にエクスプローラーが確認を求めるかどうかを制御します。", diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index a11f1cb6ffc..e3aeaafe4e7 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "右側のエディター ツール バーの操作で、変更を [元に戻す] か、ディスクの内容を変更内容で [上書き] します", - "discard": "破棄", + "overwriteElevated": "管理者権限で上書き...", + "saveElevated": "管理者権限で再試行...", "overwrite": "上書き", "retry": "再試行", - "readonlySaveError": "'{0}' の保存に失敗しました。ファイルが書き込み禁止になっています。[上書き] を選択して保護を解除してください。", + "discard": "破棄", + "readonlySaveErrorAdmin": "'{0}' の保存に失敗しました。ファイルが書き込み禁止になっています。[管理者権限で上書き] を選択して管理者として再試行してください。", + "readonlySaveError": "'{0}' の保存に失敗しました。ファイルが書き込み禁止になっています。[上書き] を選択して保護の解除を試してください。", + "permissionDeniedSaveError": "'{0}' の保存に失敗しました。十分な権限がありません。[管理者権限で再試行] を選択して管理者として再試行してください。", "genericSaveError": "'{0}' の保存に失敗しました: {1}", "staleSaveError": "'{0} の保存に失敗しました。ディスクの内容の方が新しくなっています。[比較] をクリックしてご使用のバージョンをディスク上のバージョンと比較してください。", "compareChanges": "比較", diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index f9c3565a125..3b5ce0838f3 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,6 +10,7 @@ "dropFolder": "ワークスペースにフォルダーを追加しますか?", "addFolders": "フォルダーの追加(&&A)", "addFolder": "フォルダーの追加(&&A)", + "confirmMultiMove": "次の {0} 個のファイルを移動してもよろしいですか?", "confirmMove": "'{0}' を移動しますか?", "doNotAskAgain": "再度表示しない", "moveButtonLabel": "移動(&&M)", diff --git a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index b798b662ed0..95dfcf4fae9 100644 --- a/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "開いているエディター", "openEditosrSection": "[開いているエディター] セクション", - "dirtyCounter": "未保存 ({0})", - "saveAll": "すべて保存", - "closeAllUnmodified": "未変更を閉じる", - "closeAll": "すべて閉じる", - "compareWithSaved": "保存済みと比較", - "close": "閉じる", - "closeOthers": "その他を閉じる" + "dirtyCounter": "未保存 ({0})" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..f95880fcc36 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "ログ (メイン)", + "sharedLog": "ログ (共有)", + "rendererLog": "ログ (ウィンドウ)", + "extensionsLog": "ログ (拡張機能ホスト)", + "developer": "開発者" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..861a564f2de --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "ログ フォルダーを開く", + "showLogs": "ログの表示...", + "mainProcess": "メイン", + "sharedProcess": "共有", + "rendererProcess": "ウィンドウ", + "extensionHost": "拡張機能ホスト", + "selectProcess": "プロセスの選択", + "openLogFile": "ログ ファイルを開く...", + "setLogLevel": "ログ レベルの設定", + "trace": "トレース", + "debug": "デバッグ", + "info": "情報", + "warn": "警告", + "err": "エラー", + "critical": "重大", + "off": "オフ", + "selectLogLevel": "ログ レベルを選択" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/jpn/src/vs/workbench/parts/markers/common/messages.i18n.json index efe22d017f6..0c951e42e75 100644 --- a/i18n/jpn/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,13 +5,13 @@ // Do not edit this file. It is machine generated. { "viewCategory": "表示", - "problems.view.toggle.label": "問題の切り替え", - "problems.view.focus.label": "問題にフォーカス", + "problems.view.toggle.label": "問題 (エラー、警告、情報) の切り替え", + "problems.view.focus.label": "問題 (エラー、警告、情報) にフォーカス", "problems.panel.configuration.title": "問題ビュー", "problems.panel.configuration.autoreveal": "ファイルを開くときに問題ビューに自動的にそのファイルを表示するかどうかを制御します", "markers.panel.title.problems": "問題", "markers.panel.aria.label.problems.tree": "ファイル別にグループ化した問題", - "markers.panel.no.problems.build": "現時点で問題はワークスペースで検出されていません。", + "markers.panel.no.problems.build": "現時点でワークスペースの問題は検出されていません。", "markers.panel.no.problems.filters": "指定されたフィルター条件による結果はありません", "markers.panel.action.filter": "問題のフィルター処理", "markers.panel.filter.placeholder": "種類またはテキストでフィルター処理", diff --git a/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..57deadb1a55 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "出力", + "logViewer": "ログ ビューアー", + "viewCategory": "表示", + "clearOutput.label": "出力のクリア" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..8f00064048d --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - 出力", + "channel": "'{0}' の出力チャネル" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingWidgets.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingWidgets.i18n.json index efdc6c41cac..99ba1fc8808 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingWidgets.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingWidgets.i18n.json @@ -5,5 +5,5 @@ // Do not edit this file. It is machine generated. { "defineKeybinding.initial": "任意のキーの組み合わせを押し、ENTER キーを押します。", - "defineKeybinding.chordsTo": "次へのコード:" + "defineKeybinding.chordsTo": "の次に" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index d963a2915fe..c440e97085d 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -17,6 +17,7 @@ "resetLabel": "キー バインドのリセット", "showConflictsLabel": "競合の表示", "copyLabel": "コピー", + "copyCommandLabel": "コピー コマンド", "error": "キー バインドの編集中にエラー '{0}' が発生しました。'keybindings.json' ファイルを開いてご確認ください。", "command": "コマンド", "keybinding": "キー バインド", @@ -31,6 +32,6 @@ "keybindingAriaLabel": "キー バインドは {0} です。", "noKeybinding": "キー バインドが割り当てられていません。", "sourceAriaLabel": "ソースは {0} です。", - "whenAriaLabel": "時間は {0} です。", - "noWhen": "時間コンテキストがありません。" + "whenAriaLabel": "タイミングは {0} です。", + "noWhen": "タイミングのコンテキストがありません。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index dacdf6ccd9d..00efa778c91 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 つの設定が一致します", "settingsFound": "{0} 個の設定が一致します", "totalSettingsMessage": "合計 {0} 個の設定", + "nlpResult": "自然文 (natural language) の結果", + "filterResult": "フィルター後の結果", "defaultSettings": "既定の設定", "defaultFolderSettings": "既定のフォルダー設定", "defaultEditorReadonly": "既定値を上書きするには、右側のエディターを編集します。", diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index dbb463d1324..05635b7c0f4 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "自然文検索 (natural language search) を試し下さい!", "defaultSettings": "上書きするには、右側のエディターに設定を入力します。", "noSettingsFound": "設定が見つかりません。", "settingsSwitcherBarAriaLabel": "設定切り替え", "userSettings": "ユーザー設定", "workspaceSettings": "ワークスペースの設定", - "folderSettings": "フォルダーの設定", - "enableFuzzySearch": "自然文検索を有効にする" + "folderSettings": "フォルダーの設定" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/jpn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index a99b14b8dd8..f28c0310389 100644 --- a/i18n/jpn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "よく使用するもの", - "mostRelevant": "最も関連性の高い", "defaultKeybindingsHeader": "キー バインド ファイル内にキー バインドを挿入して、キー バインドを上書きします。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 63217f20e3e..932be0b6bfa 100644 --- a/i18n/jpn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "表示", "commandsHandlerDescriptionDefault": "コマンドの表示と実行", "gotoLineDescriptionMac": "行へ移動", "gotoLineDescriptionWin": "行へ移動", diff --git a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index b650b0b0eb3..84c7c41eb09 100644 --- a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "Git を表示", "source control": "ソース管理", "toggleSCMViewlet": "SCM を表示", - "view": "表示" + "view": "表示", + "scmConfigurationTitle": "SCM", + "alwaysShowProviders": "ソース管理プロバイダーのセクションを常に表示するかどうか。", + "diffDecorations": "エディターの差分デコレーターを制御します。", + "inputCounter": "入力文字のカウントをいつ表示するかを制御します。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index 2cd7ee76d8f..58ba9f785fc 100644 --- a/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "ソース管理プロバイダー", "hideRepository": "非表示", + "commitMessageInfo": "現在の行に {0}  文字", + "commitMessageCountdown": "現在の行で残り {0} 文字", + "commitMessageWarning": "現在の行で {1} から {0} 文字オーバー", "installAdditionalSCMProviders": "その他の SCM プロバイダーをインストール...", "no open repo": "有効なソース管理プロバイダーがありません。", "source control": "ソース管理", diff --git a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json index d07e4c94a3f..eeb352c7ca2 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "前の検索語句を表示", "showSearchViewlet": "検索の表示", "findInFiles": "フォルダーを指定して検索", - "findInFilesWithSelectedText": "選択したテキストを含むファイルを検索", "replaceInFiles": "複数のファイルで置換", - "replaceInFilesWithSelectedText": "選択したテキストを含むファイルの置換", "RefreshAction.label": "最新の情報に更新", "CollapseDeepestExpandedLevelAction.label": "すべて折りたたむ", "ClearSearchResultsAction.label": "クリア", diff --git a/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index e266c4b0298..0a9eaace998 100644 --- a/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "フォルダー内を検索...", + "findInWorkspace": "ワークスペース内を検索...", "showTriggerActions": "ワークスペース内のシンボルへ移動...", "name": "検索", "search": "検索", + "showSearchViewlet": "検索の表示", "view": "表示", + "findInFiles": "フォルダーを指定して検索", "openAnythingHandlerDescription": "ファイルに移動する", "openSymbolDescriptionNormal": "ワークスペース内のシンボルへ移動", - "searchOutputChannelTitle": "検索", "searchConfigurationTitle": "検索", "exclude": "検索でファイルとフォルダーを除外するために glob パターンを構成します。files.exclude 設定からすべての glob パターンを継承します。", "exclude.boolean": "ファイル パスの照合基準となる glob パターン。これを true または false に設定すると、パターンがそれぞれ有効/無効になります。", @@ -18,5 +21,6 @@ "useRipgrep": "テキストとファイル検索で ripgrep を使用するかどうかを制御します", "useIgnoreFiles": "ファイルを検索するときに、.gitignore ファイルを使用するか .ignore ファイルを使用するかを制御します。", "search.quickOpen.includeSymbols": "グローバル シンボル検索の結果を、Quick Open の結果ファイルに含めるように構成します。", - "search.followSymlinks": "検索中にシンボリック リンクをたどるかどうかを制御します。" + "search.followSymlinks": "検索中にシンボリック リンクをたどるかどうかを制御します。", + "search.smartCase": "すべて小文字のパターンの場合、大文字と小文字を区別しないで検索し、そうでない場合は大文字と小文字を区別して検索する" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..9f9a7171140 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.scope": "(グローバル)", + "global.1": "({0})", + "new.global": "新しいグローバル スニペット ファイル...", + "group.global": "既存のスニペット", + "new.global.sep": "新しいスニペット", + "openSnippet.pickLanguage": "スニペット ファイルの選択もしくはスニペットの作成", + "openSnippet.label": "ユーザー スニペットの構成", + "preferences": "基本設定" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 72cf35b045c..f4559520bc0 100644 --- a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "スニペットの言語を選択", - "openSnippet.errorOnCreate": "{0} を作成できません", - "openSnippet.label": "ユーザー スニペットを開く", - "preferences": "基本設定", "snippetSchema.json.default": "空のスニペット", "snippetSchema.json": "ユーザー スニペット構成", "snippetSchema.json.prefix": "intellisense でスニペットを選択するときに使用するプレフィックス", "snippetSchema.json.body": "スニペットのコンテンツです。カーソルの位置を定義するには '$1', '${1:defaultText}' を使用し、最後のカーソルの位置には '$0' を使用します。'${varName}' と '${varName:defaultText}' を使用すると変数値を挿入します。例: 'This is file: $TM_FILENAME'.", - "snippetSchema.json.description": "スニペットについての記述。" + "snippetSchema.json.description": "スニペットについての記述。", + "snippetSchema.json.scope": "このスニペットを適用する言語名のリスト。例: 'typescript,javascript'。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..6528c4a5c72 --- /dev/null +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "ユーザー スニペット" +} \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 247f01f3cea..8d9acf90cf1 100644 --- a/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "`contributes.{0}.language` で不明な言語です。提供された値: {1}", "invalid.path.0": "`contributes.{0}.path` に文字列が必要です。提供された値: {1}", + "invalid.language.0": "言語を省略するとき、`contributes.{0}.path` の値は `.code-snippets`-file にする必要があります。提供された値: {1}", + "invalid.language": "`contributes.{0}.language` で不明な言語です。提供された値: {1}", "invalid.path.1": "拡張機能のフォルダー ({2}) の中に `contributes.{0}.path` ({1}) が含まれている必要があります。これにより拡張を移植できなくなる可能性があります。", "vscode.extension.contributes.snippets": "スニペットを提供します。", "vscode.extension.contributes.snippets-language": "このスニペットの提供先の言語識別子です。", "vscode.extension.contributes.snippets-path": "スニペット ファイルのパス。拡張機能フォルダーの相対パスであり、通常 './snippets/' で始まります。", "badVariableUse": "拡張機能 '{0}' の 1 つまたは複数のスニペットは、スニペット変数とスニペット プレース ホルダーを混乱させる可能性が非常にあります。 (詳細については、 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax を参照してください)", "badFile": "スニペット ファイル \"{0}\" を読み込むことができませんでした。", - "source.snippet": "ユーザー スニペット", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index 76dbf9d84f0..e264431a00f 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -13,7 +13,9 @@ "terminal.integrated.shellArgs.osx": "OS X 端末で使用するコマンド ライン引数。", "terminal.integrated.shell.windows": "Windows でターミナルが使用するシェルのパス。 Windows に同梱されているシェルを使用する場合 (cmd、PowerShell、または Bash on Ubuntu) 。", "terminal.integrated.shellArgs.windows": "Windows ターミナル上の場合に使用されるコマンド ライン引数。", + "terminal.integrated.macOptionIsMeta": "macOS のターミナルでは、オプション キーをメタ キーとして扱います。", "terminal.integrated.rightClickCopyPaste": "設定している場合、ターミナル内で右クリックしたときにコンテキスト メニューを表示させず、選択範囲がある場合はコピー、選択範囲がない場合は貼り付けの操作を行います。", + "terminal.integrated.copyOnSelection": "設定した場合、ターミナルで選択しているテキストはクリップボードにコピーされます。", "terminal.integrated.fontFamily": "端末のフォント ファミリを制御します。既定値は editor.fontFamily になります。", "terminal.integrated.fontSize": "ターミナルのフォント サイズをピクセル単位で制御します。", "terminal.integrated.lineHeight": "ターミナルの行の高さを制御します。この数値にターミナルのフォント サイズを乗算すると、実際の行の高さ (ピクセル単位) になります。", @@ -24,10 +26,12 @@ "terminal.integrated.setLocaleVariables": "ターミナルの開始時にロケール変数を設定するかどうかを制御します。OS X では既定で true になり、その他のプラットフォームでは false です。", "terminal.integrated.cwd": "端末を起動する明示的な開始パスです。これはシェル プロセスの現在の作業ディレクトリ (cwd) として使用されます。特にルート ディレクトリが cwd に適していない場合に、ワークスペースの設定で役立ちます。", "terminal.integrated.confirmOnExit": "アクティブなターミナル セッションがある場合に終了の確認をするかどうか。", + "terminal.integrated.enableBell": "ターミナルのベルが有効かどうか。", "terminal.integrated.commandsToSkipShell": "キーバインドがシェルに送信されず、代わりに常に Code で処理されるコマンド ID のセット。これにより、ターミナルがフォーカスされていない場合と同じ動作をするシェルによって通常使用されるキーバインドを使用できるようになります。例: Ctrl+p で Quick Open を起動します。", "terminal.integrated.env.osx": "OS X のターミナルで使用される VS Code のプロセスに追加される環境変数を持つオブジェクト", "terminal.integrated.env.linux": "Linux のターミナルで使用される VS Code のプロセスに追加される環境変数を持つオブジェクト", "terminal.integrated.env.windows": "Windows のターミナルで使用される VS Code のプロセスに追加される環境変数を持つオブジェクト", + "terminal.integrated.showExitAlert": "0 以外の終了コードのとき `終了コードを伴ってターミナルの処理が終了しました` と警告を表示します。", "terminalCategory": "ターミナル", "viewCategory": "表示" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 6015fb400ae..dfb2ffeb9e2 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -12,8 +12,11 @@ "workbench.action.terminal.selectAll": "すべて選択", "workbench.action.terminal.deleteWordLeft": "左の文字を削除", "workbench.action.terminal.deleteWordRight": "右の文字を削除", + "workbench.action.terminal.enterLineNavigationMode": "スクリーン リーダー移動モードにする", "workbench.action.terminal.new": "新しい統合ターミナルの作成", "workbench.action.terminal.new.short": "新しいターミナル", + "workbench.action.terminal.newWorkspacePlaceholder": "新しいターミナルの作業ディレクトリを選択してください", + "workbench.action.terminal.newInActiveWorkspace": "新しい統合ターミナルを作成 (アクティブなワークスペースに)", "workbench.action.terminal.focus": "端末にフォーカス", "workbench.action.terminal.focusNext": "次の端末にフォーカス", "workbench.action.terminal.focusPrevious": "前のターミナルにフォーカス", diff --git a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 42ec3aff619..37aa8bbba38 100644 --- a/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,7 @@ "terminal.integrated.chooseWindowsShellInfo": "カスタマイズ ボタンを選択して、既定のターミナル シェルを変更できます。", "customize": "カスタマイズする", "cancel": "キャンセル", - "never again": "OK、今後は表示しない", + "never again": "今後は表示しない", "terminal.integrated.chooseWindowsShell": "優先するターミナル シェルを選択します。これは後で設定から変更できます", "terminalService.terminalCloseConfirmationSingular": "アクティブなターミナル セッションが 1 つあります。中止しますか?", "terminalService.terminalCloseConfirmationPlural": "アクティブなターミナル セッションが {0} 個あります。中止しますか?" diff --git a/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 5007e4d58ae..6df9478e8ba 100644 --- a/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,11 +23,12 @@ "commandPalette": "コマンド パレット...", "settings": "設定", "keyboardShortcuts": "キーボード ショートカット", + "userSnippets": "ユーザー スニペット", "selectTheme.label": "配色テーマ", "themes.selectIconTheme.label": "ファイル アイコンのテーマ", "not available": "更新は利用できません", "checkingForUpdates": "更新を確認しています...", - "DownloadUpdate": "利用可能な更新プログラムをダウンロードします", + "DownloadUpdate": "利用可能な更新プログラムをダウンロード", "DownloadingUpdate": "更新をダウンロードしています...", "InstallingUpdate": "更新プログラムをインストールしています...", "restartToUpdate": "再起動して更新...", diff --git a/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index fbd940c7d47..39c4fd74ba4 100644 --- a/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/jpn/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -21,7 +21,7 @@ "welcomePage.gitHubRepository": "GitHub リポジトリ", "welcomePage.stackOverflow": "Stack Overflow", "welcomePage.showOnStartup": "起動時にウェルカム ページを表示", - "welcomePage.customize": "カスタマイズする", + "welcomePage.customize": "カスタマイズ", "welcomePage.installExtensionPacks": "ツールと言語", "welcomePage.installExtensionPacksDescription": "{0} と {1} のサポートをインストールする ", "welcomePage.moreExtensions": "その他", diff --git a/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 26fc5404882..6384721117f 100644 --- a/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "ファイルはディレクトリです", + "fileNotModifiedError": "ファイルは次の時点以後に変更されていません:", "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json index 104db33f633..95c0a8bffc2 100644 --- a/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "開くファイルが大きすぎます", "fileNotFoundError": "ファイルが見つかりません ({0})", "fileBinaryError": "ファイルはバイナリのようなので、テキストとして開くことができません", + "filePermission": "ファイルへの書き込み許可が拒否されました ({0})", "fileExists": "生成しようとしているファイル ({0}) は既に存在しています", "fileMoveConflict": "移動/コピーできません。移動/コピー先にファイルが既に存在します。", "unableToMoveCopyError": "移動/コピーできません。ファイルが含まれるフォルダーが置き換わることになります。", diff --git a/i18n/jpn/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/jpn/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index 4845e670df1..5d95483dfac 100644 --- a/i18n/jpn/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -8,19 +8,20 @@ "requirestring": "`{0}` プロパティは必須で、`string` 型でなければなりません", "optstring": "`{0}` プロパティは省略するか、`string` 型にする必要があります", "vscode.extension.contributes.keybindings.command": "キー バインドのトリガー時に実行するコマンドの識別子。", - "vscode.extension.contributes.keybindings.key": "キーまたはキー シーケンス (キーは + で区切り、シーケンスはスペースで区切る。例: Ctrl+O や Ctrl+L L のようにキーを同時に押す)。", + "vscode.extension.contributes.keybindings.key": "キーまたはキー シーケンス (キーは + で区切り、シーケンスはスペースで区切ります。例: Ctrl+O、Ctrl+L L)。", "vscode.extension.contributes.keybindings.mac": "Mac 固有のキーまたはキー シーケンス。", "vscode.extension.contributes.keybindings.linux": "Linux 固有のキーまたはキー シーケンス。", "vscode.extension.contributes.keybindings.win": "Windows 固有のキーまたはキー シーケンス。", - "vscode.extension.contributes.keybindings.when": "キーがアクティブの場合の条件。", + "vscode.extension.contributes.keybindings.when": "キーがアクティブになるときの条件。", "vscode.extension.contributes.keybindings": "キー バインドを提供します。", "invalid.keybindings": "正しくない `contributes.{0}`: {1}", "unboundCommands": "他に使用できるコマンドは次のとおりです: ", "keybindings.json.title": "キー バインドの構成", - "keybindings.json.key": "キーまたはキー シーケンス (スペースで区切る) を押します", + "keybindings.json.key": "キーまたはキー シーケンス (スペースで区切る)", "keybindings.json.command": "実行するコマンドの名前", - "keybindings.json.when": "キーがアクティブの場合の条件。", + "keybindings.json.when": "キーがアクティブになるときの条件。", "keybindings.json.args": "実行するコマンドに渡す引数。", "keyboardConfigurationTitle": "キーボード", - "dispatch": "`code` (推奨) または `keyCode` のいずれかを使用するキー操作のディスパッチ ロジックを制御します。" + "dispatch": "`code` (推奨) または `keyCode` のいずれかを使用するキー操作のディスパッチ ロジックを制御します。", + "touchbar.enabled": "利用可能であれば macOS の Touch Bar ボタンを有効にします。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/jpn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 2b4d38667bc..a570e254df8 100644 --- a/i18n/jpn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "{0} に加えた変更を保存しますか?", "saveChangesMessages": "次の {0} ファイルに対する変更を保存しますか?", - "moreFile": "...1 つの追加ファイルが表示されていません", - "moreFiles": "...{0} 個の追加ファイルが表示されていません", "saveAll": "すべて保存(&&S)", "save": "保存(&&S)", "dontSave": "保存しない(&&N)", diff --git a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index b1fd1a9b69e..3430db60129 100644 --- a/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "ファイル アイコンがありません", "iconThemeError": "ファイル アイコンのテーマが不明、またはインストールされていません。", "workbenchColors": "現在選択している配色テーマで配色を上書きします。", - "editorColors": "現在選択している配色テーマで配色とフォント スタイルを上書きします。", "editorColors.comments": "コメントの色とスタイルを設定します", "editorColors.strings": "文字列リテラルの色とスタイルを設定します。", "editorColors.keywords": "キーワードの色とスタイルを設定します。", @@ -19,5 +18,6 @@ "editorColors.types": "型定義と参照の色とスタイルを設定します。", "editorColors.functions": "関数定義と参照の色とスタイルを設定します。", "editorColors.variables": "変数定義と参照の色とスタイルを設定します。", - "editorColors.textMateRules": "textmate テーマ規則 (高度) を使っての色とスタイルを設定します。" + "editorColors.textMateRules": "textmate テーマ規則 (高度) を使っての色とスタイルを設定します。", + "editorColors": "現在選択している配色テーマで配色とフォント スタイルを上書きします。" } \ No newline at end of file diff --git a/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index ec391b0543b..132852e62ff 100644 --- a/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/jpn/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "ワークスペース構成ファイルに書き込めません。ファイルを開いて、ファイル内のエラー/警告を修正してからもう一度お試しください。", "errorWorkspaceConfigurationFileDirty": "ファイルが変更されているため、ワークスペース構成ファイルに書き込めません。ファイルを保存してから、もう一度お試しください。", "openWorkspaceConfigurationFile": "ワークスペースの構成ファイルを開く", - "close": "閉じる", - "enterWorkspace.close": "閉じる", - "enterWorkspace.dontShowAgain": "今後は表示しない", - "enterWorkspace.moreInfo": "詳細情報", - "enterWorkspace.prompt": "VS Code での複数フォルダーの操作の詳細。" + "close": "閉じる" } \ No newline at end of file diff --git a/i18n/kor/extensions/git/out/autofetch.i18n.json b/i18n/kor/extensions/git/out/autofetch.i18n.json index a02c668eb9d..1a491bc8a6d 100644 --- a/i18n/kor/extensions/git/out/autofetch.i18n.json +++ b/i18n/kor/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "예", + "read more": "자세히 알아보기", "no": "아니요", - "not now": "나중에", - "suggest auto fetch": "Git 리포지토리 자동 페치하기를 사용하도록 설정하시겠습니까?" + "not now": "나중에 물어보기", + "suggest auto fetch": "Code가 주기적으로 `git fetch`를 실행할까요?" } \ No newline at end of file diff --git a/i18n/kor/extensions/git/out/commands.i18n.json b/i18n/kor/extensions/git/out/commands.i18n.json index 15fcc99ffbe..97749e34962 100644 --- a/i18n/kor/extensions/git/out/commands.i18n.json +++ b/i18n/kor/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\n이 작업은 되돌릴 수 없으며, 현재 작업 설정이 영구적으로 손실됩니다.", "yes discard tracked": "1개의 추적된 파일 취소", "yes discard tracked multiple": "{0}개의 추적된 파일 취소", + "unsaved files single": "다음 파일이 저장되지 않았습니다: {0}.\n\n제출하기 전에 저장할까요?", + "unsaved files": "저장되지 않은 {0}개의 파일들이 있습니다.\n\n제출하기 전에 저장할까요?", + "save and commit": "모두 저장하고 제출", + "commit": "그냥 제출", "no staged changes": "저장할 단계적 변경 사항이 없습니다.\n\n모든 변경 사항을 자동으로 스테이징하고 직접 저장하시겠습니까?", "always": "항상", "no changes": "커밋할 변경 내용이 없습니다.", @@ -64,12 +68,12 @@ "no remotes to pull": "리포지토리에 풀하도록 구성된 원격 항목이 없습니다.", "pick remote pull repo": "분기를 가져올 원격 선택", "no remotes to push": "리포지토리에 푸시하도록 구성된 원격이 없습니다.", - "push with tags success": "태그와 함께 푸시되었습니다.", "nobranch": "원격에 푸시할 분기를 체크 아웃하세요.", + "confirm publish branch": "'{0}' 분기에는 상향 분기가 없습니다. 이 분기를 게시하시겠습니까?", + "ok": "확인", + "push with tags success": "태그와 함께 푸시되었습니다.", "pick remote": "'{0}' 분기를 다음에 게시하려면 원격을 선택하세요.", "sync is unpredictable": "이 작업은 '{0}' 간에 커밋을 푸시하고 풀합니다.", - "ok": "확인", - "never again": "다시 표시 안 함", "no remotes to publish": "리포지토리에 게시하도록 구성된 원격이 없습니다.", "no changes stash": "스태시할 변경 내용이 없습니다.", "provide stash message": "필요한 경우 스태시 메시지를 입력하세요.", diff --git a/i18n/kor/extensions/git/package.i18n.json b/i18n/kor/extensions/git/package.i18n.json index 33448449d9e..8e38cc88df5 100644 --- a/i18n/kor/extensions/git/package.i18n.json +++ b/i18n/kor/extensions/git/package.i18n.json @@ -54,12 +54,12 @@ "command.stashPopLatest": "최신 슬래시 표시", "config.enabled": "Git 사용 여부", "config.path": "Git 실행 파일의 경로", + "config.autoRepositoryDetection": "리포지토리가 자동 감지되어야 하는지 여부", "config.autorefresh": "자동 새로 고침 사용 여부", "config.autofetch": "자동 가져오기 사용 여부", "config.enableLongCommitWarning": "긴 커밋 메시지에 대해 경고할지 여부입니다.", "config.confirmSync": "Git 리포지토리를 동기화하기 전에 확인합니다.", "config.countBadge": "Git 배지 카운터를 제어합니다. `all`이면 변경 내용을 모두 계산하고, `tracked`이면 추적된 변경 내용만 계산하고, `off`이면 해제합니다.", - "config.checkoutType": "`다음으로 체크 아웃...`을 실행할 때 나열되는 분기 유형을 제어합니다. `all`이면 모든 참조를 표시하고, `local`이면 로컬 분기만 표시하고, `tags`이면 태그만 표시하고, `remote`이면 원격 분기만 표시합니다.", "config.ignoreLegacyWarning": "레거시 Git 경고를 무시합니다.", "config.ignoreMissingGitWarning": "Git이 없으면 경고를 무시합니다.", "config.ignoreLimitWarning": "리포지토리에 변경 내용이 너무 많으면 경고를 무시합니다.", @@ -72,5 +72,6 @@ "colors.deleted": "삭제된 리소스의 색상입니다.", "colors.untracked": "추적되지 않은 리소스의 색상입니다.", "colors.ignored": "무시된 리소스의 색상입니다.", - "colors.conflict": "충돌이 발생한 리소스의 색상입니다." + "colors.conflict": "충돌이 발생한 리소스의 색상입니다.", + "colors.submodule": "서브모듈 자원의 색상" } \ No newline at end of file diff --git a/i18n/kor/extensions/typescript/out/commands.i18n.json b/i18n/kor/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..70c3246796b --- /dev/null +++ b/i18n/kor/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "TypeScript 또는 JavaScript 프로젝트를 사용하려면 VS Code의 폴더를 여세요.", + "typescript.projectConfigUnsupportedFile": "TypeScript 또는 JavaScript 프로젝트를 확인할 수 없습니다. 지원되지 않는 파일 형식", + "typescript.projectConfigCouldNotGetInfo": "TypeScript 또는 JavaScript 프로젝트를 확인할 수 없습니다.", + "typescript.noTypeScriptProjectConfig": "파일이 TypeScript 프로젝트의 일부가 아닙니다.", + "typescript.noJavaScriptProjectConfig": "파일이 JavaScript 프로젝트의 일부가 아닙니다.", + "typescript.configureTsconfigQuickPick": "tsconfig.json 구성", + "typescript.configureJsconfigQuickPick": "jsconfig.json 구성", + "typescript.projectConfigLearnMore": "자세한 정보" +} \ No newline at end of file diff --git a/i18n/kor/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/kor/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/kor/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/kor/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/kor/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/kor/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/base/node/ps.i18n.json b/i18n/kor/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/kor/src/vs/base/node/ps.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json index 1fe9d415d3a..31de53acb3a 100644 --- a/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/kor/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "줄 번호는 절대값으로 렌더링 됩니다.", "lineNumbers.relative": "줄 번호는 커서 위치에서 줄 간격 거리로 렌더링 됩니다.", "lineNumbers.interval": "줄 번호는 매 10 줄마다 렌더링이 이루어집니다.", - "lineNumbers": "줄 번호의 표시 여부를 제어합니다. 가능한 값은 'on', 'off', 'relative'입니다.", + "lineNumbers": "줄 번호의 표시 방식을 제어합니다. 가능한 값은 'on', 'off', 'relative', 'interval' 입니다.", "rulers": "특정 수의 고정 폭 문자 뒤에 세로 눈금자를 렌더링합니다. 여러 눈금자의 경우 여러 값을 사용합니다. 배열이 비어 있는 경우 눈금자가 그려져 있지 않습니다.", "wordSeparators": "단어 관련 탐색 또는 작업을 수행할 때 단어 구분 기호로 사용되는 문자입니다.", "tabSize": "탭 한 개에 해당하는 공백 수입니다. `editor.detectIndentation`이 켜져 있는 경우 이 설정은 파일 콘텐츠에 따라 재정의됩니다.", @@ -40,9 +40,6 @@ "wordWrapColumn": "`editor.wordWrap`이 'wordWrapColumn' 또는 'bounded'인 경우 편집기의 열 줄 바꿈을 제어합니다.", "wrappingIndent": "줄 바꿈 행의 들여쓰기를 제어합니다. 'none', 'same' 또는 'indent' 중 하나일 수 있습니다.", "mouseWheelScrollSensitivity": "마우스 휠 스크롤 이벤트의 `deltaX` 및 `deltaY`에서 사용할 승수", - "multiCursorModifier.ctrlCmd": "Windows와 Linux의 'Control'을 OSX의 'Command'로 매핑합니다.", - "multiCursorModifier.alt": "Windows와 Linux의 'Alt'를 OSX의 'Option'으로 매핑합니다.", - "multiCursorModifier": "마우스로 여러 커서를 추가할 때 사용할 수정자입니다. `ctrlCmd`는 Windows와 Linux에서 `Control`로 매핑되고 OSX에서 `Command`로 매핑됩니다. Go To Definition 및 Open Link 마우스 제스처가 멀티커서 수정자와 충돌하지 않도록 조정됩니다.", "quickSuggestions.strings": "문자열 내에서 빠른 제안을 사용합니다.", "quickSuggestions.comments": "주석 내에서 빠른 제안을 사용합니다.", "quickSuggestions.other": "문자열 및 주석 외부에서 빠른 제안을 사용합니다.", diff --git a/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json index a8423dd155b..90813fe32fb 100644 --- a/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/kor/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,6 @@ { "lineHighlight": "커서 위치의 줄 강조 표시에 대한 배경색입니다.", "lineHighlightBorderBox": "커서 위치의 줄 테두리에 대한 배경색입니다.", - "rangeHighlight": "빠른 열기 및 찾기 기능 등을 통해 강조 표시된 영역의 배경색입니다.", "caret": "편집기 커서 색입니다.", "editorCursorBackground": "편집기 커서의 배경색입니다. 블록 커서와 겹치는 글자의 색상을 사용자 정의할 수 있습니다.", "editorWhitespaces": "편집기의 공백 문자 색입니다.", diff --git a/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 58029e4cfcd..73b79e44721 100644 --- a/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "다음 오류 또는 경고로 이동", - "markerAction.previous.label": "이전 오류 또는 경고로 이동", "editorMarkerNavigationError": "편집기 표식 탐색 위젯 오류 색입니다.", "editorMarkerNavigationWarning": "편집기 표식 탐색 위젯 경고 색입니다.", "editorMarkerNavigationInfo": "편집기 표식 탐색 위젯 정보 색입니다.", diff --git a/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index ab340d73f19..8dd1a533f72 100644 --- a/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/kor/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "변수 읽기와 같은 읽기 액세스 중 기호의 배경색입니다.", - "wordHighlightStrong": "변수에 쓰기와 같은 쓰기 액세스 중 기호의 배경색입니다.", "overviewRulerWordHighlightForeground": "기호 강조 표시의 개요 눈금자 마커 색입니다.", "overviewRulerWordHighlightStrongForeground": "쓰기 권한 기호 강조 표시의 개요 눈금자 마커 색입니다.", "wordHighlight.next.label": "다음 강조 기호로 이동", diff --git a/i18n/kor/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/kor/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index ee9870e16a1..8a92234e152 100644 --- a/i18n/kor/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/kor/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}`은(는) 유효한 메뉴 식별자가 아닙니다.", "missing.command": "메뉴 항목이 '명령' 섹션에 정의되지 않은 `{0}` 명령을 참조합니다.", "missing.altCommand": "메뉴 항목이 '명령' 섹션에 정의되지 않은 alt 명령 `{0}`을(를) 참조합니다.", - "dupe.command": "메뉴 항목이 동일한 명령을 기본값과 alt 명령으로 참조합니다.", - "nosupport.altCommand": "죄송합니다. 현재 '편집기/제목' 메뉴의 '탐색' 그룹만 alt 명령을 지원합니다." + "dupe.command": "메뉴 항목이 동일한 명령을 기본값과 alt 명령으로 참조합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/environment/node/argv.i18n.json b/i18n/kor/src/vs/platform/environment/node/argv.i18n.json index 43b38b984db..afaf41e4aa2 100644 --- a/i18n/kor/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/kor/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,34 @@ "diff": "두 파일을 서로 비교합니다.", "add": "마지막 활성 창에 폴더를 추가합니다.", "goto": "지정된 줄과 문자 위치에 있는 경로의 파일을 엽니다.", - "locale": "사용할 로캘(예: en-US 또는 zh-TW)입니다.", "newWindow": "Code의 새 인스턴스를 강제 적용합니다.", - "performance": "'Developer: Startup Performance' 명령을 사용하여 시작합니다.", - "prof-startup": "시작하는 동안 CPU 프로파일러 실행", - "inspect-extensions": "디버깅 및 확장 프로파일링을 허용합니다. 연결 uri에 대한 개발자 도구를 확인하십시오.", - "inspect-brk-extensions": "시작 후 일시 중시된 확장 호스트에서 디버깅 및 확장 프로파일링을 허용합니다. 연결 URL은 개발자 도구를 확인하세요.", "reuseWindow": "마지막 활성 창에서 파일 또는 폴더를 강제로 엽니다.", - "userDataDir": "사용자 데이터가 저장되는 디렉터리를 지정합니다(루트로 실행할 경우 유용함).", - "log": "사용할 로그 수준이며 기본값은 'info'입니다. 허용되는 값은 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'입니다.", - "verbose": "자세한 정보 표시를 출력합니다(--wait를 의미).", "wait": "파일이 닫힐 때 까지 기다린 후 돌아갑니다.", + "locale": "사용할 로캘(예: en-US 또는 zh-TW)입니다.", + "userDataDir": "사용자 데이터가 저장되는 디렉터리를 지정합니다(루트로 실행할 경우 유용함).", + "version": "버전을 출력합니다.", + "help": "사용법을 출력합니다.", "extensionHomePath": "확장의 루트 경로를 설정합니다.", "listExtensions": "설치된 확장을 나열합니다.", "showVersions": "#NAME?", "installExtension": "확장을 설치합니다.", "uninstallExtension": "확장을 제거합니다.", "experimentalApis": "확장에 대해 제안된 API 기능을 사용하도록 설정합니다.", - "disableExtensions": "설치된 모든 확장을 사용하지 않도록 설정합니다.", - "disableGPU": "GPU 하드웨어 가속을 사용하지 않도록 설정합니다.", + "verbose": "자세한 정보 표시를 출력합니다(--wait를 의미).", + "log": "사용할 로그 수준이며 기본값은 'info'입니다. 허용되는 값은 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'입니다.", "status": "프로세스 사용 및 진단 정보를 인쇄합니다.", - "version": "버전을 출력합니다.", - "help": "사용법을 출력합니다.", + "performance": "'Developer: Startup Performance' 명령을 사용하여 시작합니다.", + "prof-startup": "시작하는 동안 CPU 프로파일러 실행", + "disableExtensions": "설치된 모든 확장을 사용하지 않도록 설정합니다.", + "inspect-extensions": "디버깅 및 확장 프로파일링을 허용합니다. 연결 uri에 대한 개발자 도구를 확인하십시오.", + "inspect-brk-extensions": "시작 후 일시 중시된 확장 호스트에서 디버깅 및 확장 프로파일링을 허용합니다. 연결 URL은 개발자 도구를 확인하세요.", + "disableGPU": "GPU 하드웨어 가속을 사용하지 않도록 설정합니다.", "usage": "사용법", "options": "옵션", "paths": "경로", - "optionsUpperCase": "옵션" + "stdinWindows": "다른 프로그램의 출력을 읽으려면, '-'를 추가하십시오. (예: 'echo Hello World | {0} -')", + "stdinUnix": "stdin에서 읽어오려면, '-'를 추가하십시오.(예. 'ps aux | grep code | {0} -')", + "optionsUpperCase": "옵션", + "extensionsManagement": "확장 관리", + "troubleshooting": "문제 해결" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 64578b6f8a5..01c78cf0a53 100644 --- a/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/kor/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,14 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "잘못된 확장: package.json이 JSON 파일이 아닙니다.", - "restartCodeLocal": "{0}을(를) 다시 설치하기 전에 Code를 다시 시작하세요.", + "restartCode": "{0}을(를) 다시 설치하기 전에 Code를 다시 시작하세요.", "installingOutdatedExtension": "이 확장의 최신 버전이 이미 설치되어 있습니다. 이 버전을 이전 버전으로 재정의하시겠습니까?", "override": "재정의", "cancel": "취소", - "notFoundCompatible": "VS Code의 현재 버전 '{1}'과(와) 호환되는 '{0}' 확장을 찾을 수 없으므로 설치할 수 없습니다.", - "quitCode": "확장의 사용되지 않는 인스턴스가 계속 실행 중이므로 설치할 수 없습니다. 다시 설치하기 전에 VS Code를 종료했다가 다시 시작하세요.", - "exitCode": "확장의 사용되지 않는 인스턴스가 계속 실행 중이므로 설치할 수 없습니다. 다시 설치하기 전에 VS Code를 종료했다가 다시 시작하세요.", + "notFoundCompatible": "'{0}'을(를) 설치할 수 없습니다; VS Code '{1}'과 호환되는 버전이 없습니다.", "notFoundCompatibleDependency": "VS Code의 현재 버전 '{1}'과(와) 호환되는 종속된 확장 '{0}'을(를) 찾을 수 없으므로 설치할 수 없습니다.", + "quitCode": "확장을 설치할 수 없습니다. 다시 설치하기 위해 VS Code를 종료하고 다시 시작하십시오.", + "exitCode": "확장을 설치할 수 없습니다. 다시 설치하기 전에 VS 코드를 종료한 후 다시 시작하십시오. ", "uninstallDependeciesConfirmation": "'{0}'만 제거할까요, 아니면 종속성도 제거할까요?", "uninstallOnly": "만", "uninstallAll": "모두", diff --git a/i18n/kor/src/vs/platform/list/browser/listService.i18n.json b/i18n/kor/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..f1ae7883f32 --- /dev/null +++ b/i18n/kor/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "워크벤치" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/message/common/message.i18n.json b/i18n/kor/src/vs/platform/message/common/message.i18n.json index 8194d2b9b95..7cec53dd19a 100644 --- a/i18n/kor/src/vs/platform/message/common/message.i18n.json +++ b/i18n/kor/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "닫기", "later": "나중에", - "cancel": "취소" + "cancel": "취소", + "moreFile": "...1개의 추가 파일이 표시되지 않음", + "moreFiles": "...{0}개의 추가 파일이 표시되지 않음" } \ No newline at end of file diff --git a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json index 8f111cba06f..ac7b14b24ea 100644 --- a/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/kor/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,7 @@ "editorWidgetBorder": "편집기 위젯의 테두리 색입니다. 위젯에 테두리가 있고 위젯이 색상을 무시하지 않을 때만 사용됩니다.", "editorSelectionBackground": "편집기 선택 영역의 색입니다.", "editorSelectionForeground": "고대비를 위한 선택 텍스트의 색입니다.", - "editorInactiveSelection": "비활성 편집기 선택 영역의 색입니다.", - "editorSelectionHighlight": "선택 영역과 동일한 콘텐츠가 있는 영역의 색입니다.", "editorFindMatch": "현재 검색 일치 항목의 색입니다.", - "findMatchHighlight": "기타 검색 일치 항목의 색입니다.", - "findRangeHighlight": "검색을 제한하는 영역의 색을 지정합니다.", - "hoverHighlight": "호버가 표시된 단어 아래를 강조 표시합니다.", "hoverBackground": "편집기 호버의 배경색.", "hoverBorder": "편집기 호버의 테두리 색입니다.", "activeLinkForeground": "활성 링크의 색입니다.", @@ -76,12 +71,6 @@ "diffEditorRemoved": "제거된 텍스트의 배경색입니다.", "diffEditorInsertedOutline": "삽입된 텍스트의 윤곽선 색입니다.", "diffEditorRemovedOutline": "제거된 텍스트의 윤곽선 색입니다.", - "mergeCurrentHeaderBackground": "인라인 병합 충돌의 현재 헤더 배경입니다.", - "mergeCurrentContentBackground": "인라인 병합 충돌의 현재 콘텐츠 배경입니다.", - "mergeIncomingHeaderBackground": "인라인 병합 충돌에서 수신 헤더 배경입니다.", - "mergeIncomingContentBackground": "인라인 병합 충돌에서 수신 콘텐츠 배경입니다.", - "mergeCommonHeaderBackground": "인라인 병합 충돌의 공통 과거 헤더 배경입니다.", - "mergeCommonContentBackground": "인라인 병합 충돌의 공통 과거 콘텐츠 배경입니다.", "mergeBorder": "인라인 병합 충돌에서 헤더 및 스플리터의 테두리 색입니다.", "overviewRulerCurrentContentForeground": "인라인 병합 충돌에서 현재 개요 눈금 전경색입니다.", "overviewRulerIncomingContentForeground": "인라인 병합 충돌에서 수신 개요 눈금 전경색입니다.", diff --git a/i18n/kor/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/kor/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..31dbb01b8b0 --- /dev/null +++ b/i18n/kor/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "속성 `{0}`은(는) 필수이며 `string` 형식이어야 합니다.", + "optstring": "속성 `{0}`은(는) 생략할 수 있으며 `string` 형식이어야 합니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..9f96e3885f7 --- /dev/null +++ b/i18n/kor/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "실행중인 저장 관계자..." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/kor/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 4dfa6a6e897..80def44cc85 100644 --- a/i18n/kor/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/kor/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -4,7 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "treeView.notRegistered": "ID가 '{0}'인 등록된 트리 뷰가 없습니다.", - "treeItem.notFound": "ID가 '{0}'인 트리 항목을 찾을 수 없습니다.", - "treeView.duplicateElement": "{0} 요소가 이미 등록되어 있습니다." + "treeView.notRegistered": "ID가 '{0}'인 등록된 트리 뷰가 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/kor/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 2ad17264baf..091e1d88413 100644 --- a/i18n/kor/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "사이드바 위치 설정/해제", "view": "보기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json index d99bcba35ef..646be54e188 100644 --- a/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "파일 열기...", "openFolder": "폴더 열기...", "openFileFolder": "열기...", - "addFolderToWorkspace": "작업 영역에 폴더 추가...", - "add": "추가(&&A)", - "addFolderToWorkspaceTitle": "작업 영역에 폴더 추가", "globalRemoveFolderFromWorkspace": "작업 영역에서 폴더 제거...", - "removeFolderFromWorkspace": "작업 영역에서 폴더 삭제", - "openFolderSettings": "폴더 설정 열기", "saveWorkspaceAsAction": "작업 영역을 다른 이름으로 저장", "save": "저장(&&S)", "saveWorkspace": "작업 영역 저장", "openWorkspaceAction": "작업 영역 열기...", "openWorkspaceConfigFile": "작업 영역 구성 파일 열기", - "openFolderAsWorkspaceInNewWindow": "새 창에서 작업 영역으로 폴더 열기", - "workspaceFolderPickerPlaceholder": "작업 영역 폴더 선택" + "openFolderAsWorkspaceInNewWindow": "새 창에서 작업 영역으로 폴더 열기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/kor/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..4aff2c19344 --- /dev/null +++ b/i18n/kor/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "작업 영역에 폴더 추가...", + "add": "추가(&&A)", + "addFolderToWorkspaceTitle": "작업 영역에 폴더 추가" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 32f439e8de1..57c83a5d7c5 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,17 @@ "groupThreePicker": "세 번째 그룹에 편집기 표시", "allEditorsPicker": "열려 있는 모든 편집기 표시", "view": "보기", - "file": "파일" + "file": "파일", + "close": "닫기", + "closeOthers": "기타 항목 닫기", + "closeRight": "오른쪽에 있는 항목 닫기", + "closeAllUnmodified": "미수정 항목 닫기", + "closeAll": "모두 닫기", + "keepOpen": "열린 상태 유지", + "showOpenedEditors": "열려 있는 편집기 표시", + "keepEditor": "편집기 유지", + "closeEditorsInGroup": "그룹의 모든 편집기 닫기", + "closeUnmodifiedEditors": "그룹의 수정되지 않은 편집기 닫기", + "closeOtherEditors": "다른 편집기 닫기", + "closeRightEditors": "오른쪽에 있는 편집기 닫기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index ed6d0f43e21..92ac30a939f 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "편집기 닫기", "revertAndCloseActiveEditor": "편집기 되돌리기 및 닫기", "closeEditorsToTheLeft": "왼쪽에 있는 편집기 닫기", - "closeEditorsToTheRight": "오른쪽에 있는 편집기 닫기", "closeAllEditors": "모든 편집기 닫기", - "closeUnmodifiedEditors": "그룹의 수정되지 않은 편집기 닫기", "closeEditorsInOtherGroups": "다른 그룹의 편집기 닫기", - "closeOtherEditorsInGroup": "다른 편집기 닫기", - "closeEditorsInGroup": "그룹의 모든 편집기 닫기", "moveActiveGroupLeft": "편집기 그룹을 왼쪽으로 이동", "moveActiveGroupRight": "편집기 그룹을 오른쪽으로 이동", "minimizeOtherEditorGroups": "다른 편집기 그룹 최소화", "evenEditorGroups": "균등한 편집기 그룹 너비", "maximizeEditor": "편집기 그룹 최대화 및 사이드바 숨기기", - "keepEditor": "편집기 유지", "openNextEditor": "다음 편집기 열기", "openPreviousEditor": "이전 편집기 열기", "nextEditorInGroup": "그룹에서 다음 편집기 열기", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "첫 번째 그룹에 편집기 표시", "showEditorsInSecondGroup": "두 번째 그룹에 편집기 표시", "showEditorsInThirdGroup": "세 번째 그룹에 편집기 표시", - "showEditorsInGroup": "그룹의 편집기 표시", "showAllEditors": "모든 편집기 표시", "openPreviousRecentlyUsedEditorInGroup": "그룹에서 최근에 사용한 이전 편집기 열기", "openNextRecentlyUsedEditorInGroup": "그룹에서 최근에 사용한 다음 편집기 열기", diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 6c0c854e4bf..b32e252f6bf 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "활성 편집기를 탭 또는 그룹 단위로 이동", "editorCommand.activeEditorMove.arg.name": "활성 편집기 이동 인수", - "editorCommand.activeEditorMove.arg.description": "인수 속성: * '를': 문자열 값을 제공 하 고 위치를 이동.\n\t* ' 의해': 문자열 이동에 대 한 단위를 제공 하는 값. 탭 또는 그룹.\n\t* ' value': 얼마나 많은 위치 또는 이동 하는 절대 위치를 제공 하는 숫자 값.", - "commandDeprecated": "**{0}** 명령이 제거되었습니다. 대신 **{1}** 명령을 사용할 수 있습니다.", - "openKeybindings": "바로 가기 키 구성" + "editorCommand.activeEditorMove.arg.description": "인수 속성: * '를': 문자열 값을 제공 하 고 위치를 이동.\n\t* ' 의해': 문자열 이동에 대 한 단위를 제공 하는 값. 탭 또는 그룹.\n\t* ' value': 얼마나 많은 위치 또는 이동 하는 절대 위치를 제공 하는 숫자 값." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index dedfef7381b..aaa9957a9bf 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "텍스트 파일 비교 편집기입니다.", "navigate.next.label": "다음 변경 내용", "navigate.prev.label": "이전 변경 내용", - "inlineDiffLabel": "인라인 보기로 전환", - "sideBySideDiffLabel": "세로 정렬 보기로 전환" + "toggleIgnoreTrimWhitespace.label": "자르기 공백 무시" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index a290c099837..13cca1a3336 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "닫기", - "closeOthers": "기타 항목 닫기", - "closeRight": "오른쪽에 있는 항목 닫기", - "closeAll": "모두 닫기", - "closeAllUnmodified": "미수정 항목 닫기", - "keepOpen": "열린 상태 유지", - "showOpenedEditors": "열려 있는 편집기 표시", "araLabelEditorActions": "편집기 작업" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index fbf734ff7aa..4777ec24002 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[지원되지 않음]", + "userIsAdmin": "[관리자]", + "userIsSudo": "[슈퍼유저]", "devExtensionWindowTitlePrefix": "[확장 개발 호스트]" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/kor/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index b4ccb557e6a..8b6ad71cd4e 100644 --- a/i18n/kor/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/kor/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -3,6 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. -{ - "hideView": "사이드바에서 숨기기" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/common/theme.i18n.json b/i18n/kor/src/vs/workbench/common/theme.i18n.json index c43957e4bd8..cbb96bc285b 100644 --- a/i18n/kor/src/vs/workbench/common/theme.i18n.json +++ b/i18n/kor/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "활성 탭 배경색입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", "tabInactiveBackground": "비활성 탭 배경색입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", + "tabHoverBackground": "마우스 커서를 올려놓았을 때의 탭 배경색. 탭은 편집 영역에서 편집기를 감싸고 있습니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 편집기 그룹이 여러 개일 수 있습니다.", + "tabUnfocusedHoverBackground": "마우스 커서를 올려놓았을 때 포커스를 받지 못한 탭 배경색. 탭은 편집 영역에서 편집기를 감싸고 있습니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 편집기 그룹이 여러 개일 수 있습니다.", "tabBorder": "탭을 서로 구분하기 위한 테두리입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", "tabActiveBorder": "활성 탭을 강조 표시하기 위한 테두리입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", "tabActiveUnfocusedBorder": "포커스가 없는 그룹에서 활성 탭을 강조 표시하기 위한 테두리입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", + "tabHoverBorder": "마우스 커서를 올려놓았을 때 활성 탭의 테두리. 탭은 편집 영역에서 편집기를 감싸고 있습니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 편집기 그룹이 여러 개일 수 있습니다.", + "tabUnfocusedHoverBorder": "마우스 커서를 올려놓았을 때 포커스를 받지 못한 그룹에서 활성 탭 테두리. 탭은 편집 영역에서 편집기를 감싸고 있습니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 편집기 그룹이 여러 개일 수 있습니다.", "tabActiveForeground": "활성 그룹의 활성 탭 전경색입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", "tabInactiveForeground": "활성 그룹의 비활성 탭 전경색입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", "tabUnfocusedActiveForeground": "포커스가 없는 그룹의 활성 탭 전경색입니다. 탭은 편집기 영역에서 편집기의 컨테이너입니다. 한 편집기 그룹에서 여러 탭을 열 수 있습니다. 여러 편집기 그룹이 있을 수 있습니다.", @@ -16,7 +20,7 @@ "editorGroupBackground": "편집기 그룹의 배경색입니다. 편집기 그룹은 편집기의 컨테이너입니다. 배경색은 편집기 그룹을 끌 때 표시됩니다.", "tabsContainerBackground": "탭을 사용도록 설정한 경우 편집기 그룹 제목 머리글의 배경색입니다. 편집기 그룹은 편집기의 컨테이너입니다.", "tabsContainerBorder": "탭을 사용하도록 설정한 경우 편집기 그룹 제목 머리글의 테두리 색입니다. 편집기 그룹은 편집기의 컨테이너입니다.", - "editorGroupHeaderBackground": "탭을 사용하지 않도록 설정한 경우 편집기 그룹 제목 머리글의 배경색입니다. 편집기 그룹은 편집기의 컨테이너입니다.", + "editorGroupHeaderBackground": "탭을 사용하지 않도록 설정한 경우(`\"workbench.editor.showTabs\": false`) 편집기 그룹 제목 머리글의 배경색입니다. 편집기 그룹은 편집기의 컨테이너입니다.", "editorGroupBorder": "여러 편집기 그룹을 서로 구분하기 위한 색입니다. 편집기 그룹은 편집기의 컨테이너입니다.", "editorDragAndDropBackground": "편집기를 끌 때 배경색입니다. 편집기 내용이 계속 비추어 보이도록 이 색은 투명해야 합니다.", "panelBackground": "패널 배경색입니다. 패널은 편집기 영역 아래에 표시되며 출력 및 통합 터미널 같은 보기가 포함됩니다.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "열린 폴더가 없을 때 사이드바 및 편집기와 구분하는 상태 표시줄 테두리 색입니다. 상태 표시줄은 창의 맨 아래에 표시됩니다.", "statusBarItemActiveBackground": "클릭할 때의 상태 표시줄 항목 배경색입니다. 상태 표시줄은 창의 맨 아래에 표시됩니다.", "statusBarItemHoverBackground": "마우스로 가리킬 때의 상태 표시줄 항목 배경색입니다. 상태 표시줄은 창의 맨 아래에 표시됩니다.", - "statusBarProminentItemBackground": "상태 표시줄 주요 항목 배경색입니다. 주요 항목은 중요도를 나타내는 다른 상태 표시줄 항목보다 눈에 잘 띕니다. 상태 표시줄은 창의 맨 아래에 표시됩니다.", - "statusBarProminentItemHoverBackground": "마우스로 가리킬 때의 상태 표시줄 주요 항목 배경색입니다. 주요 항목은 중요도를를 나타내는 다른 상태 표시줄 항목보다 눈에 잘 띕니다. 상태 표시줄은 창의 맨 아래에 표시됩니다.", + "statusBarProminentItemBackground": " 상태 표시줄 주요 항목 배경 색. 주요 항목은 중요성을 알려주기 위해 다른 상태 표시줄 항목보다 눈에 띕니다. 예제를 보기 위해 명령 팔레트에서 '포커스 이동을 위해 탭 키 토글' 모드를 변경합니다. 창 아래쪽에 상태 표시줄이 나타납니다.", + "statusBarProminentItemHoverBackground": "마우스 커서를 올렸을 때 상태 표시줄 주요 항목 배경 색. 주요 항목은 중요성을 알려주기 위해 다른 상태 표시줄 항목보다 눈에 띕니다. 예제를 보기 위해 명령 팔레트에서 '포커스 이동을 위해 탭 키 토글' 모드를 변경합니다. 창 아래쪽에 상태 표시줄이 나타납니다.", "activityBarBackground": "작업 막대 배경색입니다. 작업 막대는 맨 왼쪽이나 오른쪽에 표시되며 사이드바의 뷰 간을 전환하는 데 사용할 수 있습니다.", "activityBarForeground": "작업 막대 전경 색(예: 아이콘에 사용됨)입니다. 작업 막대는 오른쪽이나 왼쪽 끝에 표시되며 사이드바의 보기 간을 전환할 수 있습니다.", "activityBarBorder": "사이드바와 구분하는 작업 막대 테두리색입니다. 작업 막대는 오른쪽이나 왼쪽 끝에 표시되며 사이드바의 보기 간을 전환할 수 있습니다.", diff --git a/i18n/kor/src/vs/workbench/common/views.i18n.json b/i18n/kor/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..6a3532ad44d --- /dev/null +++ b/i18n/kor/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "ID `{0}`이(가) 포함된 뷰가 위치 `{1}`에 이미 등록되어 있습니다." +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json index 96f43aced40..a1086cd9b19 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "편집기 닫기", "closeWindow": "창 닫기", "closeWorkspace": "작업 영역 닫기", "noWorkspaceOpened": "현재 이 인스턴스에 열려 있는 작업 영역이 없습니다.", @@ -52,21 +51,5 @@ "displayLanguage": "VSCode의 표시 언어를 정의합니다.", "doc": "지원되는 언어 목록은 {0} 을(를) 참조하세요.", "restart": "값을 변경하려면 VSCode를 다시 시작해야 합니다.", - "fail.createSettings": "{0}'({1})을(를) 만들 수 없습니다.", - "openLogsFolder": "로그 폴더 열기", - "showLogs": "로그 표시...", - "mainProcess": "기본", - "sharedProcess": "공유", - "rendererProcess": "렌더러", - "extensionHost": "확장 호스트", - "selectProcess": "프로세스 선택", - "setLogLevel": "로그 수준 설정", - "trace": "Trace", - "debug": "디버그", - "info": "정보", - "warn": "경고", - "err": "오류", - "critical": "Critical", - "off": "Off", - "selectLogLevel": "로그 수준 선택" + "fail.createSettings": "{0}'({1})을(를) 만들 수 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json index b3ca18516e9..612e6f3495e 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "보기", "help": "도움말", "file": "파일", - "developer": "개발자", "workspaces": "작업 영역", + "developer": "개발자", + "workbenchConfigurationTitle": "워크벤치", "showEditorTabs": "열려 있는 편집기를 탭에서 표시할지 여부를 제어합니다.", "workbench.editor.labelFormat.default": "파일 이름을 표시합니다. 탭이 사용하도록 설정되어 있고 하나의 그룹에서 파일 2개의 이름이 동일하면, 각 파일 경로의 특정 섹션이 추가됩니다. 탭이 사용하도록 설정되어 있지 않으면, 작업 영역 폴더에 대한 경로는 편집기가 활성 상태일 때 표시됩니다.", "workbench.editor.labelFormat.short": "디렉터리 이름 앞에 오는 파일의 이름을 표시합니다.", @@ -20,23 +21,23 @@ "showIcons": "열린 편집기를 아이콘과 함께 표시할지 여부를 제어합니다. 이를 위해서는 아이콘 테마도 사용하도록 설정해야 합니다.", "enablePreview": "열려 있는 편집기를 미리 보기로 표시할지 여부를 제어합니다. 미리 보기 편집기는 유지된 상태까지(예: 두 번 클릭 또는 편집을 통해) 다시 사용되며 기울임꼴 글꼴 스타일로 표시됩니다.", "enablePreviewFromQuickOpen": "Quick Open에서 연 편집기를 미리 보기로 표시할지 여부를 제어합니다. 미리 보기 편집기는 유지된 상태까지(예: 두 번 클릭 또는 편집을 통해) 다시 사용됩니다.", + "closeOnFileDelete": "일부 다른 프로세스에서 파일을 삭제하거나 이름을 바꿀 때 파일을 표시하는 편집기를 자동으로 닫을지 여부를 제어합니다. 사용하지 않도록 설정하는 경우 이러한 이벤트가 발생하면 편집기가 더티 상태로 계속 열려 있습니다. 응용 프로그램 내에서 삭제하면 항상 편집기가 닫히고 데이터를 유지하기 위해 더티 파일은 닫히지 않습니다.", "editorOpenPositioning": "편집기가 열리는 위치를 제어합니다. 현재 활성 편집기의 왼쪽 또는 오른쪽에서 편집기를 열려면 '왼쪽' 또는 '오른쪽'을 선택합니다. 현재 활성 편집기와 독립적으로 편집기를 열려면 '처음' 또는 '마지막'을 선택합니다.", "revealIfOpen": "편집기를 여는 경우 보이는 그룹 중 하나에 표시할지 여부를 제어합니다. 사용하지 않도록 설정할 경우 편집기가 기본적으로 현재 활성 편집기 그룹에 열립니다. 사용하도록 설정할 경우 현재 활성 편집기 그룹에서 편집기가 다시 열리지 않고 이미 열린 편집기가 표시됩니다. 강제로 편집기가 특정 그룹에서 열리거나 현재 활성 그룹 옆에 열리도록 하는 등의 일부 경우에는 이 설정이 무시됩니다.", + "swipeToNavigate": "세 손가락으로 가로로 살짝 밀어 열려 있는 파일 간을 이동합니다.", "commandHistory": "명령 팔레트 기록을 유지하기 위해 최근 사용한 명령 개수를 제어합니다. 0으로 설정하면 명령 기록을 사용하지 않습니다.", "preserveInput": "다음에 열 때 마지막으로 명령 팔레트에 입력한 내용을 복원할지 결정합니다.", "closeOnFocusLost": "Quick Open가 포커스를 잃으면 자동으로 닫을지 여부를 제어합니다.", "openDefaultSettings": "설정을 열면 모든 기본 설정을 표시하는 편집기도 열리는지 여부를 제어합니다.", "sideBarLocation": "사이드바의 위치를 제어합니다. 워크벤치의 왼쪽이나 오른쪽에 표시될 수 있습니다.", + "panelDefaultLocation": "패널의 기본 위치를 제어합니다. 워크벤치의 아래 또는 오른쪽에 표시될 수 있습니다.", "statusBarVisibility": "워크벤치 아래쪽에서 상태 표시줄의 표시 유형을 제어합니다.", "activityBarVisibility": "워크벤치에서 작업 막대의 표시 유형을 제어합니다.", - "closeOnFileDelete": "일부 다른 프로세스에서 파일을 삭제하거나 이름을 바꿀 때 파일을 표시하는 편집기를 자동으로 닫을지 여부를 제어합니다. 사용하지 않도록 설정하는 경우 이러한 이벤트가 발생하면 편집기가 더티 상태로 계속 열려 있습니다. 응용 프로그램 내에서 삭제하면 항상 편집기가 닫히고 데이터를 유지하기 위해 더티 파일은 닫히지 않습니다.", - "enableNaturalLanguageSettingsSearch": "설정에 대한 자연어 검색 모드를 사용할지 여부를 제어합니다.", "fontAliasing": "워크벤치에서 글꼴 앨리어싱 방식을 제어합니다.\n- 기본: 서브 픽셀 글꼴 다듬기. 대부분의 일반 디스플레이에서 가장 선명한 글꼴 제공\n- 안티앨리어싱: 서브 픽셀이 아닌 픽셀 단위에서 글꼴 다듬기. 전반적으로 더 밝은 느낌을 줄 수 있음\n- 없음: 글꼴 다듬기 사용 안 함. 텍스트 모서리가 각지게 표시됨", "workbench.fontAliasing.default": "서브 픽셀 글꼴 다듬기. 대부분의 일반 디스플레이에서 가장 선명한 텍스트를 제공합니다. ", "workbench.fontAliasing.antialiased": "서브 픽셀이 아닌 픽셀 수준에서 글꼴을 다듬습니다. 전반적으로 글꼴이 더 밝게 표시됩니다.", "workbench.fontAliasing.none": "글꼴 다듬기를 사용하지 않습니다. 텍스트 가장자리가 각지게 표시됩니다.", - "swipeToNavigate": "세 손가락으로 가로로 살짝 밀어 열려 있는 파일 간을 이동합니다.", - "workbenchConfigurationTitle": "워크벤치", + "enableNaturalLanguageSettingsSearch": "설정에 대한 자연어 검색 모드를 사용할지 여부를 제어합니다.", "windowConfigurationTitle": "창", "window.openFilesInNewWindow.on": "파일이 새 창에서 열립니다.", "window.openFilesInNewWindow.off": "파일이 파일의 폴더가 열려 있는 창 또는 마지막 활성 창에서 열립니다.", diff --git a/i18n/kor/src/vs/workbench/electron-browser/window.i18n.json b/i18n/kor/src/vs/workbench/electron-browser/window.i18n.json index dc0deb8eb7f..c019b85acbe 100644 --- a/i18n/kor/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/kor/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "잘라내기", "copy": "복사", "paste": "붙여넣기", - "selectAll": "모두 선택" + "selectAll": "모두 선택", + "runningAsRoot": "{0}을(를) 루트 사용자로 실행하지 않는 것이 좋습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index e3166a31b49..55b56ed3448 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "디버그 도구 모음 배경색입니다." + "debugToolBarBackground": "디버그 도구 모음 배경색입니다.", + "debugToolBarBorder": "디버그 도구 모음 테두리색입니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 0db91f83b2f..ba5ae3f8c3f 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json'의 유효성 검사를 위한 JSON 스키마 구성입니다.", "vscode.extension.contributes.debuggers.windows": "Windows 특정 설정", "vscode.extension.contributes.debuggers.windows.runtime": "Windows에 사용되는 런타임입니다.", - "vscode.extension.contributes.debuggers.osx": "OS X 특정 설정입니다.", - "vscode.extension.contributes.debuggers.osx.runtime": "OSX에 사용되는 런타임입니다.", "vscode.extension.contributes.debuggers.linux": "Linux 특정 설정", "vscode.extension.contributes.debuggers.linux.runtime": "Linux에 사용되는 런타임입니다.", "vscode.extension.contributes.breakpoints": "중단점을 적용합니다.", diff --git a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 0530d6e3338..744cd683e86 100644 --- a/i18n/kor/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "디버기", - "debug.terminal.not.available.error": "통합 터미널을 사용할 수 없습니다." + "debug.terminal.title": "디버기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 50730f44076..318c2b33d6f 100644 --- a/i18n/kor/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "새 명령 프롬프트 열기", "globalConsoleActionMacLinux": "새 터미널 열기", "scopedConsoleActionWin": "명령 프롬프트에서 열기", - "scopedConsoleActionMacLinux": "터미널에서 열기", - "openFolderInIntegratedTerminal": "터미널에서 열기" + "scopedConsoleActionMacLinux": "터미널에서 열기" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 3b5fdb0caac..ec5f81cd482 100644 --- a/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "최근에 연 파일을 기반으로 확장이 권장됩니다.", + "neverShowAgain": "다시 표시 안 함", + "close": "닫기", "workspaceRecommendation": "이 확장은 현재 작업 영역 사용자가 권장합니다.", + "fileBasedRecommendation": "최근에 연 파일을 기반으로 확장이 권장됩니다.", "exeBasedRecommendation": "{0}이(가) 설치되어 있으므로 이 확장을 권장합니다.", "reallyRecommended2": "이 파일 형식에 대해 '{0}' 확장이 권장됩니다.", "reallyRecommendedExtensionPack": "이 파일 형식에 대해 '{0}' 확장 팩이 권장됩니다.", "showRecommendations": "권장 사항 표시", "install": "설치", - "neverShowAgain": "다시 표시 안 함", - "close": "닫기", "workspaceRecommended": "이 작업 영역에 확장 권장 사항이 있습니다.", "installAll": "모두 설치", "ignoreExtensionRecommendations": "확장 권장 사항을 모두 무시하시겠습니까?", diff --git a/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..f1ae7883f32 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "워크벤치" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 70dd8169321..9595a565713 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,25 @@ "filesCategory": "파일", "revealInSideBar": "세로 막대에 표시", "acceptLocalChanges": "변경을 적용하고 디스크 콘텐츠 덮어쓰기", - "revertLocalChanges": "변경 내용을 취소하고 디스크의 콘텐츠로 되돌리기" + "revertLocalChanges": "변경 내용을 취소하고 디스크의 콘텐츠로 되돌리기", + "copyPathOfActive": "활성 파일의 경로 복사", + "saveAllInGroup": "그룹의 모든 항목 저장", + "saveFiles": "파일 모두 저장", + "revert": "파일 되돌리기", + "compareActiveWithSaved": "활성 파일을 저장된 파일과 비교", + "closeEditor": "편집기 닫기", + "view": "보기", + "openToSide": "측면에서 열기", + "revealInWindows": "탐색기에 표시", + "revealInMac": "Finder에 표시", + "openContainer": "상위 폴더 열기", + "copyPath": "경로 복사", + "saveAll": "모두 저장", + "compareWithSaved": "저장된 항목과 비교", + "compareSource": "비교를 위해 선택", + "close": "닫기", + "closeOthers": "기타 항목 닫기", + "closeUnmodified": "미수정 항목 닫기", + "closeAll": "모두 닫기", + "deleteFile": "영구히 삭제" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 87d00a4c77a..63c70d80b92 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "다시 시도", - "rename": "이름 바꾸기", "newFile": "새 파일", "newFolder": "새 폴더", + "rename": "이름 바꾸기", + "delete": "삭제", + "copyFile": "복사", + "pasteFile": "붙여넣기", + "retry": "다시 시도", "openFolderFirst": "안에 파일이나 폴더를 만들려면 먼저 폴더를 엽니다.", "newUntitledFile": "제목이 없는 새 파일", "createNewFile": "새 파일", @@ -28,26 +31,14 @@ "confirmDeleteMessageFile": "'{0}'을(를) 영구히 삭제할까요?", "irreversible": "이 작업은 취소할 수 없습니다.", "permDelete": "영구히 삭제", - "delete": "삭제", "importFiles": "파일 가져오기", "confirmOverwrite": "이름이 같은 파일 또는 폴더가 대상 폴더에 이미 있습니다. 덮어쓸까요?", "replaceButtonLabel": "바꾸기(&&R)", - "copyFile": "복사", - "pasteFile": "붙여넣기", "duplicateFile": "중복", - "openToSide": "측면에서 열기", - "compareSource": "비교를 위해 선택", "globalCompareFile": "활성 파일을 다음과 비교...", "openFileToCompare": "첫 번째 파일을 열어서 다른 파일과 비교합니다.", - "compareWith": "'{0}'과(와) '{1}' 비교", - "compareFiles": "파일 비교", "refresh": "새로 고침", - "save": "저장", - "saveAs": "다른 이름으로 저장...", - "saveAll": "모두 저장", "saveAllInGroup": "그룹의 모든 항목 저장", - "saveFiles": "파일 모두 저장", - "revert": "파일 되돌리기", "focusOpenEditors": "열려 있는 편집기 뷰에 포커스", "focusFilesExplorer": "파일 탐색기에 포커스", "showInExplorer": "세로 막대에서 활성 파일 표시", @@ -56,20 +47,11 @@ "refreshExplorer": "탐색기 새로 고침", "openFileInNewWindow": "새 창에서 활성 파일 열기", "openFileToShowInNewWindow": "먼저 파일 한 개를 새 창에서 엽니다.", - "revealInWindows": "탐색기에 표시", - "revealInMac": "Finder에 표시", - "openContainer": "상위 폴더 열기", - "revealActiveFileInWindows": "Windows 탐색기에 활성 파일 표시", - "revealActiveFileInMac": "Finder에 활성 파일 표시", - "openActiveFileContainer": "활성 파일의 상위 폴더 열기", "copyPath": "경로 복사", - "copyPathOfActive": "활성 파일의 경로 복사", "emptyFileNameError": "파일 또는 폴더 이름을 입력해야 합니다.", "fileNameExistsError": "파일 또는 폴더 **{0}**이(가) 이 위치에 이미 있습니다. 다른 이름을 선택하세요.", "invalidFileNameError": "**{0}**(이)라는 이름은 파일 또는 폴더 이름으로 올바르지 않습니다. 다른 이름을 선택하세요.", "filePathTooLongError": "**{0}**(이)라는 이름을 사용하면 경로가 너무 길어집니다. 짧은 이름을 선택하세요.", - "compareWithSaved": "활성 파일을 저장된 파일과 비교", - "modifiedLabel": "{0}(디스크) ↔ {1}", "compareWithClipboard": "클립보드와 활성 파일 비교", "clipboardComparisonLabel": "클립보드 ↔ {0}" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index f77f75c5013..3ba45c45801 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "첫 번째 파일을 열어서 경로를 복사합니다.", - "openFileToReveal": "첫 번째 파일을 열어서 나타냅니다." + "revealInWindows": "탐색기에 표시", + "revealInMac": "Finder에 표시", + "openContainer": "상위 폴더 열기", + "saveAs": "다른 이름으로 저장...", + "save": "저장", + "saveAll": "모두 저장", + "removeFolderFromWorkspace": "작업 영역에서 폴더 삭제", + "modifiedLabel": "{0}(디스크) ↔ {1}", + "openFileToReveal": "첫 번째 파일을 열어서 나타냅니다.", + "openFileToCopy": "첫 번째 파일을 열어서 경로를 복사합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 64e3a748c1d..f166c5489ca 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "편집기", "formatOnSave": "파일 저장 시 서식을 지정합니다. 포맷터를 사용할 수 있어야 하며, 파일이 자동으로 저장되지 않아야 하고, 편집기가 종료되지 않아야 합니다.", "explorerConfigurationTitle": "파일 탐색기", - "openEditorsVisible": "열려 있는 편집기 창에 표시되는 편집기 수입니다. 창을 숨기려면 0으로 설정합니다.", - "dynamicHeight": "열려 있는 편집기 섹션의 높이가 요소 수에 따라 동적으로 조정되는지 여부를 제어합니다.", "autoReveal": "탐색기에서 파일을 열 때 자동으로 표시하고 선택할지를 제어합니다.", "enableDragAndDrop": "탐색기에서 끌어서 놓기를 통한 파일 및 폴더 이동을 허용하는지를 제어합니다.", "confirmDragAndDrop": "끌어서 놓기를 사용하여 파일 및 폴더를 이동하기 위해 탐색기에서 확인을 요청해야 하는지 제어합니다.", diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 6cf353ae712..33af3c52303 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,10 @@ // Do not edit this file. It is machine generated. { "userGuide": "오른쪽 편집기 도구 모음의 작업을 사용하여 변경 내용을 **실행 취소**하거나 디스크의 콘텐츠를 변경 내용으로 **덮어쓰기**", - "discard": "삭제", "overwrite": "덮어쓰기", "retry": "다시 시도", - "readonlySaveError": "'{0}'을(를) 저장하지 못했습니다. 파일이 쓰기 보호되어 있습니다. 보호를 제거하려면 '덮어쓰기'를 선택하세요.", + "discard": "삭제", + "permissionDeniedSaveError": "저장 실패 '{0}': 권한 부족. 관리자로 다시 시도하려면 '관리자로 다시 시도'를 선택하세요.", "genericSaveError": "'{0}'을(를) 저장하지 못했습니다. {1}", "staleSaveError": "'{0}'을(를) 저장하지 못했습니다. 디스크의 내용이 최신 버전입니다. 버전을 디스크에 있는 버전과 비교하려면 **비교**를 클릭하세요.", "compareChanges": "비교", diff --git a/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 56030126c94..3f6a56914c0 100644 --- a/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "열려 있는 편집기", "openEditosrSection": "열려 있는 편집기 섹션", - "dirtyCounter": "{0}이(가) 저장되지 않음", - "saveAll": "모두 저장", - "closeAllUnmodified": "미수정 항목 닫기", - "closeAll": "모두 닫기", - "compareWithSaved": "저장된 항목과 비교", - "close": "닫기", - "closeOthers": "기타 항목 닫기" + "dirtyCounter": "{0}이(가) 저장되지 않음" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..c6b46a532f7 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "로그(메인)", + "rendererLog": "로그(창)", + "extensionsLog": "로그(확장 호스트)", + "developer": "개발자" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..e36190cd574 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "로그 폴더 열기", + "showLogs": "로그 표시...", + "mainProcess": "기본", + "sharedProcess": "공유", + "rendererProcess": "창", + "selectProcess": "프로세스 선택", + "setLogLevel": "로그 수준 설정", + "trace": "Trace", + "debug": "디버그", + "info": "정보", + "warn": "경고", + "err": "오류", + "critical": "Critical", + "off": "Off" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/kor/src/vs/workbench/parts/markers/common/messages.i18n.json index f9e867de14d..f0b9f22340c 100644 --- a/i18n/kor/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "보기", - "problems.view.toggle.label": "설정/해제 문제", - "problems.view.focus.label": "포커스 문제", "problems.panel.configuration.title": "문제 보기", "problems.panel.configuration.autoreveal": "문제 보기를 열 때 문제 보기에 자동으로 파일이 표시되어야 하는지를 제어합니다.", "markers.panel.title.problems": "문제", diff --git a/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..921f1b58efc --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "출력", + "logViewer": "로그 표시기", + "viewCategory": "보기", + "clearOutput.label": "출력 내용 지우기" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/kor/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..9261a8ba1e2 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - 출력" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 188fd9c37da..9dc8bd95b1f 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "자연어 검색을 사용해 보세요!", "defaultSettings": "설정을 오른쪽 편집기에 넣어서 덮어씁니다.", "noSettingsFound": "설정을 찾을 수 없습니다.", "settingsSwitcherBarAriaLabel": "설정 전환기", "userSettings": "사용자 설정", "workspaceSettings": "작업 영역 설정", - "folderSettings": "폴더 설정", - "enableFuzzySearch": "자연어 검색 사용" + "folderSettings": "폴더 설정" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/kor/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index de4c67a1e30..90960b4f14d 100644 --- a/i18n/kor/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "일반적으로 사용되는 설정", - "mostRelevant": "가장 관련 있는 항목", "defaultKeybindingsHeader": "키 바인딩을 키 바인딩 파일에 배치하여 덮어씁니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index 0be24d926bb..c631d0cd782 100644 --- a/i18n/kor/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "보기", "commandsHandlerDescriptionDefault": "명령 표시 및 실행", "gotoLineDescriptionMac": "줄 이동", "gotoLineDescriptionWin": "줄 이동", diff --git a/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 4b848835e91..29d19883f06 100644 --- a/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,6 @@ "toggleGitViewlet": "Git 표시", "source control": "소스 제어", "toggleSCMViewlet": "SCM 표시", - "view": "보기" + "view": "보기", + "scmConfigurationTitle": "SCM" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json index b045a022b27..68680603aad 100644 --- a/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "이전 검색어 표시", "showSearchViewlet": "검색 표시", "findInFiles": "파일에서 찾기", - "findInFilesWithSelectedText": "선택한 텍스트가 있는 파일에서 찾기", "replaceInFiles": "파일에서 바꾸기", - "replaceInFilesWithSelectedText": "선택한 텍스트가 있는 파일에서 바꾸기", "RefreshAction.label": "새로 고침", "CollapseDeepestExpandedLevelAction.label": "모두 축소", "ClearSearchResultsAction.label": "지우기", diff --git a/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index 9b239f6fd5f..4233df18482 100644 --- a/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -7,10 +7,11 @@ "showTriggerActions": "작업 영역에서 기호로 이동...", "name": "검색", "search": "검색", + "showSearchViewlet": "검색 표시", "view": "보기", + "findInFiles": "파일에서 찾기", "openAnythingHandlerDescription": "파일로 이동", "openSymbolDescriptionNormal": "작업 영역에서 기호로 이동", - "searchOutputChannelTitle": "검색", "searchConfigurationTitle": "검색", "exclude": "검색에서 파일 및 폴더를 제외하도록 GLOB 패턴을 구성합니다. files.exclude 설정에서 모든 GLOB 패턴을 상속합니다.", "exclude.boolean": "파일 경로를 일치시킬 GLOB 패턴입니다. 패턴을 사용하거나 사용하지 않도록 설정하려면 true 또는 false로 설정하세요.", diff --git a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..37d5355620e --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "기본 설정" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 582f284bf10..7a0857e6f8d 100644 --- a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "코드 조각의 언어 선택", - "openSnippet.errorOnCreate": "{0}을(를) 만들 수 없음", - "openSnippet.label": "사용자 코드 조각 열기", - "preferences": "기본 설정", "snippetSchema.json.default": "빈 코드 조각", "snippetSchema.json": "사용자 코드 조각 구성", "snippetSchema.json.prefix": "IntelliSense에서 코드 조각을 선택할 때 사용할 접두사입니다.", diff --git a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..587455cd532 --- /dev/null +++ b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "사용자 코드 조각" +} \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index c423047529b..b33ab06f4bb 100644 --- a/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "`contributes.{0}.language`에 알 수 없는 언어가 있습니다. 제공된 값: {1}", "invalid.path.0": "`contributes.{0}.path`에 문자열이 필요합니다. 제공된 값: {1}", + "invalid.language": "`contributes.{0}.language`에 알 수 없는 언어가 있습니다. 제공된 값: {1}", "invalid.path.1": "확장 폴더({2})에 포함할 `contributes.{0}.path`({1})가 필요합니다. 확장이 이식 불가능해질 수 있습니다.", "vscode.extension.contributes.snippets": "코드 조각을 적용합니다.", "vscode.extension.contributes.snippets-language": "이 코드 조각이 적용되는 언어 식별자입니다.", "vscode.extension.contributes.snippets-path": "코드 조각 파일의 경로입니다. 이 경로는 확장 폴더의 상대 경로이며 일반적으로 './snippets/'로 시작합니다.", "badVariableUse": "'{0}' 확장의 1개 이상의 코드 조각은 snippet-variables 및 snippet-placeholders와 혼동하기 쉽습니다(자세한 내용은 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax를 참조하세요).", "badFile": "코드 조각 파일 \"{0}\"을(를) 읽을 수 없습니다.", - "source.snippet": "사용자 코드 조각", "detail.snippet": "{0}({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index 32869d50216..8483a433151 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "터미널의 전경색입니다.", "terminalCursor.foreground": "터미널 커서의 전경색입니다.", "terminalCursor.background": "터미널 커서의 배경색입니다. 블록 커서와 겹친 문자의 색상을 사용자 정의할 수 있습니다.", - "terminal.selectionBackground": "터미널의 선택 영역 배경색입니다.", - "terminal.ansiColor": "터미널의 '{0}' ANSI 색입니다." + "terminal.selectionBackground": "터미널의 선택 영역 배경색입니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index b21bf5b25fa..ed40b375339 100644 --- a/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "사용자 지정 단추를 선택하여 기본 터미널 셸을 변경할 수 있습니다.", "customize": "사용자 지정", "cancel": "취소", - "never again": "다시 표시 안 함", "terminal.integrated.chooseWindowsShell": "기본으로 설정할 터미널 셸을 선택하세요. 나중에 설정에서 이 셸을 변경할 수 있습니다.", "terminalService.terminalCloseConfirmationSingular": "활성 터미널 세션이 있습니다. 종료할까요?", "terminalService.terminalCloseConfirmationPlural": "{0}개의 활성 터미널 세션이 있습니다. 종료할까요?" diff --git a/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json index bb502a90cb6..485a7f763c8 100644 --- a/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/kor/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "명령 팔레트...", "settings": "설정", "keyboardShortcuts": "바로 가기 키(&&K)", + "userSnippets": "사용자 코드 조각", "selectTheme.label": "색 테마", "themes.selectIconTheme.label": "파일 아이콘 테마", "not available": "업데이트를 사용할 수 없음", diff --git a/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index d48fe3d053e..196d40bcdb5 100644 --- a/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "파일이 디렉터리입니다.", + "fileNotModifiedError": "파일 수정 안 됨", "fileBinaryError": "파일이 이진인 것 같으므로 테스트로 열 수 없습니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/kor/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index db19c348ac8..56bf06242e3 100644 --- a/i18n/kor/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "{0}에 대한 변경 내용을 저장할까요?", "saveChangesMessages": "다음 {0}개 파일에 대한 변경 내용을 저장할까요?", - "moreFile": "...1개의 추가 파일이 표시되지 않음", - "moreFiles": "...{0}개의 추가 파일이 표시되지 않음", "saveAll": "모두 저장(&&S)", "save": "저장(&&S)", "dontSave": "저장 안 함(&&N)", diff --git a/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index d365ddcbff5..ae661bf4187 100644 --- a/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "현재 선택한 색 테마에서 색을 재정의합니다.", - "editorColors": "현재 선택된 색 테마에서 편집기 색상과 글꼴 스타일을 재정의합니다.", "editorColors.comments": "주석의 색 및 스타일을 설정합니다.", "editorColors.strings": "문자열 리터럴의 색 및 스타일을 설정합니다.", "editorColors.keywords": "키워드의 색과 스타일을 설정합니다.", @@ -19,5 +18,6 @@ "editorColors.types": "형식 선언 및 참조의 색 및 스타일을 설정합니다.", "editorColors.functions": "함수 선언 및 참조의 색 및 스타일을 설정합니다.", "editorColors.variables": "변수 선언 및 참조의 색 및 스타일을 설정합니다.", - "editorColors.textMateRules": "textmate 테마 설정 규칙을 사용하여 색 및 스타일을 설정합니다(고급)." + "editorColors.textMateRules": "textmate 테마 설정 규칙을 사용하여 색 및 스타일을 설정합니다(고급).", + "editorColors": "현재 선택된 색 테마에서 편집기 색상과 글꼴 스타일을 재정의합니다." } \ No newline at end of file diff --git a/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index e836eb6be3f..a2425123fe5 100644 --- a/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/kor/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "작업 영역 구성 파일에 쓸 수 없습니다. 파일을 열고 오류/경고를 수정한 다음 다시 시도하세요.", "errorWorkspaceConfigurationFileDirty": "파일이 변경되어 작업 영역 구성 파일에 쓸 수 없습니다. 저장하고 다시 시도하세요.", "openWorkspaceConfigurationFile": "작업 영역 구성 파일 열기", - "close": "닫기", - "enterWorkspace.close": "닫기", - "enterWorkspace.dontShowAgain": "다시 표시 안 함", - "enterWorkspace.moreInfo": "추가 정보", - "enterWorkspace.prompt": "VS Code에서 여러 개의 파일을 작업하는 방법에 대해 자세히 알아보세요." + "close": "닫기" } \ No newline at end of file diff --git a/i18n/ptb/extensions/git/out/autofetch.i18n.json b/i18n/ptb/extensions/git/out/autofetch.i18n.json index 1c3c1cf318d..5df527f070d 100644 --- a/i18n/ptb/extensions/git/out/autofetch.i18n.json +++ b/i18n/ptb/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Sim", + "read more": "Ler Mais", "no": "Não", - "not now": "Agora Não", - "suggest auto fetch": "Deseja habilitar o autopreenchimento dos repositórios Git?" + "not now": "Pergunte-me depois", + "suggest auto fetch": "Você gostaria que o Code executasse periodicamente `git fetch`?" } \ No newline at end of file diff --git a/i18n/ptb/extensions/git/out/commands.i18n.json b/i18n/ptb/extensions/git/out/commands.i18n.json index 03a6223ad1d..b56c7d4a6f4 100644 --- a/i18n/ptb/extensions/git/out/commands.i18n.json +++ b/i18n/ptb/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\n é IRREVERSÍVEL, o conjunto de trabalho atual será PERDIDO PARA SEMPRE.", "yes discard tracked": "Descartar 1 arquivo controlado", "yes discard tracked multiple": "Descartar arquivos {0} controlados", + "unsaved files single": "O seguinte arquivo não foi salvo: [0}.\n\nGostaria de salvá-lo antes de executar o commit?", + "unsaved files": "Existem {0} arquivos não salvos.\n\nGostaria de salvá-los antes de executar o commit?", + "save and commit": "Salvar Tudo & Confirmar", + "commit": "Confirmar de qualquer maneira", "no staged changes": "Não há nenhuma modificação escalonada para confirmar.\n\nGostaria de escalonar automaticamente todas as suas alterações e confirmá-las diretamente?", "always": "Sempre", "no changes": "Não há mudanças para confirmar.", @@ -64,12 +68,13 @@ "no remotes to pull": "O seu repositório não possui remotos configurados para efetuar pull.", "pick remote pull repo": "Selecione um remoto para efeutar o pull da ramificação", "no remotes to push": "O seu repositório não possui remotos configurados para efetuar push.", - "push with tags success": "Envio de rótulos finalizado com sucesso.", "nobranch": "Por favor, faça checkout em um ramo para fazer push em um remoto.", + "confirm publish branch": "O branch '{0}' não possui um branch superior. Você quer publicar este branch?", + "ok": "OK", + "push with tags success": "Envio de rótulos finalizado com sucesso.", "pick remote": "Pegue um remoto para publicar o ramo '{0}':", "sync is unpredictable": "Esta ação vai fazer push e pull nos commits de e para '{0}'.", - "ok": "OK", - "never again": "Ok, Nunca Mostrar Novamente", + "never again": "OK, Não Mostrar Novamente", "no remotes to publish": "Seu repositório não possui remotos configurados para publicação.", "no changes stash": "Não há nenhuma mudança para esconder.", "provide stash message": "Opcionalmente forneça uma mensagem para esconder.", diff --git a/i18n/ptb/extensions/git/out/repository.i18n.json b/i18n/ptb/extensions/git/out/repository.i18n.json index 214c9e1d36f..df6cf8fd751 100644 --- a/i18n/ptb/extensions/git/out/repository.i18n.json +++ b/i18n/ptb/extensions/git/out/repository.i18n.json @@ -27,6 +27,6 @@ "staged changes": "Alterações em Etapas", "changes": "Alterações", "ok": "OK", - "neveragain": "Nunca Mostrar Novamente", + "neveragain": "Não mostrar novamente", "huge": "O repositório git em '{0}' tem muitas atualizações ativas, somente um subconjunto de funcionalidades do Git será habilitado." } \ No newline at end of file diff --git a/i18n/ptb/extensions/git/package.i18n.json b/i18n/ptb/extensions/git/package.i18n.json index 81db50ac04f..3f76d9389b0 100644 --- a/i18n/ptb/extensions/git/package.i18n.json +++ b/i18n/ptb/extensions/git/package.i18n.json @@ -54,12 +54,13 @@ "command.stashPopLatest": "Pop mais recente Stash", "config.enabled": "Se o git estiver habilitado", "config.path": "Caminho para o executável do git", + "config.autoRepositoryDetection": "Se os repositórios devem ser detectados automaticamente", "config.autorefresh": "Se a atualização automática estiver habilitada", "config.autofetch": "Se a recuperação automática estiver habilitada", "config.enableLongCommitWarning": "Se mensagens longas de confirmação devem ter aviso", "config.confirmSync": "Confirmar antes de sincronizar repositórios git", "config.countBadge": "Controla o contador de distintivos do git. 'todos' considera todas as alterações. 'rastreado' considera apenas as alterações controladas. 'desligado' desliga o contador.", - "config.checkoutType": "Controla quais tipos de ramos são listados quando executando `Checkout para... `. `todos` mostra todas as referências, `local` mostra apenas os ramos locais, `etiqueta` mostra apenas etiquetas e `remoto` mostra apenas os ramos remotos.", + "config.checkoutType": "Controla quais tipos de ramos são listados quando executando `Checkout para... `. `todos` mostra todas as referências, `local` mostra apenas os ramos locais, `etiquetas` mostra apenas etiquetas e `remoto` mostra apenas os ramos remotos.", "config.ignoreLegacyWarning": "Ignora o aviso de Git legado", "config.ignoreMissingGitWarning": "Ignora o aviso quando Git não existir.", "config.ignoreLimitWarning": "Ignora o aviso quando houver muitas alterações em um repositório", @@ -72,5 +73,6 @@ "colors.deleted": "Cor para recursos excluídos.", "colors.untracked": "Cor para recursos não controlados.", "colors.ignored": "Cor para recursos ignorados.", - "colors.conflict": "Cor para recursos com conflitos." + "colors.conflict": "Cor para recursos com conflitos.", + "colors.submodule": "Cor para recursos de sub-módulos." } \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript/out/commands.i18n.json b/i18n/ptb/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..01c9f9ae0d9 --- /dev/null +++ b/i18n/ptb/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Favor abrir uma pasta no VS Code para usar um projeto TypeScript ou JavaScript", + "typescript.projectConfigUnsupportedFile": "Não foi possível determinar o projeto TypeScript ou JavaScript. Tipo de arquivo não suportado", + "typescript.projectConfigCouldNotGetInfo": "Não foi possível determinar o projeto TypeScript ou JavaScript", + "typescript.noTypeScriptProjectConfig": "Arquivo não é parte de um projeto TypeScript", + "typescript.noJavaScriptProjectConfig": "Arquivo não é parte de um projeto JavaScript", + "typescript.configureTsconfigQuickPick": "Configurar tsconfig.json", + "typescript.configureJsconfigQuickPick": "Configurar jsconfig.json", + "typescript.projectConfigLearnMore": "Saiba Mais" +} \ No newline at end of file diff --git a/i18n/ptb/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/ptb/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..7e0ce09dfcd --- /dev/null +++ b/i18n/ptb/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "fixAllInFileLabel": "{0} (Reparar tudo no arquivo)" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/ptb/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/ptb/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/base/node/ps.i18n.json b/i18n/ptb/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..e8b9b91a595 --- /dev/null +++ b/i18n/ptb/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Coletando informações de CPU e memória. Isso pode demorar alguns segundos." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json index 52ffce48a73..3cb267503b9 100644 --- a/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/ptb/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Números de linhas são renderizados em números absolutos.", "lineNumbers.relative": "Números de linhas são renderizadas como distância em linhas até a posição do cursor.", "lineNumbers.interval": "Números de linhas são renderizados a cada 10 linhas.", - "lineNumbers": "Controla a exibição dos números de linha. Os valores possíveis são 'on', 'off' e 'relative'.", + "lineNumbers": "Controla a exibição dos números de linha. Os valores possíveis são 'on', 'off', 'relative' e 'interval'.", "rulers": "Renderiza réguas verticais após um certo número de caracteres de espaço. Use vários valores para várias réguas. Réguas não serão desenhadas se a matriz estiver vazia", "wordSeparators": "Caracteres que serão usados como separadores de palavras ao fazer navegação relacionada a palavras ou operações", "tabSize": "O número de espaços equivalentes a uma tabulação. Esta configuração é sobreposta com base no conteúdo do arquivo quando `editor.detectIndentation` está ligado.", @@ -40,9 +40,9 @@ "wordWrapColumn": "Controla a coluna de quebra de linha do editor quando editor.wordWrap` é 'wordWrapColumn' ou 'bounded'.", "wrappingIndent": "Controla o recuo de linhas quebradas. Pode ser \"none\", \"same\" ou \"indent\".", "mouseWheelScrollSensitivity": "Um multiplicador a ser usado em \"deltaX\" e \"deltaY\" dos eventos de rolagem do botão de rolagem do mouse", - "multiCursorModifier.ctrlCmd": "Mapeia para 'Control' no Windows e Linux e 'Command' no OSX.", - "multiCursorModifier.alt": "Mapeia para 'Alt' em Windows e Linux e 'Option' em OSX.", - "multiCursorModifier": "O modificador a ser usado para adicionar vários cursores com o mouse. `ctrlCmd` mapeia 'Control' no Windows e Linux e 'Command' no OSX. Os gestos do mouse Ir para definição e Abrir Link irão adaptar-se tal maneira que eles não entrem em conflito com o modificador multicursor.", + "multiCursorModifier.ctrlCmd": "Mapeia para 'Control' no Windows e Linux e para 'Command' no macOS.", + "multiCursorModifier.alt": "Mapeia para 'Alt' em Windows e Linux e para 'Option' em macOS.", + "multiCursorModifier": "O modificador a ser usado para adicionar vários cursores com o mouse. `ctrlCmd` mapeia para 'Control' no Windows e Linux e para 'Command' no macOS. Os gestos do mouse Ir para definição e Abrir Link irão adaptar-se de forma que eles não entrem em conflito com o modificador multicursor.", "quickSuggestions.strings": "Habilitar sugestões rápidas dentro de strings.", "quickSuggestions.comments": "Habilitar sugestões rápidas dentro de comentários.", "quickSuggestions.other": "Habilitar sugestões rápidas fora de strings e comentários.", @@ -72,6 +72,7 @@ "cursorBlinking": "Controla o estilo de animação do cursor, os valores possíveis são 'blink', 'smooth', 'phase', 'expand' e 'solid'", "mouseWheelZoom": "Alterar o zoom da fonte editor quando utilizada a roda do mouse e pressionando Ctrl", "cursorStyle": "Controla o estilo do cursor, os valores aceitos são 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'", + "lineCursorWidth": "Controla a largura do cursor quando editor.cursorStyle está definido como 'line'", "fontLigatures": "Habilita ligaduras de fontes", "hideCursorInOverviewRuler": "Controla se o cursor deve ficar oculto na régua de visão geral.", "renderWhitespace": "Controla como o editor deve rendenizar caracteres de espaços em branco, possibilidades são 'none', 'boundary' e 'all'. A opção 'boundary' não rendeniza espaços simples entre palavras.", diff --git a/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json index 434fe65993d..27de662d885 100644 --- a/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/ptb/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,7 @@ { "lineHighlight": "Cor de fundo para a posição do cursor na seleção de linhas.", "lineHighlightBorderBox": "Cor de fundo para a borda em volta da linha na posição do cursor", - "rangeHighlight": "Cor de fundo dos ranges selecionados, assim como abertura instantânea e descoberta de recursos ", + "rangeHighlight": "Cor de fundo dos intervalos selecionados, assim como da abertura instantânea e localização de recursos. A cor não deve ser opaca para evitar esconder as decorações subjacentes", "caret": "Cor do cursor no editor.", "editorCursorBackground": "A cor de fundo do cursor do editor. Permite customizar a cor de um caractere sobreposto pelo bloco do cursor.", "editorWhitespaces": "Cor dos caracteres em branco no editor", diff --git a/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json index d05aeee6c34..5be9785fd64 100644 --- a/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Ir para o Próximo Erro ou Aviso", - "markerAction.previous.label": "Ir para o Erro ou Aviso Anterior", + "markerAction.next.label": "Ir para o Próximo Problema (Erro, Aviso, Informação)", + "markerAction.previous.label": "Ir para o Problema Anterior (Erro, Aviso, Informação)", "editorMarkerNavigationError": "Ferramenta de marcação de edição apresentando error na cor ", "editorMarkerNavigationWarning": "Ferramenta de marcação de edição apresentando adventência na cor", "editorMarkerNavigationInfo": "Cor de informação da ferramenta de navegação do marcador do editor.", diff --git a/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 6ccc873b02c..99acb12e285 100644 --- a/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/ptb/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Cor de fundo de um símbolo durante acesso de leitura, como ao ler uma variável.", - "wordHighlightStrong": "Cor de fundo de um símbolo durante acesso de escrita, como ao escrever uma variável.", + "wordHighlight": "Cor de fundo de um símbolo durante o acesso de leitura, como ao ler uma variável. A cor não deve ser opaca para não ocultar as decorações subjacentes.", + "wordHighlightStrong": "Cor de fundo de um símbolo durante o acesso de escrita, como ao escrever uma variável. A cor não deve ser opaca para não ocultar as decorações subjacentes.", "overviewRulerWordHighlightForeground": "Visão geral da cor do marcador da régua para destaques de símbolos.", "overviewRulerWordHighlightStrongForeground": "Visão geral da cor do marcador da régua para gravação de destaques de símbolos.", "wordHighlight.next.label": "Ir para o próximo símbolo em destaque", diff --git a/i18n/ptb/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/ptb/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 28adcb87065..5ade9a9290c 100644 --- a/i18n/ptb/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/ptb/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "'{0}' nao é um identificador de menu válido ", "missing.command": "Identificador do comando para ser executado. O comando deve ser declarado na seção de 'Comandos'", "missing.altCommand": "Referências ao item de menu no alt-command '{0}' qual nao é definido na sessão 'comandos'", - "dupe.command": "Itens de referencias do mesmo comando como padrão e alt-command", - "nosupport.altCommand": "Desculpe, mas atualmente somente o groupo 'navegação' do menu 'editor/título' suporta alt-commands" + "dupe.command": "Itens de referencias do mesmo comando como padrão e alt-command" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json b/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json index ed9e5aca99c..c7a8e620a99 100644 --- a/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/ptb/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,36 @@ "diff": "Comparar dois arquivos entre si.", "add": "Adicione pasta(s) para a última janela ativa.", "goto": "Abra um arquivo no caminho sobre a linha especificada e a posição do caractere.", - "locale": "Para localização utilize (ex. en-US ou zh-TW).", "newWindow": "Força uma nova instância do Código.", - "performance": "Comece com o 'Desenvolvedor: Desempenho de inicialização' comando habilitado.", - "prof-startup": "Rodar o CPU profiler durante a inicialização", - "inspect-extensions": "Permite depuração e criação de perfis de extensões. Verifique as ferramentas de desenvolvimento para a conexão uri.", - "inspect-brk-extensions": "Permitir depuração e criação de perfil de extensões com o host de extensão em pausa após o início. Verifique as ferramentas do desenvolvedor para a conexão uri.", "reuseWindow": "Forçar a abertura de um arquivo ou pasta na última janela ativa", - "userDataDir": "Especifica o diretório que os dados do usuário serão mantidos, útil quando estiver rodando como root.", - "log": "Nível de log a ser utilizado. O padrão é 'info'. Os valores permitidos são 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", - "verbose": "Imprimir a saída detalhada (Implica -- esperar).", "wait": "Espere pelos arquivos a serem fechados antes de retornar.", + "locale": "Para localização utilize (ex. en-US ou zh-TW).", + "userDataDir": "Especifica o diretório que os dados do usuário serão mantidos, útil quando estiver rodando como root.", + "version": "Versão de impressão", + "help": "Uso de impressão.", "extensionHomePath": "Defina o caminho raíz para as extensões.", "listExtensions": "Lista de extensões instaladas", "showVersions": "Exibir versões de extensões instaladas, quando estiver usando --list-extension", "installExtension": "Instala uma extensão.", "uninstallExtension": "Desinstala uma extensão.", "experimentalApis": "Permite recursos de api propostos para uma extensão.", - "disableExtensions": "Desabilita todas as extensões instaladas.", - "disableGPU": "Desabilita aceleração de hardware da GPU.", + "verbose": "Imprimir a saída detalhada (Implica -- esperar).", + "log": "Nível de log a ser utilizado. O padrão é 'info'. Os valores permitidos são 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.", "status": "Utilização do processo de impressão e informações de diagnóstico.", - "version": "Versão de impressão", - "help": "Uso de impressão.", + "performance": "Comece com o 'Desenvolvedor: Desempenho de inicialização' comando habilitado.", + "prof-startup": "Rodar o CPU profiler durante a inicialização", + "disableExtensions": "Desabilita todas as extensões instaladas.", + "inspect-extensions": "Permite depuração e criação de perfis de extensões. Verifique as ferramentas de desenvolvimento para a conexão uri.", + "inspect-brk-extensions": "Permitir depuração e criação de perfil de extensões com o host de extensão em pausa após o início. Verifique as ferramentas do desenvolvedor para a conexão uri.", + "disableGPU": "Desabilita aceleração de hardware da GPU.", + "uploadLogs": "Envia os registros de atividade da sessão atual para um destino seguro.", + "issue": "Reportar um problema.", "usage": "Uso", "options": "opções", "paths": "caminhos", - "optionsUpperCase": "Opções" + "stdinWindows": "Para ler a saída de outro programa, adicione '-' ao final (ex. 'echo Hello World | {0} -')", + "stdinUnix": "Para ler do stdin, adicione '-' ao final (ex. 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Opções", + "extensionsManagement": "Gerenciamento de Extensões", + "troubleshooting": "Solução de problemas" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 98c0be5cdcb..4fe84adc13b 100644 --- a/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/ptb/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Extensão inválida: pacote.json nao é um arquivo JSON válido", - "restartCodeLocal": "Por favor reinicie Code antes de reinstalar {0}.", + "restartCode": "Por favor reinicie Code antes de reinstalar {0}.", "installingOutdatedExtension": "Uma nova versão desta extensão já está instalada. Você deseja sobrescrever esta instalação com a versão mais antiga?", "override": "Sobrescrever", "cancel": "Cancelar", - "notFoundCompatible": "Não foi possível instalar porque a extensão '{0}' compatível com a versão atual '{1}' do VS Code não foi encontrada.", - "quitCode": "Não foi possível instalar porque uma instância obsoleta da extensão ainda está em execução. Por favor, pare e inicie o VS Code antes de reinstalar.", - "exitCode": "Não foi possível instalar porque uma instância obsoleta da extensão ainda está em execução. Por favor, pare e inicie o VS Code antes de reinstalar.", + "errorInstallingDependencies": "Erro ao instalar dependências. {0}", + "notFoundCompatible": "Não foi possível instalar '{0}; não existe nenhuma versão compatível com o VSCode '{1}'.", "notFoundCompatibleDependency": "Não foi possível instalar porque a extensão dependente '{0}' compatível com a versão atual '{1}' do VS Code não foi encontrada.", + "quitCode": "Não foi possível instalar a extensão. Por favor, saia e reinicie o VS Code antes de reinstalar.", + "exitCode": "Não foi possível instalar a extensão. Por favor, saia e reinicie o VS Code antes de reinstalar.", "uninstallDependeciesConfirmation": "Gostaria de desinstalar '{0}' somente, ou suas dependências também?", "uninstallOnly": "Apenas", "uninstallAll": "Todos", diff --git a/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json b/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..f0c45d298c0 --- /dev/null +++ b/i18n/ptb/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Área de Trabalho", + "multiSelectModifier.ctrlCmd": "Mapeia para 'Control' no Windows e Linux e para 'Command' no macOS.", + "multiSelectModifier.alt": "Mapeia para 'Alt' no Windows e Linux e 'Option' no macOS.", + "multiSelectModifier": "O modificador a ser usado para adicionar um item à múltiplas seleções com o mouse (por exemplo, em árvores e listas, se suportado) `ctrlCmd` mapeia para 'Control' no Windows e Linux e 'Command' no macOS. Os gestos do mouse para 'Abrir do Lado' - se suportado - irá adaptar-se de forma que eles não entrem em conflito com o modificador de múltiplas seleções." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/message/common/message.i18n.json b/i18n/ptb/src/vs/platform/message/common/message.i18n.json index 620c63edd07..0d24937956e 100644 --- a/i18n/ptb/src/vs/platform/message/common/message.i18n.json +++ b/i18n/ptb/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Fechar", "later": "Mais tarde", - "cancel": "Cancelar" + "cancel": "Cancelar", + "moreFile": "... 1 arquivo adicional não está mostrado", + "moreFiles": "... {0} arquivos adicionais não estão mostrados" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json index 6f399a88a06..ad9e4de8759 100644 --- a/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/ptb/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,12 @@ "editorWidgetBorder": "Cor da borda das ferramentas do editor. A cor é usada somente se a ferramenta escolhe ter uma borda e a cor não é substituída por uma ferramenta.", "editorSelectionBackground": "Cor de seleção do editor.", "editorSelectionForeground": "Cor do texto selecionado para alto contraste.", - "editorInactiveSelection": "Cor de seleção em um editor inativo.", - "editorSelectionHighlight": "Cor de regiões com o mesmo conteúdo da seleção.", + "editorInactiveSelection": "Cor da seleção em um editor inativo. A cor não deve ser opaca para não esconder decorações subjacentes.", + "editorSelectionHighlight": "Cor para regiões com o mesmo conteúdo da seleção. A cor não deve ser opaca para não esconder decorações subjacentes.", "editorFindMatch": "Cor da correspondência de pesquisa atual.", - "findMatchHighlight": "Cor dos outros resultados de pesquisa.", - "findRangeHighlight": "Cor da faixa que limita a pesquisa.", - "hoverHighlight": "Realçar abaixo da palavra onde é mostrado item flutuante", + "findMatchHighlight": "Cor dos outros termos que correspondem ao da pesquisa. A cor não deve ser opaca para não esconder as decorações subjacentes.", + "findRangeHighlight": "Cor do intervalo limitando a pesquisa. A cor não deve ser opaca para não esconder decorações subjacentes.", + "hoverHighlight": "Destaque abaixo da palavra para qual um flutuador é mostrado. A cor não deve ser opaca para não esconder decorações subjacentes.", "hoverBackground": "Cor de fundo para o item flutuante do editor", "hoverBorder": "Cor da borda para o item flutuante do editor.", "activeLinkForeground": "Cor dos links ativos.", @@ -76,12 +76,12 @@ "diffEditorRemoved": "Cor de fundo para texto que foi removido.", "diffEditorInsertedOutline": "Cor de contorno para o texto que foi inserido.", "diffEditorRemovedOutline": "Cor de contorno para o texto que foi removido.", - "mergeCurrentHeaderBackground": "Cor de fundo de cabeçalho atual em conflito de mesclagem em linha.", - "mergeCurrentContentBackground": "Cor de fundo de conteúdo atual em conflito de mesclagem em linha.", - "mergeIncomingHeaderBackground": "Cor de fundo de cabeçalho de entrada em conflito de mesclagem em linha.", - "mergeIncomingContentBackground": "Cor de fundo de conteúdo de entrada em conflito de mesclagem em linha.", - "mergeCommonHeaderBackground": "Ancestral comum da cor de fundo do cabeçalho em conflitos de mesclagem inline.", - "mergeCommonContentBackground": "Ancestral comum da cor de fundo do conteúdo em conflitos de mesclagem inline. ", + "mergeCurrentHeaderBackground": "Fundo do cabeçalho atual em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", + "mergeCurrentContentBackground": "Fundo do conteúdo atual em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", + "mergeIncomingHeaderBackground": "Fundo do cabeçalho entrante em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", + "mergeIncomingContentBackground": "Fundo do conteúdo entrante em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", + "mergeCommonHeaderBackground": "Fundo comum do cabeçalho antepassado em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", + "mergeCommonContentBackground": "Fundo comum do conteúdo antepassado em conflitos de merge inline. A cor não deve ser opaca para não esconder decorações subjacentes.", "mergeBorder": "Cor da borda dos cabeçalhos e separadores estão em conflito de mesclagem em linha.", "overviewRulerCurrentContentForeground": "Cor de fundo de régua de visuaização atual em conflito de mesclagem em linha.", "overviewRulerIncomingContentForeground": "Cor de fundo de régua de visuaização de entrada em conflito de mesclagem em linha.", diff --git a/i18n/ptb/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/ptb/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..299a2d2ab1d --- /dev/null +++ b/i18n/ptb/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "a propriedade `{0}` é obrigatória e deve ser do tipo `string`", + "optstring": "a propriedade `{0}` é opcional ou deve ser do tipo `string`" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..d2677dfdc5b --- /dev/null +++ b/i18n/ptb/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Executando Salvamento de Participantes..." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/ptb/src/vs/workbench/api/node/extHostTreeViews.i18n.json index d5ca67a9353..2d6a1561774 100644 --- a/i18n/ptb/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/ptb/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "treeView.notRegistered": "Nenhuma visualização de árvore com id '{0}' registrado.", - "treeItem.notFound": "Nenhum item de árvore com id '{0}' encontrado.", - "treeView.duplicateElement": "Elemento {0} já está registrado" + "treeView.duplicateElement": "Elemento com id {0} já está registrado" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/ptb/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index ee4fc530361..3bc4ff33bb9 100644 --- a/i18n/ptb/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Alternar Localização da Barra Lateral", + "toggleSidebarPosition": "Alternar a Posição da Barra Lateral", "view": "Exibir" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 18546fb98ab..84f170bd32c 100644 --- a/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Abrir arquivo...", "openFolder": "Abrir Pasta...", "openFileFolder": "Abrir...", - "addFolderToWorkspace": "Adicionar pasta ao espaço de trabalho...", - "add": "&& Adicionar", - "addFolderToWorkspaceTitle": "Adicionar pasta ao espaço de trabalho", "globalRemoveFolderFromWorkspace": "Remover pasta da área de trabalho", - "removeFolderFromWorkspace": "Remover pasta da área de trabalho", - "openFolderSettings": "Abrir configurações da pasta", "saveWorkspaceAsAction": "Salvar o espaço de trabalho como...", "save": "&&Salvar", "saveWorkspace": "Salvar o espaço de trabalho", "openWorkspaceAction": "Abrir o Espaço de Trabalho...", "openWorkspaceConfigFile": "Abrir o Arquivo de Configuração do Espaço de Trabalho", - "openFolderAsWorkspaceInNewWindow": "Abrir a pasta como espaço de trabalho em nova janela", - "workspaceFolderPickerPlaceholder": "Selecione a pasta de trabalho" + "openFolderAsWorkspaceInNewWindow": "Abrir a pasta como espaço de trabalho em nova janela" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/ptb/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..34b9d5b4435 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Adicionar pasta ao espaço de trabalho...", + "add": "&&Adicionar", + "addFolderToWorkspaceTitle": "Adicionar pasta ao espaço de trabalho", + "workspaceFolderPickerPlaceholder": "Selecione a pasta do espaço de trabalho" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index d1d8a425227..229a03e2233 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,18 @@ "groupThreePicker": "Mostrar editores no terceiro grupo", "allEditorsPicker": "Mostrar todos editores abertos", "view": "Exibir", - "file": "Arquivo" + "file": "Arquivo", + "close": "Fechar", + "closeOthers": "Fechar Outros", + "closeRight": "Fechar à direita", + "closeAllUnmodified": "Fechar Não Modificados", + "closeAll": "Fechar todos", + "keepOpen": "Manter aberto", + "toggleInlineView": "Alternar para exibição embutida", + "showOpenedEditors": "Mostrar editores abertos", + "keepEditor": "Manter editor", + "closeEditorsInGroup": "Fechar todos editores no grupo", + "closeUnmodifiedEditors": "Fechar os Editores Não Modificados no Grupo", + "closeOtherEditors": "Fechar outros editores", + "closeRightEditors": "Fechar editores à direita" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 5035a541040..d43b455c264 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Fechar editor", "revertAndCloseActiveEditor": "Reverter e fechar editor", "closeEditorsToTheLeft": "Fechar editores à esquerda ", - "closeEditorsToTheRight": "Fechar editores à direita", "closeAllEditors": "Fechar todos editores", - "closeUnmodifiedEditors": "Fechar os Editores Não Modificados no Grupo", "closeEditorsInOtherGroups": "Fechar editores nos outros grupos", - "closeOtherEditorsInGroup": "Fechar outros editores", - "closeEditorsInGroup": "Fechar todos editores no grupo", "moveActiveGroupLeft": "Mover grupo de editores para esquerda", "moveActiveGroupRight": "Mover grupo de editores para direita", "minimizeOtherEditorGroups": "Minimizar outros grupos de editores", "evenEditorGroups": "Igualar larguras de grupos de editores", "maximizeEditor": "Maximizar grupo de editor e ocultar barra lateral", - "keepEditor": "Manter editor", "openNextEditor": "Abrir próximo editor", "openPreviousEditor": "Abrir editor anterior", "nextEditorInGroup": "Abrir próximo editor no grupo", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Mostrar editores no primeiro grupo", "showEditorsInSecondGroup": "Mostrar editores no segundo grupo", "showEditorsInThirdGroup": "Mostrar editores no terceiro grupo", - "showEditorsInGroup": "Mostrar editores no grupo", "showAllEditors": "Mostrar todos editores", "openPreviousRecentlyUsedEditorInGroup": "Abrir o Editor Anterior Recentemente Usado no Grupo", "openNextRecentlyUsedEditorInGroup": "Abrir o Próximo Editor Recentemente Usado no Grupo", @@ -54,5 +48,8 @@ "moveEditorLeft": "Mover o Editor para a Esquerda", "moveEditorRight": "Mover o Editor para a Direita", "moveEditorToPreviousGroup": "Mover o Editor para o Grupo Anterior", - "moveEditorToNextGroup": "Mover o Editor para o Próximo Grupo" + "moveEditorToNextGroup": "Mover o Editor para o Próximo Grupo", + "moveEditorToFirstGroup": "Mover o Editor para o Primeiro Grupo", + "moveEditorToSecondGroup": "Mover o Editor para o Segundo Grupo", + "moveEditorToThirdGroup": "Mover o Editor para o Terceiro Grupo" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 4b701929e85..550e345a27f 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Mover o editor ativo por guias ou grupos", "editorCommand.activeEditorMove.arg.name": "Argumento de movimento do editor ativo", - "editorCommand.activeEditorMove.arg.description": "Propriedades do argumento:\n* 'to': Valor do tipo sequencia de caracteres fornecendo onde se mover.\n\t* 'by': sequência de valor, proporcionando a unidade para o movimento. Por guia ou por grupo.\n\t* 'value': valor numérico, fornecendo quantas posições ou uma posição absoluta para mover.", - "commandDeprecated": "Comando **{0}** foi removido. Você pode usar **{1}** em vez disso", - "openKeybindings": "Configurar os atalhos de teclado" + "editorCommand.activeEditorMove.arg.description": "Propriedades do argumento:\n* 'to': Valor do tipo sequencia de caracteres fornecendo onde se mover.\n\t* 'by': sequência de valor, proporcionando a unidade para o movimento. Por guia ou por grupo.\n\t* 'value': valor numérico, fornecendo quantas posições ou uma posição absoluta para mover." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 8af2aff62d5..1e1fde93df0 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Editor de comparação de arquivos texto.", "navigate.next.label": "Próxima Alteração", "navigate.prev.label": "Alteração Anterior", - "inlineDiffLabel": "Alternar para exibição embutida", - "sideBySideDiffLabel": "Alternar para exibição lado a lado" + "toggleIgnoreTrimWhitespace.label": "Ignore espaços em branco" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index aafa87dc9bf..b78b8688cfd 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Fechar", - "closeOthers": "Fechar Outros", - "closeRight": "Fechar à direita", - "closeAll": "Fechar todos", - "closeAllUnmodified": "Fechar Não Modificados", - "keepOpen": "Manter aberto", - "showOpenedEditors": "Mostrar editores abertos", "araLabelEditorActions": "Ações de editor" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index 1c3db4d572b..4c843f96e08 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Sem Suporte]", + "userIsAdmin": "[Administrador]", + "userIsSudo": "[Superusuário]", "devExtensionWindowTitlePrefix": "[Host de Desenvolvimento de Extensão]" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/ptb/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index a2d4770e337..e40ee5163a0 100644 --- a/i18n/ptb/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/ptb/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "hideView": "Ocultar a Barra Lateral" + "hideView": "Ocultar" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/common/theme.i18n.json b/i18n/ptb/src/vs/workbench/common/theme.i18n.json index 0ed9a7f5447..b8e2f1b3570 100644 --- a/i18n/ptb/src/vs/workbench/common/theme.i18n.json +++ b/i18n/ptb/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "Cor de fundo da guia ativa. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editor.", "tabInactiveBackground": "Cor de fundo da guia inativa. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editor.", + "tabHoverBackground": "Cor de fundo da guia ao passar o mouse. As guias são os contêineres para editores na área do editor. Várias guias podem ser abertas em um grupo de editor. Podem existir vários grupos de editor.", + "tabUnfocusedHoverBackground": "Cor de fundo da guia em um grupo fora de foco ao passar o mouse. As guias são os contêineres para editores na área do editor. Várias guias podem ser abertas em um grupo de editor. Podem existir vários grupos de editor.", "tabBorder": "Borda para separar uma guia das outras. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editor.", "tabActiveBorder": "Borda para destacar guias ativas. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editores.", "tabActiveUnfocusedBorder": "Borda para destacar guias ativas em um grupo fora de foco. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editores.", + "tabHoverBorder": "Borda para destacar guias ao passar o mouse. As guias são os contêineres para editores na área do editor. Várias guias podem ser abertas em um grupo de editor. Podem existir vários grupos de editor.", + "tabUnfocusedHoverBorder": "Borda para destacar guias em um grupo fora de foco ao passar o mouse. As guias são os contêineres para editores na área do editor. Várias guias podem ser abertas em um grupo de editor. Podem existir vários grupos de editor.", "tabActiveForeground": "Cor de primeiro plano da guia ativa em um grupo ativo. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editor.", "tabInactiveForeground": "Cor de primeiro plano da guia inativa em um grupo ativo. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editor.", "tabUnfocusedActiveForeground": "Cor de primeiro plano da aba ativa em um grupo fora de foco. As guias são os recipientes para editores na área do editor. Várias guias podem ser abertas em um grupo de editores. Podem haver vários grupos de editores.", @@ -16,7 +20,7 @@ "editorGroupBackground": "Cor de fundo de um grupo de editor. Grupos de editor são os recipientes dos editores. A cor de fundo é mostrada ao arrastar o editor de grupos ao redor.", "tabsContainerBackground": "Cor de fundo do cabeçalho do título do grupo de editor quando as guias são habilitadas. Grupos de editor são os recipientes dos editores.", "tabsContainerBorder": "Cor da borda do cabeçalho do título do grupo de editor quando as guias estão habilitadas. Grupos de editor são os recipientes dos editores.", - "editorGroupHeaderBackground": "Cor de fundo do título do cabeçalho do grupo de editor quando as guias são desabilitadas. Grupos de editor são os recipientes dos editores.", + "editorGroupHeaderBackground": "Cor de fundo do título no cabeçalho do grupo de editor quando guias estiverem desabilitadas (`\"workbench.editor.showTabs\": false`). Grupos de editor são os contêineres dos editores.", "editorGroupBorder": "Cor para separar múltiplos grupos de editor de outro. Grupos de editor são os recipientes dos editores.", "editorDragAndDropBackground": "Cor de fundo ao arrastar editores. A cor deve ter transparência para que o conteúdo do editor ainda possa ser visto.", "panelBackground": "Cor de fundo do painel. Os painéis são mostrados abaixo da área do editor e contém visualizações como saída e terminal integrado.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "Cor da borda da barra de status separando para a barra lateral e editor quando nenhuma pasta é aberta. A barra de status é mostrada na parte inferior da janela.", "statusBarItemActiveBackground": "Cor de fundo do item da barra de status quando você clicado. A barra de status é mostrada na parte inferior da janela.", "statusBarItemHoverBackground": "Cor de fundo do item da barra de status quando estiver passando sobre ele. A barra de status é mostrada na parte inferior da janela.", - "statusBarProminentItemBackground": "Cor de fundo de itens proeminentes da barra de status. Itens proeminentes destacam-se outras entradas da barra de status para indicar a importância. A barra de status é mostrada na parte inferior da janela.", - "statusBarProminentItemHoverBackground": "Cor de fundo dos itens proeminentes de barra de status quando estiver passando sobre eles. Itens proeminentes destacam-se outras entradas de barra de status para indicar a importância. A barra de status é mostrada na parte inferior da janela.", + "statusBarProminentItemBackground": "Cor de fundo de itens proeminentes na barra de status. Itens proeminentes destacam-se de outros itens na barra de status para indicar importância. Altere o modo `Alternar Tecla Tab Move o Foco` da paleta de comandos para ver um exemplo. A barra de status é exibida na parte inferior da janela.", + "statusBarProminentItemHoverBackground": "Cor de fundo de itens proeminentes na barra de status ao passar o mouse sobre sobre eles. Itens proeminentes destacam-se de outros itens na barra de status para indicar importância. Altere o modo `Alternar Tecla Tab Move o Foco` da paleta de comandos para ver um exemplo. A barra de status é exibida na parte inferior da janela.", "activityBarBackground": "Cor de fundo da barra de atividades. Barra de atividade está visível à esquerda ou à direita e permite alternar entre as visualizações da barra lateral.", "activityBarForeground": "Cor de primeiro plano da barra de atividades (por exemplo, usada para os ícones). A barra de atividades está visível à esquerda ou à direita e permite alternar entre as visualizações da barra lateral.", "activityBarBorder": "Cor da borda da barra de atividades separando a barra lateral. A barra de atividade é mostrada à esquerda ou à direita e permite alternar entre as visualizações da barra lateral.", diff --git a/i18n/ptb/src/vs/workbench/common/views.i18n.json b/i18n/ptb/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..b7201e3d4af --- /dev/null +++ b/i18n/ptb/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Uma exibição com id '{0}' já está registrada na localização '{1}'" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json index 67b112045f5..44851d18637 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Fechar Editor", "closeWindow": "Fechar Janela", "closeWorkspace": "Fechar o espaço de trabalho", "noWorkspaceOpened": "Não há nenhum espaço de trabalho aberto nessa instância para ser fechado.", @@ -52,21 +51,5 @@ "displayLanguage": "Define o idioma de exibição do VSCode.", "doc": "Veja {0} para obter uma lista dos idiomas suportados.", "restart": "Modificar o valor requer reinicialização do VSCode.", - "fail.createSettings": "Não foi possível criar '{0}' ({1}).", - "openLogsFolder": "Abrir Pasta de Logs", - "showLogs": "Exibir Logs...", - "mainProcess": "Principal", - "sharedProcess": "Compartilhado", - "rendererProcess": "Renderizador", - "extensionHost": "Host de Extensão", - "selectProcess": "Selecionar processo", - "setLogLevel": "Definir Nível de Log", - "trace": "Rastreamento", - "debug": "Depurar", - "info": "Informações", - "warn": "Aviso", - "err": "Erro", - "critical": "Crítico", - "off": "Desligado", - "selectLogLevel": "Selecione o nível de log" + "fail.createSettings": "Não foi possível criar '{0}' ({1})." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json index 06f44d416ff..e83d165cd84 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Exibir", "help": "Ajuda", "file": "Arquivo", - "developer": "Desenvolvedor", "workspaces": "Espaços de trabalho", + "developer": "Desenvolvedor", + "workbenchConfigurationTitle": "Área de Trabalho", "showEditorTabs": "Controla se os editores abertos devem ou não serem exibidos em abas.", "workbench.editor.labelFormat.default": "Mostra o nome do arquivo. Quando guias estiverem ativadas e dois arquivos em um grupo tiverem o mesmo nome, a seção de distinção para cada caminho de arquivo é adicionada. Quando guias estiverem desativadas, o caminho relativo para a pasta do espaço de trabalho é exibida se o editor estiver ativo.", "workbench.editor.labelFormat.short": "Mostrar o nome do arquivo seguido pelo nome do diretório.", @@ -20,23 +21,23 @@ "showIcons": "Controla se os editores abertos devem ou não ser exibidos com um ícone. Requer um tema de ícone para ser habilitado. ", "enablePreview": "Controla se editores abertos mostram uma visualização. Editores de visualização são reutilizados até que eles sejam mantidos (por exemplo, através do duplo clique ou edição) e aparecerem com um estilo de fonte em itálico.", "enablePreviewFromQuickOpen": "Controla se os editores abertos da Abertura Rápida são exibidos como visualização. Os editores de visualização são reutilizados até serem preservados (por exemplo, através de um duplo clique ou edição).", + "closeOnFileDelete": "Controla se os editores que mostram um arquivo devem fechar automaticamente quanto o arquivo é apagado ou renomeado por algum outro processo. Desativar isso manterá o editor aberto como sujo neste evento. Note que apagar do aplicativo sempre fechará o editor e os arquivos sujos nunca fecharão para preservar seus dados.", "editorOpenPositioning": "Controla onde os editores serão abertos. Escolha 'esquerda' ou 'direita' para abrir os editores à esquerda ou à direita do editor ativo. Selecione 'primeiro' ou 'último' para abrir os editores independentemente do ativo no momento.", "revealIfOpen": "Controla se um editor é exibido em qualquer um dos grupos, se aberto. Se desabilitado, um editor será aberto preferencialmente no grupo de editores ativo. Se habilitado, um editor já aberto será exibido no grupo de editores ativo, ao invés de ser aberto novamente. Note que há alguns casos onde esta configuração é ignorada, por exemplo, quando for forçada a abertura de um editor em um grupo específico ou ao lado do grupo atualmente ativo.", + "swipeToNavigate": "Navegue entre arquivos abertos usando o deslizamento horizontal de três dedos.", "commandHistory": "Controla o número de comandos usados recentemente a serem mantidos no histórico da paleta de comando. Definir como 0 para desativar o histórico de comandos.", "preserveInput": "Controla se a última entrada digitada na paleta de comandos deve ser restaurada ao abri-la da próxima vez.", "closeOnFocusLost": "Controla se Abertura Rápida deve fechar automaticamente caso perca o foco.", "openDefaultSettings": "Controla se a abertura de configurações também abre um editor mostrando todas as configurações padrão.", "sideBarLocation": "Controla a localização da barra lateral. Ele pode ser exibido à esquerda ou à direita da área de trabalho.", + "panelDefaultLocation": "Controla o local padrão do painel. Pode ser visualizado na parte inferior ou no lado direito da área de trabalho.", "statusBarVisibility": "Controla a visibilidade da barra de status na parte inferior da área de trabalho.", "activityBarVisibility": "Controla a visibilidade da barra de atividades na área de trabalho.", - "closeOnFileDelete": "Controla se os editores que mostram um arquivo devem fechar automaticamente quanto o arquivo é apagado ou renomeado por algum outro processo. Desativar isso manterá o editor aberto como sujo neste evento. Note que apagar do aplicativo sempre fechará o editor e os arquivos sujos nunca fecharão para preservar seus dados.", - "enableNaturalLanguageSettingsSearch": "Controla se deve habilitar o modo de busca de linguagem natural para as configurações.", "fontAliasing": "Controla o método de identificação de fonte no espaço de trabalho.\n- padrão: Suavização de fonte subpixel. Na maioria dos monitores não-retina isto mostrará o texto mais nítido\n- antialiased: Suaviza a fonte no nível do pixel, em oposição a subpixel. Pode fazer a fonte aparecer mais clara de um modo geral \n- nenhum: Desabilita a suavização de fonte. Texto será mostrado com bordas irregulares", "workbench.fontAliasing.default": "Suavização de fonte subpixel. Na maioria dos monitores não-retina isto mostrará o texto mais nítido.", "workbench.fontAliasing.antialiased": "Suavizar a fonte no nível do pixel, em oposição a subpixel. Pode fazer com que a fonte apareça mais clara de uma forma geral.", "workbench.fontAliasing.none": "Desabilita a suavização de fonte. Texto será mostrado com bordas irregulares.", - "swipeToNavigate": "Navegue entre arquivos abertos usando o deslizamento horizontal de três dedos.", - "workbenchConfigurationTitle": "Área de Trabalho", + "enableNaturalLanguageSettingsSearch": "Controla se deve habilitar o modo de busca de linguagem natural para as configurações.", "windowConfigurationTitle": "Janela", "window.openFilesInNewWindow.on": "Arquivos serão abertos em uma nova janela", "window.openFilesInNewWindow.off": "Arquivos serão abertos em uma nova janela com a pasta de arquivos aberta ou com a última janela ativa.", diff --git a/i18n/ptb/src/vs/workbench/electron-browser/window.i18n.json b/i18n/ptb/src/vs/workbench/electron-browser/window.i18n.json index 8a03ff87882..3bb18871ba8 100644 --- a/i18n/ptb/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/ptb/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Recortar", "copy": "Copiar", "paste": "Colar", - "selectAll": "Selecionar Tudo" + "selectAll": "Selecionar Tudo", + "runningAsRoot": "Não é recomendado executar {0} como usuário root." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json index 421e5b19c79..05dd117d6de 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/browser/debugActionsWidget.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debugToolBarBackground": "Cor de fundo da barra de ferramentas de depuração." + "debugToolBarBackground": "Cor de fundo da barra de ferramentas de depuração.", + "debugToolBarBorder": "Cor da borda da barra de ferramentas de depuração." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 3908acc5028..f196dbc34be 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "Configurações de esquema JSON para validar 'launch.json'.", "vscode.extension.contributes.debuggers.windows": "Configurações específicas do Windows.", "vscode.extension.contributes.debuggers.windows.runtime": "Runtime usado para Windows.", - "vscode.extension.contributes.debuggers.osx": "Configurações específicas do OS X.", - "vscode.extension.contributes.debuggers.osx.runtime": "Runtime usado para o OS X.", "vscode.extension.contributes.debuggers.linux": "Configurações específicas do Linux.", "vscode.extension.contributes.debuggers.linux.runtime": "Runtime usado para o Linux.", "vscode.extension.contributes.breakpoints": "Contribui aos pontos de interrupção.", diff --git a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 898a18605fb..68ea94e5a20 100644 --- a/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "depurado", - "debug.terminal.not.available.error": "Terminal integrado não disponível" + "debug.terminal.title": "depurado" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 548fff57edc..21d5f668ec9 100644 --- a/i18n/ptb/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Abrir Novo Prompt de Comando", "globalConsoleActionMacLinux": "Abrir Novo Terminal", "scopedConsoleActionWin": "Abrir no Prompt de Comando", - "scopedConsoleActionMacLinux": "Abrir no Terminal", - "openFolderInIntegratedTerminal": "Abrir no Terminal" + "scopedConsoleActionMacLinux": "Abrir no Terminal" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index b4f99cdf746..9d1bc5a5312 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Esta extensão é recomendada baseada nos arquivos que você abriu recentemente.", + "neverShowAgain": "Não mostrar novamente", + "close": "Fechar", "workspaceRecommendation": "Esta extensão é recomendada pelos usuários da área de trabalho atual.", + "fileBasedRecommendation": "Esta extensão é recomendada baseada nos arquivos que você abriu recentemente.", "exeBasedRecommendation": "Esta extensão é recomendada porque você tem {0} instalado.", "reallyRecommended2": "A extensão {0} é recomendada para este tipo de arquivo.", "reallyRecommendedExtensionPack": "O pacote de extensão '{0}' é recomendado para este tipo de arquivo.", "showRecommendations": "Mostrar Recomendações", "install": "Instalar", - "neverShowAgain": "Não mostrar novamente", - "close": "Fechar", + "showLanguageExtensions": "A Loja tem extensões que podem ajudar com arquivos '.{0}'", + "searchMarketplace": "Pesquisar na Loja", "workspaceRecommended": "Este espaço de trabalho possui recomendações de extensão.", "installAll": "Instalar Tudo", "ignoreExtensionRecommendations": "Você quer ignorar todas as recomendações de extensão?", diff --git a/i18n/ptb/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json b/i18n/ptb/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json index 3ab045563d8..07aeb8dd560 100644 --- a/i18n/ptb/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.i18n.json @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "installingVSIXExtension": "Instalando extensão do VSIX...", + "installingMarketPlaceExtension": "Instalando extensão da Loja...", + "uninstallingExtension": "Desinstalando extensão...", "enableDependeciesConfirmation": "Habilitando '{0}' também habilita suas dependências. Gostaria de continuar?", "enable": "Sim", "doNotEnable": "Não", diff --git a/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..25e6a323be4 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Área de Trabalho", + "feedbackVisibility": "Controla a visibilidade do feedback no Twitter (smiley) na barra de status na região inferior da área de trabalho." +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json index 5d3c22c39a8..db165d19e5b 100644 --- a/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedback.i18n.json @@ -16,6 +16,7 @@ "request a missing feature": "Solicitar um recurso ausente", "tell us why?": "Diga-nos porquê?", "commentsHeader": "Comentários", + "showFeedback": "Mostrar Smiley de Feedback na Barra de Status", "tweet": "Tweetar", "character left": "caractere à esquerda", "characters left": "caracteres à esquerda", diff --git a/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..afb315a42d4 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "Ocultar" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 464da97e4e9..a67013312a3 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,27 @@ "filesCategory": "Arquivo", "revealInSideBar": "Revelar na Barra Lateral", "acceptLocalChanges": "Usar suas alterações e substituir o conteúdo do disco", - "revertLocalChanges": "Descartar as alterações e reverter para o conteúdo no disco" + "revertLocalChanges": "Descartar as alterações e reverter para o conteúdo no disco", + "copyPathOfActive": "Copiar Caminho do Arquivo Ativo", + "saveAllInGroup": "Salvar Todos no Grupo", + "saveFiles": "Salvar todos os arquivos", + "revert": "Reverter Arquivo", + "compareActiveWithSaved": "Comparar o Arquivo Ativo com o Arquivo Salvo", + "closeEditor": "Fechar Editor", + "view": "Exibir", + "openToSide": "Aberto para o lado", + "revealInWindows": "Revelar no Explorer", + "revealInMac": "Revelar no Finder", + "openContainer": "Abrir a Pasta", + "copyPath": "Copiar Caminho", + "saveAll": "Salvar Todos", + "compareWithSaved": "Comparar com o salvo", + "compareWithSelected": "Comparar com o Selecionado", + "compareSource": "Selecione para comparar", + "compareSelected": "Comparar Selecionado", + "close": "Fechar", + "closeOthers": "Fechar Outros", + "closeUnmodified": "Fechar Não Modificados", + "closeAll": "Fechar todos", + "deleteFile": "Excluir permanentemente" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 18ed68af70c..02499c21575 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Tentar novamente", - "rename": "Renomear", "newFile": "Novo Arquivo", "newFolder": "Nova Pasta", + "rename": "Renomear", + "delete": "Excluir", + "copyFile": "Copiar", + "pasteFile": "Colar", + "retry": "Tentar novamente", "openFolderFirst": "Abrir uma pasta primeiro para criar arquivos ou pastas dentro dele.", "newUntitledFile": "Novo Arquivo Sem Título", "createNewFile": "Novo Arquivo", @@ -15,39 +18,32 @@ "deleteButtonLabelRecycleBin": "&&Mover para Lixeira", "deleteButtonLabelTrash": "&&Mover para o Lixo", "deleteButtonLabel": "&&Excluir", + "dirtyMessageFilesDelete": "Você está excluindo arquivos com alterações não salvas. Você quer continuar?", "dirtyMessageFolderOneDelete": "Você está excluindo uma pasta com alterações não salvas em 1 arquivo. Você quer continuar?", "dirtyMessageFolderDelete": "Você está excluindo uma pasta com alterações não salvas em {0} arquivos. Você quer continuar?", "dirtyMessageFileDelete": "Você está excluindo um arquivo com alterações não salvas. Você quer continuar?", "dirtyWarning": "Suas alterações serão perdidas se você não salvá-las.", + "confirmMoveTrashMessageMultiple": "Você tem certeza que deseja excluir os seguintes {0} arquivos?", "confirmMoveTrashMessageFolder": "Tem certeza de que deseja excluir '{0}' e seu conteúdo?", "confirmMoveTrashMessageFile": "Tem certeza de que deseja excluir '{0}'?", "undoBin": "Você pode restaurar da lixeira.", "undoTrash": "Você pode restaurar a partir do lixo.", "doNotAskAgain": "Não me pergunte novamente", + "confirmDeleteMessageMultiple": "Você tem certeza que deseja excluir permanentemente os seguintes {0} arquivos?", "confirmDeleteMessageFolder": "Tem certeza de que deseja excluir permanentemente '{0}' e seu conteúdo?", "confirmDeleteMessageFile": "Tem certeza de que deseja excluir permanentemente '{0}'?", "irreversible": "Esta ação é irreversível!", "permDelete": "Excluir permanentemente", - "delete": "Excluir", "importFiles": "Importar Arquivos", "confirmOverwrite": "Um arquivo ou pasta com o mesmo nome já existe na pasta de destino. Você quer substituí-lo?", "replaceButtonLabel": "&&Substituir", - "copyFile": "Copiar", - "pasteFile": "Colar", + "fileDeleted": "Arquivo foi excluído ou movido durante o processo", + "fileIsAncestor": "Arquivo a ser copiado é um ancestral da pasta de destino.", "duplicateFile": "Duplicar", - "openToSide": "Aberto para o lado", - "compareSource": "Selecione para comparar", "globalCompareFile": "Compare o Arquivo Ativo Com...", "openFileToCompare": "Abrir um arquivo primeiro para compará-lo com outro arquivo.", - "compareWith": "Comparar '{0}' com '{1}'", - "compareFiles": "Comparar Arquivos", "refresh": "Atualizar", - "save": "Salvar", - "saveAs": "Salvar como...", - "saveAll": "Salvar Todos", "saveAllInGroup": "Salvar Todos no Grupo", - "saveFiles": "Salvar todos os arquivos", - "revert": "Reverter Arquivo", "focusOpenEditors": "Foco na Visualização dos Editores Abertos", "focusFilesExplorer": "Foco no Explorador de Arquivos", "showInExplorer": "Revelar o Arquivo Ativo na Barra Lateral", @@ -56,20 +52,11 @@ "refreshExplorer": "Atualizar Explorador", "openFileInNewWindow": "Abrir o Arquivo Ativo em uma Nova Janela", "openFileToShowInNewWindow": "Abrir um arquivo primeiro para abrir em uma nova janela", - "revealInWindows": "Revelar no Explorer", - "revealInMac": "Revelar no Finder", - "openContainer": "Abrir a Pasta", - "revealActiveFileInWindows": "Revelar Arquivo Ativo no Windows Explorer", - "revealActiveFileInMac": "Revelar Arquivo Ativo no Finder", - "openActiveFileContainer": "Abrir a Pasta do Arquivo Ativo.", "copyPath": "Copiar Caminho", - "copyPathOfActive": "Copiar Caminho do Arquivo Ativo", "emptyFileNameError": "Um nome de arquivo ou pasta deve ser fornecido.", "fileNameExistsError": "Um arquivo ou pasta **{0}** já existe neste local. Escolha um nome diferente.", "invalidFileNameError": "O nome **{0}** não é válido como um nome de arquivo ou pasta. Por favor, escolha um nome diferente.", "filePathTooLongError": "O nome **{0}** resulta em um caminho muito longo. Escolha um nome mais curto.", - "compareWithSaved": "Comparar o Arquivo Ativo com o Arquivo Salvo", - "modifiedLabel": "{0} (em disco) ↔ {1}", "compareWithClipboard": "Compare o Arquivo Ativo com a Área de Transferência", "clipboardComparisonLabel": "Área de Transferência ↔ {0}" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index 2e61a1656c8..7a2c7c9c70d 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Abrir um arquivo primeiro para copiar seu caminho", - "openFileToReveal": "Abrir um arquivo primeiro para revelar" + "revealInWindows": "Revelar no Explorer", + "revealInMac": "Revelar no Finder", + "openContainer": "Abrir a Pasta", + "saveAs": "Salvar como...", + "save": "Salvar", + "saveAll": "Salvar Todos", + "removeFolderFromWorkspace": "Remover pasta da área de trabalho", + "genericRevertError": "Falha ao reverter '{0}': {1}", + "modifiedLabel": "{0} (em disco) ↔ {1}", + "openFileToReveal": "Abrir um arquivo primeiro para revelar", + "openFileToCopy": "Abrir um arquivo primeiro para copiar seu caminho" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 0e95d226253..8488c0881d3 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,7 @@ "editorConfigurationTitle": "Editor", "formatOnSave": "Formata um arquivo no salvamento. Um formatador deve estar disponível, o arquivo não deve ser salvo automaticamente e editor não deve ser desligado.", "explorerConfigurationTitle": "Explorador de arquivos", - "openEditorsVisible": "Número de editores mostrado no painel Abrir Editores. Configurá-lo para 0 irá ocultar o painel.", - "dynamicHeight": "Controla se a altura da seção de editores abertos deve adaptar-se dinamicamente para o número de elementos ou não.", + "openEditorsVisible": "Número de editores mostrados no painel Editores Abertos.", "autoReveal": "Controla se o explorador deve automaticamente revelar e selecionar arquivos ao abri-los.", "enableDragAndDrop": "Controla se o explorador deve permitir mover arquivos e pastas através de arrastar e soltar.", "confirmDragAndDrop": "Controla se o explorer deve pedir a confirmação ao mover arquivos ou pastas através de arrastar e soltar.", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 09a29894643..5f8a28ec46b 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Use as ações na barra de ferramentas de editor para a direita para **desfazer** suas alterações ou **substituir** o conteúdo no disco com as alterações", - "discard": "Descartar", + "overwriteElevated": "Sobrescrever como Admin...", + "saveElevated": "Tentar novamente como Admin...", "overwrite": "Sobrescrever", "retry": "Tentar novamente", - "readonlySaveError": "Falha ao salvar '{0}': O arquivo está protegido contra gravação. Selecione 'Substituir' para remover a proteção.", + "discard": "Descartar", + "readonlySaveErrorAdmin": "Falha ao salvar '{0}': O arquivo está protegido contra gravação. Selecione 'Sobrescrever como Admin' para tentar novamente como administrador.", + "readonlySaveError": "Falha ao salvar '{0}': O arquivo está protegido contra gravação. Selecione 'Sobrescrever' para tentar remover a proteção.", + "permissionDeniedSaveError": "Falha ao salvar '{0}': Permissões insuficientes. Selecione 'Tentar novamente como Admin' para tentar novamente como administrador.", "genericSaveError": "Erro ao salvar '{0}': {1}", "staleSaveError": "Falha ao salvar '{0}': O conteúdo no disco é mais recente. Clique em **Comparar** para comparar a sua versão com a do disco.", "compareChanges": "Comparar", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json index 02afd8f004f..e29cc00e9bf 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.i18n.json @@ -10,6 +10,7 @@ "dropFolder": "Você quer adicionar a pasta no espaço de trabalho?", "addFolders": "&&Adicionar Pastas", "addFolder": "&&Adicionar Pasta", + "confirmMultiMove": "Você tem certeza que deseja mover os seguintes {0} arquivos?", "confirmMove": "Tem certeza que deseja mover '{0}'?", "doNotAskAgain": "Não me pergunte novamente", "moveButtonLabel": "&&Mover", diff --git a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 83f2a510196..e075736dad3 100644 --- a/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Abrir Editores", "openEditosrSection": "Abrir Seção de Editores", - "dirtyCounter": "{0} não salvos", - "saveAll": "Salvar Todos", - "closeAllUnmodified": "Fechar Não Modificados", - "closeAll": "Fechar todos", - "compareWithSaved": "Comparar com o salvo", - "close": "Fechar", - "closeOthers": "Fechar Outros" + "dirtyCounter": "{0} não salvos" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..05cf5d42db3 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "Log (Principal)", + "sharedLog": "Log (Compartilhado)", + "rendererLog": "Log (Janela)", + "extensionsLog": "Log (Host de Extensão)", + "developer": "Desenvolvedor" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..2bd2313c928 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Abrir Pasta de Logs", + "showLogs": "Exibir Logs...", + "mainProcess": "Principal", + "sharedProcess": "Compartilhado", + "rendererProcess": "Janela", + "extensionHost": "Host de Extensão", + "selectProcess": "Selecionar processo", + "openLogFile": "Abrir Arquivo de Log...", + "setLogLevel": "Definir Nível de Log", + "trace": "Rastreamento", + "debug": "Depurar", + "info": "Informações", + "warn": "Aviso", + "err": "Erro", + "critical": "Crítico", + "off": "Desligado", + "selectLogLevel": "Selecione o nível de log" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/ptb/src/vs/workbench/parts/markers/common/messages.i18n.json index ad1f8b439c5..e304c1044a9 100644 --- a/i18n/ptb/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Exibir", - "problems.view.toggle.label": "Alternar Problemas", - "problems.view.focus.label": "Problemas de foco", + "problems.view.toggle.label": "Esconder/exibir Problemas (Erros, Avisos, Infos)", + "problems.view.focus.label": "Focar Problemas (Erros, Avisos, Infos)", "problems.panel.configuration.title": "Visualização de Problemas", "problems.panel.configuration.autoreveal": "Controla se a visaulização de problemas evela os arquivos automaticamente ao abri-los", "markers.panel.title.problems": "Problemas", diff --git a/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..9a9c6f73156 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Saída", + "logViewer": "Visualizador do Log", + "viewCategory": "Exibir", + "clearOutput.label": "Limpar saída" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..383a9f4835d --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "{0} - Saída", + "channel": "Canal de saída para '{0}'" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json index 4027814e08d..75c87388f26 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/keybindingsEditor.i18n.json @@ -17,6 +17,7 @@ "resetLabel": "Redefinir Keybinding", "showConflictsLabel": "Mostrar Conflitos", "copyLabel": "Copiar", + "copyCommandLabel": "Copiar Comando", "error": "Erro '{0}' enquanto edita keybinding. Por favor, abra o arquivo 'keybindings.json' e verifique.", "command": "Comando", "keybinding": "KeyBinding", diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json index 49fd2fe9bd8..0877b71005f 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesEditor.i18n.json @@ -11,6 +11,8 @@ "oneSettingFound": "1 Configuração correspondente", "settingsFound": "{0} Configurações correspondentes", "totalSettingsMessage": "Total {0} Configurações", + "nlpResult": "Resultados da Linguagem Natural", + "filterResult": "Resultados Filtrados", "defaultSettings": "Configurações Padrão", "defaultFolderSettings": "Configuração Padrão da Pasta", "defaultEditorReadonly": "Editar no editor do lado direito para substituir os padrões.", diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index 800b9bf18e2..df12c20c366 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Tente a busca de linguagem natural!", "defaultSettings": "Coloque suas configurações no editor do lado direito para substituir.", "noSettingsFound": "Não há configurações encontradas.", "settingsSwitcherBarAriaLabel": "Chave de Configurações", "userSettings": "Configurações de Usuário", "workspaceSettings": "Configurações de Espaço de Trabalho", - "folderSettings": "Configurações da Pasta", - "enableFuzzySearch": "Habilitar busca de linguagem natural" + "folderSettings": "Configurações da Pasta" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/ptb/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 9f80cd79e8b..6427118b75b 100644 --- a/i18n/ptb/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Comumente Utilizado", - "mostRelevant": "Mais Relevante", "defaultKeybindingsHeader": "Substituir as chaves de ligações, colocando-os em seu arquivo de chave ligações." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index e3c6204b605..75a93eabf9c 100644 --- a/i18n/ptb/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Exibir", "commandsHandlerDescriptionDefault": "Exibir e executar comandos", "gotoLineDescriptionMac": "Ir para linha", "gotoLineDescriptionWin": "Ir para linha", diff --git a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 117ddc11b04..668463cff46 100644 --- a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,9 @@ "toggleGitViewlet": "Mostrar Git", "source control": "Controle de código-fonte", "toggleSCMViewlet": "Mostrar SCM", - "view": "Exibir" + "view": "Exibir", + "scmConfigurationTitle": "SCM", + "alwaysShowProviders": "Se deverá sempre mostrar a seção Provedor de Controle de Código Fonte.", + "diffDecorations": "Controla decorações do diff no editor.", + "inputCounter": "Controla quando exibir o contador de entrada." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json index fc4f8f90311..916c6469ab8 100644 --- a/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/scm/electron-browser/scmViewlet.i18n.json @@ -6,6 +6,9 @@ { "scm providers": "Provedores de Controle de Código Fonte", "hideRepository": "Ocultar", + "commitMessageInfo": "{0} caracteres na linha atual", + "commitMessageCountdown": "{0} caracteres restantes na linha atual", + "commitMessageWarning": "{0} caracteres sobre {1} na linha atual", "installAdditionalSCMProviders": "Instalar provedores de SCM adicionais...", "no open repo": "Não existem provedores controle de código fonte ativos.", "source control": "Controle de código-fonte", diff --git a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json index 34ded87a267..62c0f96918e 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Mostrar Termo de Pesquisa Anterior", "showSearchViewlet": "Mostrar Busca", "findInFiles": "Localizar nos Arquivos", - "findInFilesWithSelectedText": "Localizar nos Arquivos Com o Texto Selecionado", "replaceInFiles": "Substituir nos Arquivos", - "replaceInFilesWithSelectedText": "Substituir nos Arquivos Com o Texto Selecionado", "RefreshAction.label": "Atualizar", "CollapseDeepestExpandedLevelAction.label": "Recolher tudo", "ClearSearchResultsAction.label": "Limpar", diff --git a/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index b7b7494e9e4..d407ebde609 100644 --- a/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Procurar na pasta...", + "findInWorkspace": "Procurar no Espaço de Trabalho...", "showTriggerActions": "Ir para Símbolo no Espaço de Trabalho...", "name": "Pesquisar", "search": "Pesquisar", + "showSearchViewlet": "Mostrar Busca", "view": "Exibir", + "findInFiles": "Localizar nos Arquivos", "openAnythingHandlerDescription": "Ir para o Arquivo", "openSymbolDescriptionNormal": "Ir para o Símbolo em Área de Trabalho", - "searchOutputChannelTitle": "Pesquisar", "searchConfigurationTitle": "Pesquisar", "exclude": "Configure os padrões glob para excluir arquivos e pastas nas pesquisas. Herda todos os padrões glob da configuração files.exclude.", "exclude.boolean": "O padrão glob com o qual combinar os caminhos de arquivo. Defina para verdadeiro ou falso para habilitar ou desabilitar o padrão.", @@ -18,5 +21,6 @@ "useRipgrep": "Controla se utiliza ripgrep em buscas de texto e de arquivo", "useIgnoreFiles": "Controla se utiliza arquivos .gitignore e .ignore por padrão ao fazer pesquisas de arquivos.", "search.quickOpen.includeSymbols": "Configurar para incluir resultados de uma pesquisa símbolo global nos resultados do arquivo para Abertura Rápida.", - "search.followSymlinks": "Controla quando seguir symlinks ao realizar uma busca." + "search.followSymlinks": "Controla quando seguir symlinks ao realizar uma busca.", + "search.smartCase": "Faz pesquisas do tipo case-insensitive se o termo for totalmente minúsculo, caso contrário, faz pesquisas do tipo case-sensitive." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..be32250a3f7 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.scope": "(global)", + "global.1": "({0})", + "new.global": "Novo Arquivo de Trechos de Código Global...", + "group.global": "Trechos de código existentes", + "new.global.sep": "Novos Trechos de Código", + "openSnippet.pickLanguage": "Selecionar Arquivo de Trechos de Código ou Criar Trechos de Código", + "openSnippet.label": "Configurar Trechos de Código do Usuário", + "preferences": "Preferências" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index b9823c384ad..5cad5c0f57d 100644 --- a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Selecionar Idioma para o Trecho", - "openSnippet.errorOnCreate": "Não é possível criar {0}", - "openSnippet.label": "Abrir trechos de código do usuário", - "preferences": "Preferências", "snippetSchema.json.default": "Trecho de código vazio", "snippetSchema.json": "Configuração do trecho do usuário", "snippetSchema.json.prefix": "O prefixo usado ao selecionar o trecho no intelliSense", "snippetSchema.json.body": "O conteúdo do trecho. Use '$1', '${1:defaultText}' para definir as posições do cursor, use '$0' para a posição final do cursor. Insira valores de variáveis com '${varName}' e '${varName:defaultText}', por exemplo ' Este é o arquivo: $TM_FILENAME'.", - "snippetSchema.json.description": "A descrição do trecho." + "snippetSchema.json.description": "A descrição do trecho.", + "snippetSchema.json.scope": "Uma lista de nomes de linguagem para a qual este trecho de código aplica-se, por exemplo 'typescript,javascript'." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..bfdaf9232d5 --- /dev/null +++ b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Trecho de código do usuário" +} \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index a2c0fbab96a..142b52e21ef 100644 --- a/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Linguagem desconhecida em `contributes.{0}.language`. Valor fornecido: {1}", "invalid.path.0": "Esperada uma string em `contributes.{0}.path`. Valor informado: {1}", + "invalid.language.0": "Quando a linguagem for omitida, o valor de `contributes.{0}.path` deve ser um arquivo-`.code-snippets`. Valor definido: {1}", + "invalid.language": "Linguagem desconhecida em `contributes.{0}.language`. Valor fornecido: {1}", "invalid.path.1": "É esperado que `contributes.{0}.path` ({1}) seja incluído na pasta da extensão ({2}). Isto pode tornar a extensão não portável.", "vscode.extension.contributes.snippets": "Contribui aos trechos de código.", "vscode.extension.contributes.snippets-language": "Identificador de linguagem para o qual este trecho de código contribui.", "vscode.extension.contributes.snippets-path": "Caminho do arquivo de trechos de código. O caminho é relativo à pasta de extensão e normalmente começa com '. /snippets/'.", "badVariableUse": "Um ou mais trechos da extensão '{0}' provavelmente se confundem com trechos de código de variáveis e trechos de código de espaços reservados (veja https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax para mais detalhes)", "badFile": "O arquivo de trechos \"{0}\" não pôde ser lido.", - "source.snippet": "Trecho de código do usuário", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json index d97a515c6ea..f45a86033e6 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.i18n.json @@ -14,6 +14,7 @@ "terminal.integrated.shell.windows": "O caminho do shell que o terminal utiliza no Windows. Quando estiver usando shells fornecidos com o Windows (cmd, PowerShell ou Bash no Ubuntu).", "terminal.integrated.shellArgs.windows": "Os argumentos de linha de comando a serem utilizados no terminal do Windows.", "terminal.integrated.rightClickCopyPaste": "Quando configurado, isto evitará que o menu de contexto apareça quando pressionado o botão direito do mouse dentro do terminal, em vez disso vai copiar quando há uma seleção e colar quando não há nenhuma seleção.", + "terminal.integrated.copyOnSelection": "Quando ativado, texto selecionado no terminal será copiado para a área de transferência.", "terminal.integrated.fontFamily": "Controla a família de fontes do terminal, este padrão é o valor do editor.fontFamily.", "terminal.integrated.fontSize": "Controla o tamanho da fonte em pixels do terminal.", "terminal.integrated.lineHeight": "Controla a altura da linha do terminal, este número é multiplicado pelo tamanho da fonte do terminal para obter a altura real da linha em pixels.", @@ -24,10 +25,12 @@ "terminal.integrated.setLocaleVariables": "Controla se as variáveis locais são definidas na inicialização do terminal, este padrão é verdadeiro no OS X e falso em outras plataformas.", "terminal.integrated.cwd": "Um caminho de início explícito onde o terminal será lançado, isso é usado como o diretório de trabalho atual (cwd) para o processo shell. Isto pode ser particularmente útil em configurações de espaço de trabalho se o diretório raiz não é um cwd conveniente.", "terminal.integrated.confirmOnExit": "Confirmar na saída se ainda houverem sessões de terminal ativas.", + "terminal.integrated.enableBell": "Se o sino do terminal está habilitado ou não.", "terminal.integrated.commandsToSkipShell": "Um conjunto de IDs de comando, cujas combinações de teclas não serão enviadas para o shell e sempre serão tratadas por código. Isto permite o uso de combinações de teclas que normalmente seriam consumidas pelo shell para agir da mesma forma quando o terminal não é focado, por exemplo ctrl+p para Execução Rápida.", "terminal.integrated.env.osx": "Objeto com variáveis de ambiente que serão adicionadas ao VS Code e utilizadas pelo terminal no Mac OS X", "terminal.integrated.env.linux": "Objeto com variáveis de ambiente que serão adicionadas ao VS Code e utilizadas pelo terminal no Linux", "terminal.integrated.env.windows": "Objeto com variáveis de ambiente que serão adicionadas ao VS Code e utilizadas pelo terminal no Windows", + "terminal.integrated.showExitAlert": "Mostrar alerta 'O processo terminal foi encerrado com código de saída' quando o código de saída é diferente de zero.", "terminalCategory": "Terminal", "viewCategory": "Exibir" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json index 2ee45b6deb3..f59efd68a97 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalActions.i18n.json @@ -14,6 +14,8 @@ "workbench.action.terminal.deleteWordRight": "Excluir Palavra à Direita", "workbench.action.terminal.new": "Criar Novo Terminal Integrado", "workbench.action.terminal.new.short": "Novo Terminal", + "workbench.action.terminal.newWorkspacePlaceholder": "Selecione o diretório de trabalho atual para novo terminal", + "workbench.action.terminal.newInActiveWorkspace": "Criar Novo Terminal Integrado (No Espaço de Trabalho Ativo)", "workbench.action.terminal.focus": "Focalizar Terminal", "workbench.action.terminal.focusNext": "Focalizar Próximo Terminal", "workbench.action.terminal.focusPrevious": "Focalizar Terminal Anterior", diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index 655ae8902e5..345ffbe4d25 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -9,5 +9,5 @@ "terminalCursor.foreground": "A cor de primeiro plano do cursor do terminal.", "terminalCursor.background": "A cor de fundo do cursor do terminal. Permite personalizar a cor de um personagem sobreposto por um cursor de bloco.", "terminal.selectionBackground": "A cor de fundo de seleção do terminal.", - "terminal.ansiColor": "'{0}' cor ansi no terminal." + "terminal.ansiColor": "'{0}' cor ANSI no terminal." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 83214ad4be8..53b433626d5 100644 --- a/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,7 @@ "terminal.integrated.chooseWindowsShellInfo": "Você pode alterar o terminal shell padrão selecionando o botão Personalizar.", "customize": "Personalizar", "cancel": "Cancelar", - "never again": "Ok, Nunca Mostrar Novamente", + "never again": "OK, Não Mostrar Novamente", "terminal.integrated.chooseWindowsShell": "Selecione o seu terminal shell preferido, você pode alterar isso mais tarde em suas configurações", "terminalService.terminalCloseConfirmationSingular": "Há uma sessão ativa de terminal, você quer finalizá-la?", "terminalService.terminalCloseConfirmationPlural": "Existem {0} sessões ativas de terminal, você quer finalizá-las?" diff --git a/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 6a2cfcb15ab..84ce2109e07 100644 --- a/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -13,7 +13,7 @@ "read the release notes": "Bem-vindo a {0} v{1}! Gostaria de ler as Notas da Versão?", "licenseChanged": "Nossos termos de licença mudaram, favor revisá-los.", "license": "Ler Licença", - "neveragain": "Nunca Mostrar Novamente", + "neveragain": "Não mostrar novamente", "64bitisavailable": "{0} para Windows de 64 bits está agora disponível!", "learn more": "Saiba Mais", "updateIsReady": "Nova atualização de {0} disponível.", @@ -23,6 +23,7 @@ "commandPalette": "Paleta de comandos...", "settings": "Configurações", "keyboardShortcuts": "Atalhos de Teclado", + "userSnippets": "Trecho de código do usuário", "selectTheme.label": "Tema de Cores", "themes.selectIconTheme.label": "Arquivo de Ícone do Tema", "not available": "Atualizações Indisponíveis", diff --git a/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json b/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json index 5411c925e8d..76ee2be0031 100644 --- a/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json +++ b/i18n/ptb/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.i18n.json @@ -5,7 +5,7 @@ // Do not edit this file. It is machine generated. { "welcomePage.vscode": "Visual Studio Code", - "welcomePage.editingEvolved": "Edição evoluiu", + "welcomePage.editingEvolved": "Edição evoluída", "welcomePage.start": "Início", "welcomePage.newFile": "Novo arquivo", "welcomePage.openFolder": "Abrir pasta...", diff --git a/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 7b91deaec2e..1cc780952f6 100644 --- a/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "Arquivo é um diretório", + "fileNotModifiedError": "Arquivo não modificado desde", "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto" } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json b/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json index ae4ae718743..dba7ada15b5 100644 --- a/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/files/node/fileService.i18n.json @@ -10,6 +10,7 @@ "fileTooLargeError": "Arquivo muito grande para abrir", "fileNotFoundError": "Arquivo não encontrado ({0})", "fileBinaryError": "Arquivo parece ser binário e não pode ser aberto como texto", + "filePermission": "Permissão negada ao escrever no arquivo ({0})", "fileExists": "Arquivo a ser criado já existe ({0})", "fileMoveConflict": "Não é possível mover/copiar. Arquivo já existe no destino.", "unableToMoveCopyError": "Não é possível mover/copiar. Arquivo poderia substituir a pasta em que está contida.", diff --git a/i18n/ptb/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json b/i18n/ptb/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json index fedfd5457f0..4e6320dddaa 100644 --- a/i18n/ptb/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/keybinding/electron-browser/keybindingService.i18n.json @@ -22,5 +22,6 @@ "keybindings.json.when": "Condição quando a chave está ativa.", "keybindings.json.args": "Argumentos a serem passados para o comando para executar.", "keyboardConfigurationTitle": "Teclado", - "dispatch": "Controla a lógica de pressionamentos de teclas a ser usada para envio, se será 'code' (recomendado) ou 'keyCode'." + "dispatch": "Controla a lógica de pressionamentos de teclas a ser usada para envio, se será 'code' (recomendado) ou 'keyCode'.", + "touchbar.enabled": "Habilita os botões do touchbar do macOS no teclado se disponível." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/ptb/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 491b19e87c4..f86146be73a 100644 --- a/i18n/ptb/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Você quer salvar as alterações feitas para {0}?", "saveChangesMessages": "Você quer salvar as alterações para os seguintes {0} arquivos?", - "moreFile": "... 1 arquivo adicional não está mostrado", - "moreFiles": "... {0} arquivos adicionais não estão mostrados", "saveAll": "&&Salvar tudo", "save": "&&Salvar", "dontSave": "&&Não Salvar", diff --git a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 15017c07157..164708fcd63 100644 --- a/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "Nenhum arquivo de ícones", "iconThemeError": "Arquivo de tema de ícones é desconhecido ou não está instalado.", "workbenchColors": "Substitui as cores do tema do tema de cores atualmente selecionado.", - "editorColors": "Substitui as cores e o estilo da fonte do editor do tema de cores atualmente selecionado.", "editorColors.comments": "Define as cores e estilos para os comentários", "editorColors.strings": "Define as cores e estilos para textos literais.", "editorColors.keywords": "Define as cores e estilos para palavras-chave.", @@ -19,5 +18,6 @@ "editorColors.types": "Define as cores e estilos para declarações de tipo e referências.", "editorColors.functions": "Define as cores e estilos para declarações de funções e referências.", "editorColors.variables": "Define as cores e estilos para declarações de variáveis e referências.", - "editorColors.textMateRules": "Define as cores e estilos usando regras de temas textmate (avançado)." + "editorColors.textMateRules": "Define as cores e estilos usando regras de temas textmate (avançado).", + "editorColors": "Substitui as cores e o estilo da fonte do editor do tema de cores atualmente selecionado." } \ No newline at end of file diff --git a/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 078a8eb1b7d..73fdc1bd8e4 100644 --- a/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/ptb/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Não é possível escrever no arquivo de configuração. Por favor, abra o arquivo para corrigir erros/avisos nele e tente novamente.", "errorWorkspaceConfigurationFileDirty": "Não é possível escrever no arquivo de configuração do espaço de trabalho porque o arquivo está sujo. Por favor, salve-o e tente novamente.", "openWorkspaceConfigurationFile": "Abrir o Arquivo de Configuração do Espaço de Trabalho", - "close": "Fechar", - "enterWorkspace.close": "Fechar", - "enterWorkspace.dontShowAgain": "Não mostrar novamente", - "enterWorkspace.moreInfo": "Mais informações", - "enterWorkspace.prompt": "Saiba mais sobre como trabalhar com várias pastas no VS Code." + "close": "Fechar" } \ No newline at end of file diff --git a/i18n/rus/extensions/git/out/autofetch.i18n.json b/i18n/rus/extensions/git/out/autofetch.i18n.json index 1e461cf4629..d3d761f3636 100644 --- a/i18n/rus/extensions/git/out/autofetch.i18n.json +++ b/i18n/rus/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,6 @@ // Do not edit this file. It is machine generated. { "yes": "Да", - "no": "Нет", - "not now": "Не сейчас", - "suggest auto fetch": "Вы хотите включить автоматическое получение для репозиториев Git?" + "read more": "Подробнее", + "no": "Нет" } \ No newline at end of file diff --git a/i18n/rus/extensions/git/out/commands.i18n.json b/i18n/rus/extensions/git/out/commands.i18n.json index d8d6feaa35d..b99a2ac09aa 100644 --- a/i18n/rus/extensions/git/out/commands.i18n.json +++ b/i18n/rus/extensions/git/out/commands.i18n.json @@ -64,12 +64,11 @@ "no remotes to pull": "Для вашего репозитория не настроены удаленные репозитории для получения данных.", "pick remote pull repo": "Выберите удаленный компьютер, с которого следует загрузить ветвь", "no remotes to push": "Для вашего репозитория не настроены удаленные репозитории для отправки данных.", - "push with tags success": "Файлы с тегами успешно отправлены.", "nobranch": "Извлеките ветвь, чтобы передать данные в удаленный репозиторий.", + "ok": "ОК", + "push with tags success": "Файлы с тегами успешно отправлены.", "pick remote": "Выберите удаленный сервер, на котором нужно опубликовать ветвь \"{0}\":", "sync is unpredictable": "Это действие отправляет фиксации в \"{0}\" и извлекает их из этого расположения.", - "ok": "ОК", - "never again": "ОК. Больше не показывать", "no remotes to publish": "Для вашего репозитория не настроены удаленные репозитории для публикации.", "no changes stash": "Отсутствуют изменения, которые необходимо спрятать.", "provide stash message": "Укажите сообщение о скрытии", diff --git a/i18n/rus/extensions/git/package.i18n.json b/i18n/rus/extensions/git/package.i18n.json index dcff3e1c9f0..bb4a19e4ed2 100644 --- a/i18n/rus/extensions/git/package.i18n.json +++ b/i18n/rus/extensions/git/package.i18n.json @@ -59,7 +59,6 @@ "config.enableLongCommitWarning": "Следует ли предупреждать о длинных сообщениях о фиксации", "config.confirmSync": "Подтвердите синхронизацию репозиториев GIT.", "config.countBadge": "\nУправляет счетчиком Git. При указании значения \"all\" подсчитываются все изменения, при указании значения \"tracked\" — только отслеживаемые изменения, при указании значения \"off\" счетчик отключается.", - "config.checkoutType": "Определяет типы ветвей, которые выводятся при выборе пункта меню \"Извлечь в...\". При указании значения \"all\" отображаются все ссылки, \"local\" — только локальные ветви, \"tags\" — только теги, а \"remote\" — только удаленные ветви.", "config.ignoreLegacyWarning": "Игнорирует предупреждение об устаревшей версии Git", "config.ignoreMissingGitWarning": "Игнорирует предупреждение об отсутствии Git", "config.ignoreLimitWarning": "Игнорировать предупреждение, когда в репозитории слишком много изменений", diff --git a/i18n/rus/extensions/typescript/out/commands.i18n.json b/i18n/rus/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..719d56f4f92 --- /dev/null +++ b/i18n/rus/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Откройте папку в VS Code, чтобы использовать проект JavaScript или TypeScript.", + "typescript.projectConfigUnsupportedFile": "Не удалось определить проект TypeScript или JavaScript. Неподдерживаемый тип файла", + "typescript.projectConfigCouldNotGetInfo": "Не удалось определить проект TypeScript или JavaScript.", + "typescript.noTypeScriptProjectConfig": "Файл не является частью проекта TypeScript.", + "typescript.noJavaScriptProjectConfig": "Файл не является частью проекта JavaScript.", + "typescript.configureTsconfigQuickPick": "Настроить tsconfig.json", + "typescript.configureJsconfigQuickPick": "Настроить jsconfig.json", + "typescript.projectConfigLearnMore": "Дополнительные сведения" +} \ No newline at end of file diff --git a/i18n/rus/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/rus/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/rus/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/rus/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/rus/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/base/node/ps.i18n.json b/i18n/rus/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..94c012b641d --- /dev/null +++ b/i18n/rus/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "Сбор информации о процессоре и памяти. Это может занять пару секунд." +} \ No newline at end of file diff --git a/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json index f265f8d9eaa..9d201095183 100644 --- a/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/rus/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Отображаются абсолютные номера строк.", "lineNumbers.relative": "Отображаемые номера строк вычисляются как расстояние в строках до положения курсора.", "lineNumbers.interval": "Номера строк отображаются каждые 10 строк.", - "lineNumbers": "Управляет отображением номеров строк. Возможные значения: \"on\", \"off\" и \"relative\".", + "lineNumbers": "Управляет отображением номеров строк. Возможные значения: 'on', 'off', 'relative' и 'interval'.", "rulers": "Отображать вертикальные линейки после определенного числа моноширинных символов. Для отображения нескольких линеек укажите несколько значений. Если не указано ни одного значения, вертикальные линейки отображаться не будут.", "wordSeparators": "Символы, которые будут использоваться как разделители слов при выполнении навигации или других операций, связанных со словами.", "tabSize": "Число пробелов в табуляции. Этот параметр переопределяется на основе содержимого файла, если установлен параметр \"editor.detectIndentation\".", @@ -40,9 +40,6 @@ "wordWrapColumn": "Определяет столбец переноса редактора, если значение \"editor.wordWrap\" — \"wordWrapColumn\" или \"bounded\".", "wrappingIndent": "Управляет отступом строк с переносом по словам. Допустимые значения: \"none\", \"same\" или \"indent\".", "mouseWheelScrollSensitivity": "Множитель, используемый для параметров deltaX и deltaY событий прокрутки колесика мыши.", - "multiCursorModifier.ctrlCmd": "Соответствует клавише CTRL в Windows и Linux и клавише COMMAND в OS X.", - "multiCursorModifier.alt": "Соответствует клавише ALT в Windows и Linux и клавише OPTION в OS X.", - "multiCursorModifier": "Модификатор, который будет использоваться для добавления нескольких курсоров с помощью мыши. \"ctrlCmd\" соответствует клавише CTRL в Windows и Linux и клавише COMMAND в OS X. Жесты мыши \"Перейти к определению\" и \"Открыть ссылку\" будут изменены так, чтобы они не конфликтовали с несколькими курсорами.", "quickSuggestions.strings": "Разрешение кратких предложений в строках.", "quickSuggestions.comments": "Разрешение кратких предложений в комментариях.", "quickSuggestions.other": "Разрешение кратких предложений вне строк и комментариев.", @@ -72,6 +69,7 @@ "cursorBlinking": "Управляет стилем анимации курсора. Допустимые значения: \"blink\", \"smooth\", \"phase\", \"expand\" и \"solid\"", "mouseWheelZoom": "Изменение размера шрифта в редакторе при нажатой клавише CTRL и движении колесика мыши", "cursorStyle": "Определяет стиль курсора. Допустимые значения: \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" и \"underline-thin\"", + "lineCursorWidth": "Управляет шириной курсора, когда для параметра editor.cursorStyle установлено значение 'line'", "fontLigatures": "Включает лигатуры шрифта.", "hideCursorInOverviewRuler": "Управляет скрытием курсора в обзорной линейке.", "renderWhitespace": "Определяет, должен ли редактор обрабатывать символы пробела; возможные значения: \"none\", \"boundary\" и \"all\". Параметр \"boundary\" не обрабатывает единичные пробелы между словами.", diff --git a/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json index 4801d2ec386..435033a9d39 100644 --- a/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/rus/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,6 @@ { "lineHighlight": "Цвет фона для выделения строки в позиции курсора.", "lineHighlightBorderBox": "Цвет фона границ вокруг строки в позиции курсора.", - "rangeHighlight": "Цвет фона выделенных диапазонов, например в функциях быстрого открытия и поиска.", "caret": "Цвет курсора редактора.", "editorCursorBackground": "Цвет фона курсора редактора. Позволяет настраивать цвет символа, перекрываемого прямоугольным курсором.", "editorWhitespaces": "Цвет пробелов в редакторе.", diff --git a/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 5ca181d11bd..46e2fc5601e 100644 --- a/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Перейти к следующей ошибке или предупреждению", - "markerAction.previous.label": "Перейти к предыдущей ошибке или предупреждению", "editorMarkerNavigationError": "Цвет ошибки в мини-приложении навигации по меткам редактора.", "editorMarkerNavigationWarning": "Цвет предупреждения в мини-приложении навигации по меткам редактора.", "editorMarkerNavigationInfo": "Цвет информационного сообщения в мини-приложении навигации по меткам редактора.", diff --git a/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index ab058cc24db..0894ee93e1f 100644 --- a/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/rus/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Цвет фона символа при доступе на чтение, например считывании переменной.", - "wordHighlightStrong": "Цвет фона символа при доступе на запись, например записи переменной.", "overviewRulerWordHighlightForeground": "Цвет метки линейки в окне просмотра для выделений символов.", "overviewRulerWordHighlightStrongForeground": "Цвет метки линейки в окне просмотра для выделений символов, доступных для записи. ", "wordHighlight.next.label": "Перейти к следующему выделению символов", diff --git a/i18n/rus/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/rus/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index b8216927851..74a4edfb15c 100644 --- a/i18n/rus/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/rus/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "\"{0}\" не является допустимым идентификатором меню", "missing.command": "Элемент меню ссылается на команду \"{0}\", которая не определена в разделе commands.", "missing.altCommand": "Элемент меню ссылается на альтернативную команду \"{0}\", которая не определена в разделе commands.", - "dupe.command": "Элемент меню ссылается на одну и ту же команду как команду по умолчанию и альтернативную команду", - "nosupport.altCommand": "Сейчас только группа navigation меню editor/title поддерживает альтернативные команды" + "dupe.command": "Элемент меню ссылается на одну и ту же команду как команду по умолчанию и альтернативную команду" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/environment/node/argv.i18n.json b/i18n/rus/src/vs/platform/environment/node/argv.i18n.json index 7314aa06087..efe216539da 100644 --- a/i18n/rus/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/rus/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,32 @@ "diff": "Сравнение двух файлов друг с другом", "add": "Добавление папок в последнее активное окно.", "goto": "Открытие файла по указанному пути с выделением указанного символа в указанной строке.", - "locale": "Языковой стандарт, который следует использовать (например, en-US или zh-TW).", "newWindow": "Принудительно запустить новый экземпляр Code.", - "performance": "Запустите с включенной командой \"Developer: Startup Performance\".", - "prof-startup": "Запустить профилировщик ЦП при запуске", - "inspect-extensions": "Разрешить отладку и профилирование расширений. Проверьте URI подключения для инструментов разработчика.", - "inspect-brk-extensions": "Разрешить отладку и профилирование расширений, когда узел расширения приостановлен после запуска. Проверьте URI подключения для инструментов разработчика. ", "reuseWindow": "Принудительно открыть файл или папку в последнем активном окне.", - "userDataDir": "Указывает каталог, в котором хранятся данные пользователей, используется в случае выполнения от имени привилегированного пользователя.", - "log": "Используемый уровень ведения журнала. Значение по умолчанию — \"info\". Допустимые значения: \"critical\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"off\".", - "verbose": "Печать подробного вывода (подразумевает использование параметра \"--wait\").", "wait": "Дождаться закрытия файлов перед возвратом.", + "locale": "Языковой стандарт, который следует использовать (например, en-US или zh-TW).", + "userDataDir": "Указывает каталог, в котором хранятся данные пользователей, используется в случае выполнения от имени привилегированного пользователя.", + "version": "Печать версии.", + "help": "Распечатать данные об использовании.", "extensionHomePath": "Задайте корневой путь для расширений.", "listExtensions": "Перечислить существующие расширения.", "showVersions": "Показать версии установленных расширений при указании параметра --list-extension.", "installExtension": "Устанавливает расширение.", "uninstallExtension": "Удаляет расширение.", "experimentalApis": "Включает предложенные функции API для расширения.", - "disableExtensions": "Отключить все установленные расширения.", - "disableGPU": "Отключить аппаратное ускорение GPU.", + "verbose": "Печать подробного вывода (подразумевает использование параметра \"--wait\").", + "log": "Используемый уровень ведения журнала. Значение по умолчанию — \"info\". Допустимые значения: \"critical\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"off\".", "status": "Выводить сведения об использовании процесса и диагностическую информацию.", - "version": "Печать версии.", - "help": "Распечатать данные об использовании.", + "performance": "Запустите с включенной командой \"Developer: Startup Performance\".", + "prof-startup": "Запустить профилировщик ЦП при запуске", + "disableExtensions": "Отключить все установленные расширения.", + "inspect-extensions": "Разрешить отладку и профилирование расширений. Проверьте URI подключения для инструментов разработчика.", + "inspect-brk-extensions": "Разрешить отладку и профилирование расширений, когда узел расширения приостановлен после запуска. Проверьте URI подключения для инструментов разработчика. ", + "disableGPU": "Отключить аппаратное ускорение GPU.", "usage": "Использование", "options": "параметры", "paths": "пути", + "stdinWindows": "Чтобы прочитать вывод другой программы, добавьте '-' (например 'echo Hello World | {0} -')", + "stdinUnix": "Чтобы получить данные с stdin, добавьте '-' (например, 'ps aux | grep code | {0} -')\n", "optionsUpperCase": "Параметры" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index c25a9a85ff7..54111e4751d 100644 --- a/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/rus/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,13 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Недопустимое расширение: package.json не является файлом JSON.", - "restartCodeLocal": "Перезапустите код перед переустановкой {0}.", + "restartCode": "Перезапустите код перед переустановкой {0}.", "installingOutdatedExtension": "Уже установлена более новая версия этого расширения. Вы хотите переопределить ее более старой версией?", "override": "Переопределить", "cancel": "Отмена", - "notFoundCompatible": "Не удается выполнить установку, так как не найдено расширение '{0}', совместимое с текущей версией VS Code '{1}'.", - "quitCode": "Не удается выполнить установку, так как устаревший экземпляр расширения еще запущен. Закройте и снова откройте VS Code, затем запустите установку повторно.", - "exitCode": "Не удается выполнить установку, так как устаревший экземпляр расширения еще запущен. Закройте и снова откройте VS Code, затем запустите установку повторно. ", + "notFoundCompatible": "Невозможно установить '{0}'; нет версии, совместимой с VS Code '{1}'.", "notFoundCompatibleDependency": "Не удается выполнить установку, так как не найдено зависимое расширение '{0}', совместимое с текущей версией VS Code '{1}'. ", + "exitCode": "Невозможно установить расширение. Пожалуйста, выйдите и зайдите в VS Code перед переустановкой.", "uninstallDependeciesConfirmation": "Вы хотите удалить \"{0}\" отдельно или вместе с зависимостями?", "uninstallOnly": "Только", "uninstallAll": "Все", diff --git a/i18n/rus/src/vs/platform/list/browser/listService.i18n.json b/i18n/rus/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..933a96a0d6f --- /dev/null +++ b/i18n/rus/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Рабочее место" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/message/common/message.i18n.json b/i18n/rus/src/vs/platform/message/common/message.i18n.json index 62863fdeb53..aab52c88b34 100644 --- a/i18n/rus/src/vs/platform/message/common/message.i18n.json +++ b/i18n/rus/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Закрыть", "later": "Позже", - "cancel": "Отмена" + "cancel": "Отмена", + "moreFile": "...1 дополнительный файл не показан", + "moreFiles": "...не показано дополнительных файлов: {0}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json index 98e2cebe278..bbb9e4cefb0 100644 --- a/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/rus/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,7 @@ "editorWidgetBorder": "Цвет границы мини-приложений редактора. Этот цвет используется только в том случае, если у мини-приложения есть граница и если этот цвет не переопределен мини-приложением.", "editorSelectionBackground": "Цвет выделения редактора.", "editorSelectionForeground": "Цвет выделенного текста в режиме высокого контраста.", - "editorInactiveSelection": "Цвет выделения в неактивном редакторе.", - "editorSelectionHighlight": "Цвет регионов с тем же содержимым, что и в выделении.", "editorFindMatch": "Цвет текущего поиска совпадений.", - "findMatchHighlight": "Цвет других совпадений поиска.", - "findRangeHighlight": "Цвет диапазона, ограничивающего поиск.", - "hoverHighlight": "Выделение под словом, для которого показано наведение.", "hoverBackground": "Цвет фона при наведении указателя на редактор.", "hoverBorder": "Цвет границ при наведении указателя на редактор.", "activeLinkForeground": "Цвет активных ссылок.", @@ -76,12 +71,6 @@ "diffEditorRemoved": "Цвет фона для удаленных строк.", "diffEditorInsertedOutline": "Цвет контура для добавленных строк.", "diffEditorRemovedOutline": "Цвет контура для удаленных строк.", - "mergeCurrentHeaderBackground": "Цвет фона текущего заголовка во внутренних конфликтах слияния.", - "mergeCurrentContentBackground": "Цвет фона текущего содержимого во внутренних конфликтах слияния.", - "mergeIncomingHeaderBackground": "Цвет фона входящего заголовка во внутренних конфликтах слияния.", - "mergeIncomingContentBackground": "Цвет фона входящего содержимого во внутренних конфликтах слияния.", - "mergeCommonHeaderBackground": "Цвет фона заголовка для общего предка во внутренних конфликтах слияния.", - "mergeCommonContentBackground": "Цвет фона содержимого для общего предка во внутренних конфликтах слияния.", "mergeBorder": "Цвет границы заголовков и разделителя во внутренних конфликтах слияния.", "overviewRulerCurrentContentForeground": "Цвет переднего плана линейки текущего окна во внутренних конфликтах слияния.", "overviewRulerIncomingContentForeground": "Цвет переднего плана линейки входящего окна во внутренних конфликтах слияния.", diff --git a/i18n/rus/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/rus/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..16bdf1f2fc4 --- /dev/null +++ b/i18n/rus/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "свойство \"{0}\" является обязательным и должно иметь тип string", + "optstring": "свойство \"{0}\" может быть опущено или должно иметь тип string" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/rus/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/rus/src/vs/workbench/api/node/extHostTreeViews.i18n.json index 9f9c8f9221d..9dad9f3a71b 100644 --- a/i18n/rus/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/rus/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -4,7 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "treeView.notRegistered": "Отсутствует зарегистрированное представление в виде дерева с идентификатором '{0}'.", - "treeItem.notFound": "Отсутствует элемент дерева с идентификатором '{0}'.", - "treeView.duplicateElement": "Элемент {0} уже зарегистрирован" + "treeView.notRegistered": "Отсутствует зарегистрированное представление в виде дерева с идентификатором '{0}'." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/rus/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index 3e03b98e62c..b88aead69da 100644 --- a/i18n/rus/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Расположение боковой панели", "view": "Просмотреть" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json index 7f87d17117e..c63304e93ba 100644 --- a/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Открыть файл...", "openFolder": "Открыть папку...", "openFileFolder": "Открыть...", - "addFolderToWorkspace": "Добавить папку в рабочую область...", - "add": "&&Добавить", - "addFolderToWorkspaceTitle": "Добавить папку в рабочую область", "globalRemoveFolderFromWorkspace": "Удалить папку из рабочей области...", - "removeFolderFromWorkspace": "Удалить папку из рабочей области", - "openFolderSettings": "Открыть параметры папок", "saveWorkspaceAsAction": "Сохранить рабочую область как...", "save": "Сохранить", "saveWorkspace": "Сохранить рабочую область", "openWorkspaceAction": "Открыть рабочую область...", "openWorkspaceConfigFile": "Открыть файл конфигурации рабочей области", - "openFolderAsWorkspaceInNewWindow": "Открыть папку как рабочую область в новом окне", - "workspaceFolderPickerPlaceholder": "Выберите папку рабочей области" + "openFolderAsWorkspaceInNewWindow": "Открыть папку как рабочую область в новом окне" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/rus/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..80b92b74445 --- /dev/null +++ b/i18n/rus/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Добавить папку в рабочую область...", + "add": "&&Добавить", + "addFolderToWorkspaceTitle": "Добавить папку в рабочую область", + "workspaceFolderPickerPlaceholder": "Выберите папку рабочей области" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 3c123d9ce41..6382785efa1 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,17 @@ "groupThreePicker": "Показать редакторы в третьей группе", "allEditorsPicker": "Показать все открытые редакторы", "view": "Просмотр", - "file": "Файл" + "file": "Файл", + "close": "Закрыть", + "closeOthers": "Закрыть другие", + "closeRight": "Закрыть справа", + "closeAllUnmodified": "Закрыть без изменений", + "closeAll": "Закрыть все", + "keepOpen": "Оставить открытым", + "showOpenedEditors": "Показать открытые редакторы", + "keepEditor": "Сохранить редактор", + "closeEditorsInGroup": "Закрыть все редакторы в группе", + "closeUnmodifiedEditors": "Закрыть редакторы без изменений в группе", + "closeOtherEditors": "Закрыть другие редакторы", + "closeRightEditors": "Закрыть редакторы справа" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index 4dba80c961d..f1572dc1c18 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Закрыть редактор", "revertAndCloseActiveEditor": "Отменить изменения и закрыть редактор", "closeEditorsToTheLeft": "Закрыть редакторы слева", - "closeEditorsToTheRight": "Закрыть редакторы справа", "closeAllEditors": "Закрыть все редакторы", - "closeUnmodifiedEditors": "Закрыть редакторы без изменений в группе", "closeEditorsInOtherGroups": "Закрыть редакторы в других группах", - "closeOtherEditorsInGroup": "Закрыть другие редакторы", - "closeEditorsInGroup": "Закрыть все редакторы в группе", "moveActiveGroupLeft": "Переместить группу редакторов влево", "moveActiveGroupRight": "Переместить группу редакторов вправо", "minimizeOtherEditorGroups": "Свернуть другие группы редакторов", "evenEditorGroups": "Уравнять ширину групп редакторов", "maximizeEditor": "Развернуть группу редакторов и скрыть боковую панель", - "keepEditor": "Сохранить редактор", "openNextEditor": "Открыть следующий редактор", "openPreviousEditor": "Открыть предыдущий редактор", "nextEditorInGroup": "Открыть следующий редактор в группе", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "Показать редакторы в первой группе", "showEditorsInSecondGroup": "Показать редакторы во второй группе", "showEditorsInThirdGroup": "Показать редакторы в третьей группе", - "showEditorsInGroup": "Показать редакторы в группе", "showAllEditors": "Показать все редакторы", "openPreviousRecentlyUsedEditorInGroup": "Открыть предыдущий недавно использованный редактор в группе", "openNextRecentlyUsedEditorInGroup": "Открыть следующий недавно использованный редактор в группе", diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 32e566863c8..64223b3c4b5 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Перемещение активного редактора по вкладкам или группам", "editorCommand.activeEditorMove.arg.name": "Аргумент перемещения активного редактора", - "editorCommand.activeEditorMove.arg.description": "Свойства аргумента:\n\t* 'to': строковое значение, указывающее направление перемещения.\n\t* 'by': строковое значение, указывающее единицу перемещения (вкладка или группа).\n\t* 'value': числовое значение, указывающее количество позиций перемещения или абсолютную позицию для перемещения.", - "commandDeprecated": "Команда **{0}** удалена. Вместо нее можно использовать **{1}**", - "openKeybindings": "Настройка сочетаний клавиш" + "editorCommand.activeEditorMove.arg.description": "Свойства аргумента:\n\t* 'to': строковое значение, указывающее направление перемещения.\n\t* 'by': строковое значение, указывающее единицу перемещения (вкладка или группа).\n\t* 'value': числовое значение, указывающее количество позиций перемещения или абсолютную позицию для перемещения." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 7e9ef4fb62e..f8b0ee45376 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -10,7 +10,5 @@ "editableEditorWithInputAriaLabel": "{0}. Редактор сравнения текстовых файлов.", "editableEditorAriaLabel": "Редактор сравнения текстовых файлов.", "navigate.next.label": "Следующее исправление", - "navigate.prev.label": "Предыдущее исправление", - "inlineDiffLabel": "Переключиться на представление в строке", - "sideBySideDiffLabel": "Переключиться на параллельное представление" + "navigate.prev.label": "Предыдущее исправление" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index f09bdce2324..cf0dce309ed 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Закрыть", - "closeOthers": "Закрыть другие", - "closeRight": "Закрыть справа", - "closeAll": "Закрыть все", - "closeAllUnmodified": "Закрыть без изменений", - "keepOpen": "Оставить открытым", - "showOpenedEditors": "Показать открытые редакторы", "araLabelEditorActions": "Действия редактора" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/rus/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index 6dd99f557bc..8b6ad71cd4e 100644 --- a/i18n/rus/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/rus/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -3,6 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. -{ - "hideView": "Скрыть из боковой панели" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/common/theme.i18n.json b/i18n/rus/src/vs/workbench/common/theme.i18n.json index bd0d0f8b98b..364c328c4c0 100644 --- a/i18n/rus/src/vs/workbench/common/theme.i18n.json +++ b/i18n/rus/src/vs/workbench/common/theme.i18n.json @@ -16,7 +16,6 @@ "editorGroupBackground": "Цвет фона группы редакторов. Группы редакторов представляют собой контейнеры редакторов. Цвет фона отображается при перетаскивании групп редакторов.", "tabsContainerBackground": "Цвет фона для заголовка группы редакторов, когда вкладки включены. Группы редакторов представляют собой контейнеры редакторов.", "tabsContainerBorder": "Цвет границы для заголовка группы редакторов, когда вкладки включены. Группы редакторов представляют собой контейнеры редакторов.", - "editorGroupHeaderBackground": "Цвет фона для заголовка группы редакторов, когда вкладки отключены. Группы редакторов представляют собой контейнеры редакторов.", "editorGroupBorder": "Цвет для разделения нескольких групп редакторов. Группы редакторов — это контейнеры редакторов.", "editorDragAndDropBackground": "Цвет фона при перетаскивании редакторов. Этот цвет должен обладать прозрачностью, чтобы содержимое редактора оставалось видимым.", "panelBackground": "Цвет фона панели. Панели показаны под областью редактора и содержат такие представления, как выходные данные и встроенный терминал.", @@ -33,8 +32,6 @@ "statusBarNoFolderBorder": "Цвет границы строки состояния, который распространяется на боковую панель и редактор, когда открытые папки отсутствуют. Строка состояния расположена в нижней части окна.", "statusBarItemActiveBackground": "Цвет фона элементов панели состояния при щелчке. Панель состояния отображается внизу окна.", "statusBarItemHoverBackground": "Цвет фона элементов панели состояния при наведении. Панель состояния отображается внизу окна.", - "statusBarProminentItemBackground": "Цвет фона приоритетных элементов панели состояния. Приоритетные элементы выделяются на фоне других элементов панели состояния, чтобы подчеркнуть их значение. Панель состояния отображается в нижней части окна.", - "statusBarProminentItemHoverBackground": "Цвет фона приоритетных элементов панели состояния при наведении. Приоритетные элементы выделяются на фоне других элементов панели состояния, чтобы подчеркнуть их значение. Панель состояния отображается в нижней части окна.", "activityBarBackground": "Цвет фона панели действий. Панель действий отображается слева или справа и позволяет переключаться между представлениями боковой панели.", "activityBarForeground": "Цвет переднего плана панели действий (например, цвет, используемый для значков). Панель действий отображается слева или справа и позволяет переключаться между представлениями боковой панели.", "activityBarBorder": "Цвет границы панели действий, который распространяется на боковую панель. Панель действий отображается слева или справа и позволяет переключаться между представлениями в боковой панели.", diff --git a/i18n/rus/src/vs/workbench/common/views.i18n.json b/i18n/rus/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..2feabab41e5 --- /dev/null +++ b/i18n/rus/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "Представление с идентификатором '{0}' уже зарегистрировано в расположении '{1}'" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json index 2380d05741c..5768ee78d85 100644 --- a/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/rus/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Закрыть редактор", "closeWindow": "Закрыть окно", "closeWorkspace": "Закрыть рабочую область", "noWorkspaceOpened": "В этом экземпляре отсутствуют открытые рабочие области.", @@ -52,21 +51,5 @@ "displayLanguage": "Определяет язык интерфейса VSCode.", "doc": "Список поддерживаемых языков см. в {0}.", "restart": "Для изменения значения требуется перезапуск VSCode.", - "fail.createSettings": "Невозможно создать \"{0}\" ({1}).", - "openLogsFolder": "Открыть папку журналов", - "showLogs": "Показать журналы...", - "mainProcess": "Главный", - "sharedProcess": "Общий", - "rendererProcess": "Отрисовщик", - "extensionHost": "Узел расширения", - "selectProcess": "Выберите процесс", - "setLogLevel": "Установите уровень ведения журнала", - "trace": "Трассировка", - "debug": "Отладка", - "info": "Сведения", - "warn": "Предупреждение", - "err": "Ошибка", - "critical": "Критический", - "off": "Отключено", - "selectLogLevel": "Установите уровень ведения журнала" + "fail.createSettings": "Невозможно создать \"{0}\" ({1})." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json index f0c8c83bedf..e6779131585 100644 --- a/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Просмотреть", "help": "Справка", "file": "Файл", - "developer": "Разработчик", "workspaces": "Рабочие области", + "developer": "Разработчик", + "workbenchConfigurationTitle": "Workbench", "showEditorTabs": "Определяет, должны ли открытые редакторы отображаться на вкладках или нет.", "workbench.editor.labelFormat.default": "Отображать имя файла. Если вкладки включены и в одной группе есть два файла с одинаковыми именами, то к имени каждого из этих файлов будут добавлены различающиеся части пути. Если вкладки отключены, то для активного редактора отображается путь по отношению к папке рабочей области.", "workbench.editor.labelFormat.short": "Отображать имя файла и имя каталога.", @@ -20,8 +21,10 @@ "showIcons": "Определяет, должны ли открытые редакторы отображаться со значком. Требует включить тему значков.", "enablePreview": "Определяет, отображаются ли открытые редакторы в режиме предварительного просмотра. Редакторы в режиме предварительного просмотра можно использовать, пока они открыты (например, с помощью двойного щелчка мыши или изменения). Текст в таких редакторах отображается курсивом.", "enablePreviewFromQuickOpen": "Определяет, отображаются ли редакторы из Quick Open в режиме предварительного просмотра. Редакторы в режиме предварительного просмотра повторно используются до сохранения (например, с помощью двойного щелчка или изменения).", + "closeOnFileDelete": "Определяет, следует ли автоматически закрывать редакторы, когда отображаемый в них файл удален или переименован другим процессом. При отключении этой функции редактор остается открытым в качестве черновика. Обратите внимание, что при удалении из приложения редактор закрывается всегда и что файлы черновиков никогда не закрываются для сохранения данных.", "editorOpenPositioning": "Определяет место открытия редакторов. Выберите 'left' или 'right', чтобы открывать редакторы слева или справа от активного редактора. Выберите 'first' или 'last', чтобы открывать редакторы независимо от активного редактора.", "revealIfOpen": "Определяет, отображается ли редактор в какой-либо из видимых групп при открытии. Если функция отключена, редактор открывается в текущей активной группе редакторов. Если функция включена, вместо открытия уже открытый редактор будет отображен в текущей активной группе редакторов. Обратите внимание, что в некоторых случаях этот параметр игнорируется, например при принудительном открытии редактора в определенной группе или сбоку от текущей активной группы редакторов.", + "swipeToNavigate": "Переключайтесь между открытыми файлами, проводя по экрану по горизонтали тремя пальцами.", "commandHistory": "Определяет количество недавно использованных команд, которые следует хранить в журнале палитры команд. Установите значение 0, чтобы отключить журнал команд.", "preserveInput": "Определяет, следует ли восстановить последнюю введенную команду в палитре команд при следующем открытии палитры.", "closeOnFocusLost": "Управляет автоматическим закрытием Quick Open при потере фокуса.", @@ -29,14 +32,11 @@ "sideBarLocation": "Определяет расположение боковой панели: слева или справа от рабочего места.", "statusBarVisibility": "Управляет видимостью строки состояния в нижней части рабочего места.", "activityBarVisibility": "Управляет видимостью панели действий на рабочем месте.", - "closeOnFileDelete": "Определяет, следует ли автоматически закрывать редакторы, когда отображаемый в них файл удален или переименован другим процессом. При отключении этой функции редактор остается открытым в качестве черновика. Обратите внимание, что при удалении из приложения редактор закрывается всегда и что файлы черновиков никогда не закрываются для сохранения данных.", - "enableNaturalLanguageSettingsSearch": "Определяет, следует ли включить режим поиска естественного языка для параметров.", "fontAliasing": "Управляет методом сглаживания шрифтов в рабочей области.-по умолчанию: субпиксельное сглаживание шрифтов; позволит добиться максимальной четкости текста на большинстве дисплеев за исключением Retina - сглаживание: сглаживание шрифтов на уровне пикселей, в отличие от субпиксельного сглаживания; позволит сделать шрифт более светлым в целом - нет: сглаживание шрифтов отключено; текст будет отображаться с неровными острыми краями ", "workbench.fontAliasing.default": "Субпиксельное сглаживание шрифтов; позволит добиться максимальной четкости текста на большинстве дисплеев за исключением Retina.", "workbench.fontAliasing.antialiased": "Сглаживание шрифтов на уровне пикселей, в отличие от субпиксельного сглаживания. Может сделать шрифт светлее в целом.", "workbench.fontAliasing.none": "Отключает сглаживание шрифтов; текст будет отображаться с неровными острыми краями.", - "swipeToNavigate": "Переключайтесь между открытыми файлами, проводя по экрану по горизонтали тремя пальцами.", - "workbenchConfigurationTitle": "Workbench", + "enableNaturalLanguageSettingsSearch": "Определяет, следует ли включить режим поиска естественного языка для параметров.", "windowConfigurationTitle": "Окно", "window.openFilesInNewWindow.on": "Файлы будут открываться в новом окне.", "window.openFilesInNewWindow.off": "Файлы будут открываться в окне с открытой папкой файлов или последнем активном окне.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index 63d876aca0d..c98dad92f14 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "Конфигурации схемы JSON для проверки launch.json.", "vscode.extension.contributes.debuggers.windows": "Параметры, связанные с Windows.", "vscode.extension.contributes.debuggers.windows.runtime": "Среда выполнения, используемая для Windows.", - "vscode.extension.contributes.debuggers.osx": "Параметры, связанные с OS X.", - "vscode.extension.contributes.debuggers.osx.runtime": "Среда выполнения, используемая для OS X.", "vscode.extension.contributes.debuggers.linux": "Параметры, связанные с Linux.", "vscode.extension.contributes.debuggers.linux.runtime": "Среда выполнения, используемая для Linux.", "vscode.extension.contributes.breakpoints": "Добавляет точки останова.", diff --git a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index 64ed05c0958..80636157f78 100644 --- a/i18n/rus/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "отлаживаемый объект", - "debug.terminal.not.available.error": "Интегрированный терминал недоступен." + "debug.terminal.title": "отлаживаемый объект" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 4671a2c1d23..7b4f9ca1fd9 100644 --- a/i18n/rus/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Открыть новую командную строку", "globalConsoleActionMacLinux": "Открыть новый терминал", "scopedConsoleActionWin": "Открыть в командной строке", - "scopedConsoleActionMacLinux": "Открыть в терминале", - "openFolderInIntegratedTerminal": "Открыть в терминале" + "scopedConsoleActionMacLinux": "Открыть в терминале" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 3e00ebd8896..f674a1cb200 100644 --- a/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Рекомендуется использовать это расширение (на основе недавно открытых файлов).", + "neverShowAgain": "Больше не показывать", + "close": "Закрыть", "workspaceRecommendation": "Это расширение рекомендуется пользователями текущей рабочей области.", + "fileBasedRecommendation": "Рекомендуется использовать это расширение (на основе недавно открытых файлов).", "exeBasedRecommendation": "Рекомендуется использовать это расширение, так как установлено {0}.", "reallyRecommended2": "Для этого типа файлов рекомендуется использовать расширение '{0}'.", "reallyRecommendedExtensionPack": "Для этого типа файлов рекомендуется использовать пакет расширений '{0}'.", "showRecommendations": "Показать рекомендации", "install": "Установить", - "neverShowAgain": "Больше не показывать", - "close": "Закрыть", "workspaceRecommended": "Эта рабочая область включает рекомендации по расширениям.", "installAll": "Установить все", "ignoreExtensionRecommendations": "Вы действительно хотите проигнорировать все рекомендации по расширениям?", diff --git a/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..933a96a0d6f --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Рабочее место" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 821930bfc87..8ff5f3c27f7 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,24 @@ "filesCategory": "Файл", "revealInSideBar": "Показать в боковой панели", "acceptLocalChanges": "Использовать изменения и перезаписать содержимое диска", - "revertLocalChanges": "Отменить изменения и вернуться к содержимому на диске" + "revertLocalChanges": "Отменить изменения и вернуться к содержимому на диске", + "copyPathOfActive": "Копировать путь к активному файлу", + "saveAllInGroup": "Сохранить все в группе", + "revert": "Отменить изменения в файле", + "compareActiveWithSaved": "Сравнить активный файл с сохраненным", + "closeEditor": "Закрыть редактор", + "view": "Просмотр", + "openToSide": "Открыть сбоку", + "revealInWindows": "Отобразить в проводнике", + "revealInMac": "Отобразить в Finder", + "openContainer": "Открыть содержащую папку", + "copyPath": "Скопировать путь", + "saveAll": "Сохранить все", + "compareWithSaved": "Сравнить с сохраненным", + "compareSource": "Выбрать для сравнения", + "close": "Закрыть", + "closeOthers": "Закрыть другие", + "closeUnmodified": "Закрыть без изменений", + "closeAll": "Закрыть все", + "deleteFile": "Удалить навсегда" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 8e87ab6930a..33066ff5f33 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Повторить попытку", - "rename": "Переименовать", "newFile": "Создать файл", "newFolder": "Создать папку", + "rename": "Переименовать", + "delete": "Удалить", + "copyFile": "Копировать", + "pasteFile": "Вставить", + "retry": "Повторить попытку", "openFolderFirst": "Сначала откройте папку, в которой будут созданы файлы и папки.", "newUntitledFile": "Новый файл без имени", "createNewFile": "Создать файл", @@ -28,26 +31,14 @@ "confirmDeleteMessageFile": "Вы действительно хотите удалить \"{0}\" без возможности восстановления?", "irreversible": "Это действие необратимо.", "permDelete": "Удалить навсегда", - "delete": "Удалить", "importFiles": "Импорт файлов", "confirmOverwrite": "Файл или папка с таким именем уже существует в конечной папке. Заменить их?", "replaceButtonLabel": "Заменить", - "copyFile": "Копировать", - "pasteFile": "Вставить", "duplicateFile": "Дублировать", - "openToSide": "Открыть сбоку", - "compareSource": "Выбрать для сравнения", "globalCompareFile": "Сравнить активный файл с...", "openFileToCompare": "Чтобы сравнить файл с другим файлом, сначала откройте его.", - "compareWith": "Сравнить '{0}' с '{1}'", - "compareFiles": "Сравнить файлы", "refresh": "Обновить", - "save": "Сохранить", - "saveAs": "Сохранить как...", - "saveAll": "Сохранить все", "saveAllInGroup": "Сохранить все в группе", - "saveFiles": "Сохранить все файлы", - "revert": "Отменить изменения в файле", "focusOpenEditors": "Фокус на представлении открытых редакторов", "focusFilesExplorer": "Фокус на проводнике", "showInExplorer": "Показать активный файл в боковой панели", @@ -56,20 +47,11 @@ "refreshExplorer": "Обновить окно проводника", "openFileInNewWindow": "Открыть активный файл в новом окне", "openFileToShowInNewWindow": "Чтобы открыть файл в новом окне, сначала откройте его.", - "revealInWindows": "Отобразить в проводнике", - "revealInMac": "Отобразить в Finder", - "openContainer": "Открыть содержащую папку", - "revealActiveFileInWindows": "Отобразить активный файл в проводнике", - "revealActiveFileInMac": "Отобразить активный файл в Finder", - "openActiveFileContainer": "Открыть папку, содержащую активный файл", "copyPath": "Скопировать путь", - "copyPathOfActive": "Копировать путь к активному файлу", "emptyFileNameError": "Необходимо указать имя файла или папки.", "fileNameExistsError": "Файл или папка **{0}** уже существует в данном расположении. Выберите другое имя.", "invalidFileNameError": "Имя **{0}** недопустимо для файла или папки. Выберите другое имя.", "filePathTooLongError": "Из-за использования имени **{0}** путь слишком длинный. Выберите более короткое имя.", - "compareWithSaved": "Сравнить активный файл с сохраненным", - "modifiedLabel": "{0} (на диске) ↔ {1}", "compareWithClipboard": "Сравнить активный файл с буфером обмена", "clipboardComparisonLabel": "Буфер обмена ↔ {0}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index f51fb88b34b..18416689c01 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Чтобы скопировать путь к файлу, сначала откройте его", - "openFileToReveal": "Чтобы отобразить файл, сначала откройте его" + "revealInWindows": "Отобразить в проводнике", + "revealInMac": "Отобразить в Finder", + "openContainer": "Открыть содержащую папку", + "saveAs": "Сохранить как...", + "save": "Сохранить", + "saveAll": "Сохранить все", + "removeFolderFromWorkspace": "Удалить папку из рабочей области", + "modifiedLabel": "{0} (на диске) ↔ {1}", + "openFileToReveal": "Чтобы отобразить файл, сначала откройте его", + "openFileToCopy": "Чтобы скопировать путь к файлу, сначала откройте его" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index d0ffe58b0f9..6f4f5194bc6 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "Редактор", "formatOnSave": "Форматирование файла при сохранении. Модуль форматирования должен быть доступен, файл не должен сохраняться автоматически, а работа редактора не должна завершаться.", "explorerConfigurationTitle": "Проводник", - "openEditorsVisible": "Число редакторов, отображаемых на панели открытых редакторов. Задайте значение 0, чтобы скрыть панель.", - "dynamicHeight": "Определяет, будет ли высота раздела открытых редакторов динамически адаптироваться к количеству элементов.", "autoReveal": "Определяет, будет ли проводник автоматически отображать и выбирать файлы при их открытии.", "enableDragAndDrop": "Определяет, разрешено ли перемещение файлов и папок перетаскиванием в проводнике.", "confirmDragAndDrop": "Определяет, должно ли запрашиваться подтверждение при перемещении файлов и папок в проводнике.", diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index d5622eec39a..a99d73ed519 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,9 @@ // Do not edit this file. It is machine generated. { "userGuide": "Используйте команды на панели инструментов редактора справа для **отмены** изменений или **перезаписи** содержимого на диске с учетом этих изменений", - "discard": "Отмена", "overwrite": "Перезаписать", "retry": "Повторить попытку", - "readonlySaveError": "Не удалось сохранить \"{0}\": файл защищен от записи. Чтобы снять защиту, нажмите \"Перезаписать\".", + "discard": "Отмена", "genericSaveError": "Не удалось сохранить \"{0}\": {1}", "staleSaveError": "Не удалось сохранить \"{0}\": содержимое на диске более новое. Чтобы сравнить свою версию с версией на диске, нажмите **Сравнить**.", "compareChanges": "Сравнить", diff --git a/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index ecfb243efe9..e8bc16acb29 100644 --- a/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Открытые редакторы", "openEditosrSection": "Раздел открытых редакторов", - "dirtyCounter": "Не сохранено: {0}", - "saveAll": "Сохранить все", - "closeAllUnmodified": "Закрыть без изменений", - "closeAll": "Закрыть все", - "compareWithSaved": "Сравнить с сохраненным", - "close": "Закрыть", - "closeOthers": "Закрыть другие" + "dirtyCounter": "Не сохранено: {0}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..fa130c143cf --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "developer": "Разработчик" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..6d7a48207b9 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Открыть папку журналов", + "mainProcess": "Главный", + "sharedProcess": "Общий", + "rendererProcess": "Окно", + "extensionHost": "Узел расширения", + "setLogLevel": "Установите уровень ведения журнала", + "trace": "Трассировка", + "debug": "Отладка", + "info": "Сведения", + "warn": "Предупреждение", + "err": "Ошибка", + "off": "Отключено", + "selectLogLevel": "Установите уровень ведения журнала" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/rus/src/vs/workbench/parts/markers/common/messages.i18n.json index 4a0ebeccf87..c561464b583 100644 --- a/i18n/rus/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Просмотреть", - "problems.view.toggle.label": "Показать/скрыть проблемы", - "problems.view.focus.label": "Проблемы с фокусом", "problems.panel.configuration.title": "Представление \"Проблемы\"", "problems.panel.configuration.autoreveal": "Определяет, следует ли представлению \"Проблемы\" отображать файлы при их открытии", "markers.panel.title.problems": "Проблемы", diff --git a/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..68cc0434ecd --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Вывод", + "viewCategory": "Просмотр", + "clearOutput.label": "Очистить выходные данные" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/rus/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index cdba5fc34b2..aa42a73f571 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Попробуйте режим поиска естественного языка!", "defaultSettings": "Чтобы переопределить параметры по умолчанию, укажите свои параметры в области справа.", "noSettingsFound": "Параметры не найдены.", "settingsSwitcherBarAriaLabel": "Переключатель параметров", "userSettings": "Параметры пользователя", "workspaceSettings": "Параметры рабочей области", - "folderSettings": "Параметры папок", - "enableFuzzySearch": "Включить режим поиска естественного языка" + "folderSettings": "Параметры папок" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/rus/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index 345c107b419..3305d6aa84d 100644 --- a/i18n/rus/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Часто используемые", - "mostRelevant": "Наиболее релевантные", "defaultKeybindingsHeader": "Перезапишите настраиваемое сочетание клавиш, поместив их в файл настраиваемых сочетаний клавиш." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index a683b0d8467..f0071d32bf8 100644 --- a/i18n/rus/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Просмотр", "commandsHandlerDescriptionDefault": "Показать и выполнить команды", "gotoLineDescriptionMac": "Перейти к строке", "gotoLineDescriptionWin": "Перейти к строке", diff --git a/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 029a91dd121..9b3baff6083 100644 --- a/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,6 @@ "toggleGitViewlet": "Показать GIT", "source control": "Система управления версиями", "toggleSCMViewlet": "Показать SCM", - "view": "Просмотреть" + "view": "Просмотреть", + "scmConfigurationTitle": "SCM" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json index acbdea84856..cd1b6966535 100644 --- a/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Показать предыдущее условие поиска", "showSearchViewlet": "Показать средство поиска", "findInFiles": "Найти в файлах", - "findInFilesWithSelectedText": "Найти в файлах с выделенным текстом", "replaceInFiles": "Заменить в файлах", - "replaceInFilesWithSelectedText": "Заменить в файлах с выделенным текстом", "RefreshAction.label": "Обновить", "CollapseDeepestExpandedLevelAction.label": "Свернуть все", "ClearSearchResultsAction.label": "Очистить", diff --git a/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index fb91734ab3b..ad29f26eb2e 100644 --- a/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -7,10 +7,11 @@ "showTriggerActions": "Перейти к символу в рабочей области...", "name": "Поиск", "search": "Поиск", + "showSearchViewlet": "Показать средство поиска", "view": "Просмотр", + "findInFiles": "Найти в файлах", "openAnythingHandlerDescription": "Перейти к файлу", "openSymbolDescriptionNormal": "Перейти к символу в рабочей области", - "searchOutputChannelTitle": "Поиск", "searchConfigurationTitle": "Поиск", "exclude": "Настройте стандартные маски для исключения файлов и папок при поиске. Все стандартные маски наследуются от параметра file.exclude.", "exclude.boolean": "Стандартная маска, соответствующая путям к файлам. Задайте значение true или false, чтобы включить или отключить маску.", diff --git a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..26ab76b193c --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "Параметры" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index a3a8c117e65..0bfa5d00f22 100644 --- a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Выберите язык для фрагментов кода", - "openSnippet.errorOnCreate": "Не удалось создать {0}.", - "openSnippet.label": "Открыть пользовательские фрагменты", - "preferences": "Параметры", "snippetSchema.json.default": "Пустой фрагмент", "snippetSchema.json": "Настройка фрагмента пользователя", "snippetSchema.json.prefix": "Префикс, используемый при выборе фрагмента в Intellisense.", diff --git a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..dd3a311fe89 --- /dev/null +++ b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Фрагмент кода пользователя" +} \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index 6c5ec091a1a..afe0462f8a1 100644 --- a/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "Неизвестный язык в contributes.{0}.language. Указанное значение: {1}", "invalid.path.0": "В contributes.{0}.path требуется строка. Указанное значение: {1}", + "invalid.language": "Неизвестный язык в contributes.{0}.language. Указанное значение: {1}", "invalid.path.1": "contributes.{0}.path ({1}) должен был быть включен в папку расширения ({2}). Это может сделать расширение непереносимым.", "vscode.extension.contributes.snippets": "Добавляет фрагменты.", "vscode.extension.contributes.snippets-language": "Идентификатор языка, для которого добавляется этот фрагмент.", "vscode.extension.contributes.snippets-path": "Путь к файлу фрагментов. Путь указывается относительно папки расширения и обычно начинается с \"./snippets/\".", "badVariableUse": "Похоже, что в одном или нескольких фрагментах расширения \"{0}\" перепутаны переменные и заполнители. Дополнительные сведения см. на странице https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax.", "badFile": "Не удалось прочитать файл фрагмента \"{0}\".", - "source.snippet": "Фрагмент кода пользователя", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index fc208588fb0..04ba7d28169 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "Цвет переднего плана терминала.", "terminalCursor.foreground": "Цвет переднего плана курсора терминала.", "terminalCursor.background": "Цвет фона курсора терминала. Позволяет выбрать цвет символа, который перекрывается блочным курсором.", - "terminal.selectionBackground": "Цвет фона выделения терминала.", - "terminal.ansiColor": "Цвет ANSI \"{0}\" в терминале." + "terminal.selectionBackground": "Цвет фона выделения терминала." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index 440d374ef82..9de408a9653 100644 --- a/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/rus/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "Вы можете изменить оболочку терминала по умолчанию, нажав кнопку \"Настроить\".", "customize": "Настроить", "cancel": "Отмена", - "never again": "ОК. Больше не показывать", "terminal.integrated.chooseWindowsShell": "Выберите предпочитаемую оболочку терминала. Ее можно позже изменить в параметрах", "terminalService.terminalCloseConfirmationSingular": "Есть активный сеанс терминала, завершить его?", "terminalService.terminalCloseConfirmationPlural": "Есть несколько активных сеансов терминала ({0}), завершить их?" diff --git a/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 54fbd1ada7b..04cb07cdd65 100644 --- a/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileNotModifiedError": "undefined", "fileBinaryError": "Похоже, файл является двоичным, и его нельзя открыть как текстовый." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/rus/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index fd9cd98e381..27106b8b44d 100644 --- a/i18n/rus/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "Сохранить изменения, внесенные в {0}?", "saveChangesMessages": "Сохранить изменения в указанных файлах ({0})?", - "moreFile": "...1 дополнительный файл не показан", - "moreFiles": "...не показано дополнительных файлов: {0}", "saveAll": "&&Сохранить все", "save": "&&Сохранить", "dontSave": "&&Не сохранять", diff --git a/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 9cba5bba5fd..768f28f6eae 100644 --- a/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "No file icons", "iconThemeError": "File icon theme is unknown or not installed.", "workbenchColors": "Переопределяет цвета из выбранной цветовой темы.", - "editorColors": "Переопределяет цвета редактора и стиль шрифта из текущей выбранной цветовой темы.", "editorColors.comments": "Задает цвета и стили для комментариев", "editorColors.strings": "Задает цвета и стили для строковых литералов.", "editorColors.keywords": "Задает цвета и стили для ключевых слов.", @@ -19,5 +18,6 @@ "editorColors.types": "Задает цвета и стили для объявлений типов и ссылок. ", "editorColors.functions": "Задает цвета и стили для объявлений функций и ссылок. ", "editorColors.variables": "Задает цвета и стили для объявлений переменных и для ссылок. ", - "editorColors.textMateRules": "Задает цвета и стили с использованием правил оформления textmate (расширенный параметр)." + "editorColors.textMateRules": "Задает цвета и стили с использованием правил оформления textmate (расширенный параметр).", + "editorColors": "Переопределяет цвета редактора и стиль шрифта из текущей выбранной цветовой темы." } \ No newline at end of file diff --git a/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 019229d3fbb..d4e81ae004d 100644 --- a/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/rus/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Не удается записать файл конфигурации рабочей области. Откройте файл, исправьте ошибки и предупреждения и повторите попытку.", "errorWorkspaceConfigurationFileDirty": "Не удается записать файл конфигурации рабочей области, так как файл был изменен. Сохраните файл и повторите попытку.", "openWorkspaceConfigurationFile": "Открыть файл конфигурации рабочей области", - "close": "Закрыть", - "enterWorkspace.close": "Закрыть", - "enterWorkspace.dontShowAgain": "Больше не показывать", - "enterWorkspace.moreInfo": "Дополнительные сведения", - "enterWorkspace.prompt": "Дополнительные сведения о работе с несколькими папками в VS Code." + "close": "Закрыть" } \ No newline at end of file diff --git a/i18n/trk/extensions/git/out/autofetch.i18n.json b/i18n/trk/extensions/git/out/autofetch.i18n.json index 95a3249f5f4..737e720ea79 100644 --- a/i18n/trk/extensions/git/out/autofetch.i18n.json +++ b/i18n/trk/extensions/git/out/autofetch.i18n.json @@ -5,7 +5,8 @@ // Do not edit this file. It is machine generated. { "yes": "Evet", + "read more": "Devamını oku", "no": "Hayır", - "not now": "Şu An İstemiyorum", - "suggest auto fetch": "Otomatik Git depoları alımını etkinleştirmek ister misiniz?" + "not now": "Daha sonra hatırlat", + "suggest auto fetch": "Code'un düzenli olarak `git fetch` komutunu çalıştırmasını ister misiniz?" } \ No newline at end of file diff --git a/i18n/trk/extensions/git/out/commands.i18n.json b/i18n/trk/extensions/git/out/commands.i18n.json index fac3c95bae7..3e01d946db5 100644 --- a/i18n/trk/extensions/git/out/commands.i18n.json +++ b/i18n/trk/extensions/git/out/commands.i18n.json @@ -41,6 +41,10 @@ "confirm discard all 2": "{0}\n\nBu GERİ DÖNDÜRÜLEMEZ, mevcut çalışma grubunuz TAMAMEN KAYBOLACAK.", "yes discard tracked": "İzlenen 1 Dosyayı Göz Ardı Et", "yes discard tracked multiple": "İzlenen {0} Dosyayı Göz Ardı Et", + "unsaved files single": "Aşağıdaki dosya kaydedilmemiş: {0}.\n\nCommit'lemeden önce kaydetmek ister misiniz?", + "unsaved files": "{0} kaydedilmemiş dosya var.\n\nCommit'lemeden önce kaydetmek ister misiniz?", + "save and commit": "Tümünü Kaydet & Commit'le", + "commit": "Yine de Commit'le", "no staged changes": "Commit'lenecek hazırlanmış değişiklik yok.\n\nTüm değişikliklerinizi otomatik olarak hazırlamak ve direkt olarak commit'lemek ister misiniz?", "always": "Her Zaman", "no changes": "Commit'lenecek değişiklik yok.", @@ -64,11 +68,12 @@ "no remotes to pull": "Deponuzda çekme işleminin yapılacağı hiçbir uzak uçbirim yapılandırılmamış.", "pick remote pull repo": "Dalın çekileceği bir uzak uçbirim seçin", "no remotes to push": "Deponuzda gönderimin yapılacağı hiçbir uzak uçbirim yapılandırılmamış.", - "push with tags success": "Başarılı bir şekilde etiketlerle gönderildi.", "nobranch": "Lütfen uzak uçbirime gönderilecek dala geçiş yapın.", + "confirm publish branch": "'{0}' dalında bir ana depo(upstream) dalı bulunmuyor. Bu dalı yayınlamak ister misiniz?", + "ok": "Tamam", + "push with tags success": "Başarılı bir şekilde etiketlerle gönderildi.", "pick remote": "'{0}' dalının yayınlanacağı bir uzak uçbirim seçin:", "sync is unpredictable": "Bu eylem, '{0}' esas projesine commitleri gönderecek ve alacaktır.", - "ok": "Tamam", "never again": "Tamam, Tekrar Gösterme", "no remotes to publish": "Deponuzda yayınlamanın yapılacağı hiçbir uzak uçbirim yapılandırılmamış.", "no changes stash": "Geçici olarak saklanacak bir değişiklik yok.", diff --git a/i18n/trk/extensions/git/out/main.i18n.json b/i18n/trk/extensions/git/out/main.i18n.json index 34a8658c392..ebd9e4be3fa 100644 --- a/i18n/trk/extensions/git/out/main.i18n.json +++ b/i18n/trk/extensions/git/out/main.i18n.json @@ -7,7 +7,7 @@ "looking": "Git, şu konumda aranıyor: {0}", "using git": "{1} yolundaki git {0} kullanılıyor", "downloadgit": "Git'i İndir", - "neverShowAgain": "Tekrar gösterme", + "neverShowAgain": "Tekrar Gösterme", "notfound": "Git bulunamadı. Git'i kurun veya 'git.path' ayarı ile yapılandırın.", "updateGit": "Git'i Güncelle", "git20": "git {0} yüklemiş olarak görünüyorsunuz. Code, git >= 2 ile en iyi şekilde çalışır" diff --git a/i18n/trk/extensions/git/package.i18n.json b/i18n/trk/extensions/git/package.i18n.json index 3955baf58a0..7e10d7b3dae 100644 --- a/i18n/trk/extensions/git/package.i18n.json +++ b/i18n/trk/extensions/git/package.i18n.json @@ -54,6 +54,7 @@ "command.stashPopLatest": "En Son Geçici Olarak Saklananı Geri Yükle", "config.enabled": "Git'in etkinleştirilip etkinleştirilmediği", "config.path": "Çalıştırılabilir Git dosyasının yolu", + "config.autoRepositoryDetection": "Depoların otomatik olarak algılanıp algılanmayacağı", "config.autorefresh": "Otomatik yenilemenin etkinleştirilip etkinleştirilmediği", "config.autofetch": "Otomatik getirmenin etkinleştirilip etkinleştirilmediği", "config.enableLongCommitWarning": "Uzun commit mesajları hakkında uyarıda bulunulup bulunulmayacağı", @@ -72,5 +73,6 @@ "colors.deleted": "Silinen kaynakların rengi.", "colors.untracked": "İzlenmeyen kaynakların rengi.", "colors.ignored": "Yok sayılan kaynakların rengi.", - "colors.conflict": "Çakışma içeren kaynakların rengi." + "colors.conflict": "Çakışma içeren kaynakların rengi.", + "colors.submodule": "Alt modül kaynaklarının rengi." } \ No newline at end of file diff --git a/i18n/trk/extensions/typescript/out/commands.i18n.json b/i18n/trk/extensions/typescript/out/commands.i18n.json new file mode 100644 index 00000000000..2751d3bb07c --- /dev/null +++ b/i18n/trk/extensions/typescript/out/commands.i18n.json @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "typescript.projectConfigNoWorkspace": "Bir TypeScript veya JavaScript projesini kullanmak için lütfen bir klasör açın", + "typescript.projectConfigUnsupportedFile": "TypeScript mi yoksa JavaScript mi projesi olduğu tespit edilemedi. Desteklenmeyen dosya türü", + "typescript.projectConfigCouldNotGetInfo": "TypeScript mi yoksa JavaScript mi projesi olduğu tespit edilemedi", + "typescript.noTypeScriptProjectConfig": "Dosya bir TypeScript projesinin bir parçası değil", + "typescript.noJavaScriptProjectConfig": "Dosya bir JavaScript projesinin bir parçası değil", + "typescript.configureTsconfigQuickPick": "tsconfig.json'u yapılandır", + "typescript.configureJsconfigQuickPick": "jsconfig.json'u yapılandır", + "typescript.projectConfigLearnMore": "Daha Fazla Bilgi Edin" +} \ No newline at end of file diff --git a/i18n/trk/extensions/typescript/out/features/quickFixProvider.i18n.json b/i18n/trk/extensions/typescript/out/features/quickFixProvider.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/trk/extensions/typescript/out/features/quickFixProvider.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/trk/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json b/i18n/trk/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json new file mode 100644 index 00000000000..ed15423097d --- /dev/null +++ b/i18n/trk/src/vs/base/browser/ui/selectBox/selectBoxCustom.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "selectAriaOption": "{0}" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/base/node/ps.i18n.json b/i18n/trk/src/vs/base/node/ps.i18n.json new file mode 100644 index 00000000000..1ecdfb5a807 --- /dev/null +++ b/i18n/trk/src/vs/base/node/ps.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "collecting": "CPU ve bellek bilgisi toplanıyor. Bu işlem birkaç saniye sürebilir." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json b/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json index 3a5d4006fd7..0987f2e64af 100644 --- a/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json +++ b/i18n/trk/src/vs/editor/common/config/commonEditorConfig.i18n.json @@ -14,7 +14,7 @@ "lineNumbers.on": "Satır numaraları mutlak sayı olarak gösterilir.", "lineNumbers.relative": "Satır numaraları imlecin konumuna olan uzaklık olarak gösterilir.", "lineNumbers.interval": "Satır numaraları her 10 satırda bir gösterilir.", - "lineNumbers": "Satır numaralarının görüntülenmesini denetler. Olası değerler 'on', 'off' ve 'relative'dir.", + "lineNumbers": "Satır numaralarının görüntülenmesini denetler. Olası değerler 'on', 'off', 'relative' ve 'interval'dir.\n", "rulers": "Belirli bir eşit genişlikli karakterlerden sonra dikey cetveller göster. Birden çok cetvel için birden çok değer kullanın. Dizi boş ise cetvel gösterilmez", "wordSeparators": "Sözcüklerle ilgili gezinti veya işlem yaparken kelime ayırıcı olarak kullanılacak karakterler", "tabSize": "Bir sekmenin eşit olduğu boşluk sayısı. Bu ayar, `editor.detectIndentation` açıkken dosya içeriğine bağlı olarak geçersiz kılınır.", @@ -40,9 +40,9 @@ "wordWrapColumn": "`editor.wordWrap` ögesi, 'wordWrapColumn' veya 'bounded' iken düzenleyicinin kaydırma sütununu denetler.", "wrappingIndent": "Kaydırılan satır girintisini denetler. 'none', 'same' veya 'indent' değerlerinden biri olabilir.", "mouseWheelScrollSensitivity": "Fare tekerleği kaydırma olaylarında `deltaX` ve `deltaY` üzerinde kullanılan bir çarpan", - "multiCursorModifier.ctrlCmd": "Windows ve Linux'da `Control` ve OSX'de `Command` ile eşleşir.", - "multiCursorModifier.alt": "Windows ve Linux'da `Alt` ve OSX'de `Option` ile eşleşir.", - "multiCursorModifier": "Fare ile birden çok imleç eklenmesinde kullanılacak değiştirici. `ctrlCmd` Windows ve Linux'da `Control` ve OSX'de `Command` ile eşleşir. Tanıma Git ve Bağlantıyı Aç fare hareketleri, birden çok imleç değiştiricisi ile çakışmayacak şekilde uyum sağlarlar.", + "multiCursorModifier.ctrlCmd": "Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir.", + "multiCursorModifier.alt": "Windows ve Linux'da `Alt` ve macOS'de `Option` ile eşleşir.", + "multiCursorModifier": "Fare ile birden çok imleç eklenmesinde kullanılacak değiştirici. `ctrlCmd` Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir. Tanıma Git ve Bağlantıyı Aç fare hareketleri, birden çok imleç değiştiricisi ile çakışmayacak şekilde uyum sağlarlar.", "quickSuggestions.strings": "Dizelerin içinde hızlı önerileri etkinleştir.", "quickSuggestions.comments": "Yorumların içinde hızlı önerileri etkinleştir.", "quickSuggestions.other": "Dizeler ve yorumlar dışında hızlı önerileri etkinleştirin.", diff --git a/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json b/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json index 6022a86b6cc..8fb29c3b6d6 100644 --- a/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json +++ b/i18n/trk/src/vs/editor/common/view/editorColorRegistry.i18n.json @@ -6,7 +6,6 @@ { "lineHighlight": "İmlecin bulunduğu satırın vurgusunun arka plan rengi.", "lineHighlightBorderBox": "İmlecin bulunduğu satırın kenarlığının arka plan rengi.", - "rangeHighlight": "Hızlı açma ve bulma özellikleri gibi vurgulanan alanların arka plan rengi.", "caret": "Düzenleyici imlecinin rengi.", "editorCursorBackground": "Düzenleyici imlecinin arka plan rengi. Bir blok imlecinin kapladığı bir karakterin rengini özelleştirmeyi sağlar.", "editorWhitespaces": "Düzenleyicideki boşluk karakterlerinin rengi.", diff --git a/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json b/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json index 6bc3935d6f4..47acac3ba2a 100644 --- a/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/gotoError/gotoError.i18n.json @@ -5,8 +5,8 @@ // Do not edit this file. It is machine generated. { "title.wo_source": "({0}/{1})", - "markerAction.next.label": "Sonraki Hata veya Uyarıya Git", - "markerAction.previous.label": "Önceki Hata veya Uyarıya Git", + "markerAction.next.label": "Sonraki Soruna Git (Hata, Uyarı, Bilgi)", + "markerAction.previous.label": "Önceki Soruna Git (Hata, Uyarı, Bilgi)", "editorMarkerNavigationError": "Düzenleyicinin işaretçi gezinti aracının hata rengi.", "editorMarkerNavigationWarning": "Düzenleyicinin işaretçi gezinti aracının uyarı rengi.", "editorMarkerNavigationInfo": "Düzenleyicinin işaretçi gezinti aracının bilgilendirme rengi.", diff --git a/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json b/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json index 6faf663326d..f6e38f50e99 100644 --- a/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json +++ b/i18n/trk/src/vs/editor/contrib/wordHighlighter/wordHighlighter.i18n.json @@ -4,8 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "wordHighlight": "Bir değişkeni okumak gibi, okuma-erişimi sırasındaki bir sembolün arka plan rengi.", - "wordHighlightStrong": "Bir değişkene yazmak gibi, yazma-erişimi sırasındaki bir sembolün arka plan rengi.", "overviewRulerWordHighlightForeground": "Sembol vurguları için genel bakış cetvelinin işaretleyici rengi.", "overviewRulerWordHighlightStrongForeground": "Yazma erişimli sembol vurguları için genel bakış cetvelinin işaretleyici rengi.", "wordHighlight.next.label": "Sonraki Sembol Vurgusuna Git", diff --git a/i18n/trk/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json b/i18n/trk/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json index 5ddafd4b6b9..5565278f23e 100644 --- a/i18n/trk/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json +++ b/i18n/trk/src/vs/platform/actions/electron-browser/menusExtensionPoint.i18n.json @@ -40,6 +40,5 @@ "menuId.invalid": "`{0}` geçerli bir menü tanımlayıcısı değil", "missing.command": "Menü ögesi, 'commands' bölümünde tanımlanmamış bir `{0}` komutuna başvuruyor.", "missing.altCommand": "Menü ögesi, 'commands' bölümünde tanımlanmamış bir `{0}` alternatif komutuna başvuruyor.", - "dupe.command": "Menü ögesi, aynı varsayılan ve alternatif komutlarına başvuruyor", - "nosupport.altCommand": "Üzgünüz, fakat sadece 'editor/title' menüsünün 'navigation' grubu alternatif komutları destekliyor" + "dupe.command": "Menü ögesi, aynı varsayılan ve alternatif komutlarına başvuruyor" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/environment/node/argv.i18n.json b/i18n/trk/src/vs/platform/environment/node/argv.i18n.json index a4c4cd296d5..c0a53eb4448 100644 --- a/i18n/trk/src/vs/platform/environment/node/argv.i18n.json +++ b/i18n/trk/src/vs/platform/environment/node/argv.i18n.json @@ -8,30 +8,35 @@ "diff": "İki dosyayı birbiriyle karşılaştır.", "add": "Son aktif pencereye klasör(ler) ekle.", "goto": "Konumdaki bir dosyayı belirtilen satır ve sütunda aç.", - "locale": "Kullanılacak yerel dil (örnek: en-US veya zh-TW).", "newWindow": "Yeni bir Code örneğini zorla.", - "performance": "'Geliştirici: Başlangıç Performansı' komutu etkinleştirilmiş olarak başlat.", - "prof-startup": "Başlangıç sırasında CPU profil oluşturucusunu çalıştır", - "inspect-extensions": "Eklentilerde hata ayıklama ve ayrımlamaya izin ver. Bağlantı URI'ı için geliştirici araçlarını kontrol edin.", - "inspect-brk-extensions": "Eklentilerde hata ayıklama ve ayrımlamaya eklenti sunucusu başladıktan hemen sonra duraklatılacak şekilde izin ver. Bağlantı URI'ı için geliştirici araçlarını kontrol edin.", "reuseWindow": "Bir dosya veya klasörü son etkin pencerede açmaya zorlayın.", - "userDataDir": "Kullanıcı verilerinin tutulacağı klasörü belirtir, root olarak çalışırken yararlıdır.", - "log": "Kullanılacak günlüğe yazma düzeyi. Varsayılan değer 'info'dur. İzin verilen değerler 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off' şeklindedir.", - "verbose": "Ayrıntılı çıktı oluştur (--wait anlamına gelir).", "wait": "Geri dönmeden önce dosyaların kapanmasını bekle.", + "locale": "Kullanılacak yerel dil (örnek: en-US veya zh-TW).", + "userDataDir": "Kullanıcı verilerinin tutulacağı klasörü belirtir, root olarak çalışırken yararlıdır.", + "version": "Sürümü göster.", + "help": "Kullanımı göster.", "extensionHomePath": "Eklentilerin kök dizinini belirle.", "listExtensions": "Yüklü eklentileri listele.", "showVersions": "--list-extensions'u kullanırken, yüklü eklentilerin sürümlerini gösterir.", "installExtension": "Bir eklenti yükler.", "uninstallExtension": "Bir eklentiyi kaldırır.", "experimentalApis": "Bir eklenti için önerilen API özelliklerini etkinleştirir.", - "disableExtensions": "Yüklü tüm eklentileri devre dışı bırak.", - "disableGPU": "GPU donanım hızlandırmasını devre dışı bırak.", + "verbose": "Ayrıntılı çıktı oluştur (--wait anlamına gelir).", + "log": "Kullanılacak günlüğe yazma düzeyi. Varsayılan değer 'info'dur. İzin verilen değerler 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off' şeklindedir.", "status": "İşlem kullanımını ve tanılama bilgilerini yazdır.", - "version": "Sürümü göster.", - "help": "Kullanımı göster.", + "performance": "'Geliştirici: Başlangıç Performansı' komutu etkinleştirilmiş olarak başlat.", + "prof-startup": "Başlangıç sırasında CPU profil oluşturucusunu çalıştır", + "disableExtensions": "Yüklü tüm eklentileri devre dışı bırak.", + "inspect-extensions": "Eklentilerde hata ayıklama ve ayrımlamaya izin ver. Bağlantı URI'ı için geliştirici araçlarını kontrol edin.", + "inspect-brk-extensions": "Eklentilerde hata ayıklama ve ayrımlamaya eklenti sunucusu başladıktan hemen sonra duraklatılacak şekilde izin ver. Bağlantı URI'ı için geliştirici araçlarını kontrol edin.", + "disableGPU": "GPU donanım hızlandırmasını devre dışı bırak.", + "issue": "Sorun bildirin.", "usage": "Kullanım", "options": "seçenekler", "paths": "yollar", - "optionsUpperCase": "Seçenekler" + "stdinWindows": "Başka bir programın çıktısını okumak için '-' karakterini ekleyin. (ör. 'echo Hello World | {0} -')", + "stdinUnix": "stdin'den okutmak için '-' karakterini ekleyin (ör. 'ps aux | grep code | {0} -')", + "optionsUpperCase": "Seçenekler", + "extensionsManagement": "Eklenti Yönetimi", + "troubleshooting": "Sorun giderme" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json b/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json index 7cf70b2f373..79f9fd64611 100644 --- a/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json +++ b/i18n/trk/src/vs/platform/extensionManagement/node/extensionManagementService.i18n.json @@ -5,14 +5,15 @@ // Do not edit this file. It is machine generated. { "invalidManifest": "Eklenti geçersiz: package.json bir JSON dosyası değil.", - "restartCodeLocal": "{0} eklentisini yeniden yüklemeden önce lütfen Code'u yeniden başlatın.", + "restartCode": "{0} eklentisini yeniden yüklemeden önce lütfen Code'u yeniden başlatın.", "installingOutdatedExtension": "Bu eklentinin daha yeni bir sürümü zaten yüklü. Bunu, daha eski bir sürümle geçersiz kılmak ister misiniz?", "override": "Geçersiz Kıl", "cancel": "İptal", - "notFoundCompatible": "Yükleme başarısız oldu çünkü, '{0}' eklentisinin uyumlu olduğu VS Code'un '{1}' sürümü bulunamadı.", - "quitCode": "Yükleme başarısız oldu çünkü, eklentinin eski bir örneği hâlâ çalışıyor. Yeniden yüklemeden önce lütfen VS Code'dan çıkın ve tekrar açın.", - "exitCode": "Yükleme başarısız oldu çünkü, eklentinin eski bir örneği hâlâ çalışıyor. Yeniden yüklemeden önce lütfen VS Code'dan çıkın ve tekrar açın.", + "errorInstallingDependencies": "Bağımlılıklar yüklenirken hata oluştu. {0}", + "notFoundCompatible": "'{0}' yüklenemiyor; VS Code '{1}' ile uyumlu mevcut bir sürümü yok.", "notFoundCompatibleDependency": "Yükleme başarısız oldu çünkü, bağımlılığı bulunan '{0}' eklentisinin uyumlu olduğu VS Code'un '{1}' sürümü bulunamadı.", + "quitCode": "Eklenti yüklenemedi. Lütfen yeniden yüklemeden önce VS Code'u sonlandırın ve tekrar başlatın.", + "exitCode": "Eklenti yüklenemedi. Lütfen yeniden yüklemeden önce VS Code'u sonlandırın ve tekrar başlatın.", "uninstallDependeciesConfirmation": "Yalnızca '{0}' eklentisini mi yoksa bağımlılıklarını da kaldırmak ister misiniz?", "uninstallOnly": "Sadece Eklenti", "uninstallAll": "Tümü", diff --git a/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json b/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json index 8d0fe384379..a5e03c83816 100644 --- a/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json +++ b/i18n/trk/src/vs/platform/integrity/node/integrityServiceImpl.i18n.json @@ -5,7 +5,7 @@ // Do not edit this file. It is machine generated. { "integrity.ok": "Tamam", - "integrity.dontShowAgain": "Tekrar gösterme", + "integrity.dontShowAgain": "Tekrar Gösterme", "integrity.moreInfo": "Daha fazla bilgi", "integrity.prompt": "{0} kurulumunuz bozuk görünüyor. Lütfen yeniden yükleyin." } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/list/browser/listService.i18n.json b/i18n/trk/src/vs/platform/list/browser/listService.i18n.json new file mode 100644 index 00000000000..9f083e8ed4a --- /dev/null +++ b/i18n/trk/src/vs/platform/list/browser/listService.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Çalışma Ekranı", + "multiSelectModifier.ctrlCmd": "Windows ve Linux'da `Control` ve macOS'de `Command` ile eşleşir.", + "multiSelectModifier.alt": "Windows ve Linux'da `Alt` ve macOS'de `Option` ile eşleşir." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/message/common/message.i18n.json b/i18n/trk/src/vs/platform/message/common/message.i18n.json index 4f9a44f9383..3d5ccdec1e6 100644 --- a/i18n/trk/src/vs/platform/message/common/message.i18n.json +++ b/i18n/trk/src/vs/platform/message/common/message.i18n.json @@ -6,5 +6,7 @@ { "close": "Kapat", "later": "Daha Sonra", - "cancel": "İptal" + "cancel": "İptal", + "moreFile": "...1 ek dosya gösterilmiyor", + "moreFiles": "...{0} ek dosya gösterilmiyor" } \ No newline at end of file diff --git a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json index d6e0e3db142..f57a875d1db 100644 --- a/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json +++ b/i18n/trk/src/vs/platform/theme/common/colorRegistry.i18n.json @@ -63,12 +63,7 @@ "editorWidgetBorder": "Editör araçlarının kenarlık rengi. Renk, araç bir kenarlığı olmasına karar verdiğinde ve renk hiçbir eklenti tarafından geçersiz kılınmadığında kullanılır.", "editorSelectionBackground": "Düzenleyici seçiminin rengi.", "editorSelectionForeground": "Yüksek karşıtlık için seçilen metnin rengi.", - "editorInactiveSelection": "Bir pasif düzenleyicideki seçimin rengi.", - "editorSelectionHighlight": "Seçimle aynı içeriğe sahip bölgelerin rengi.", "editorFindMatch": "Geçerli arama eşleşmesinin rengi.", - "findMatchHighlight": "Diğer arama eşleşmelerinin rengi.", - "findRangeHighlight": "Aramayı sınırlayan aralığı renklendirin.", - "hoverHighlight": "Bağlantı vurgusu gösterilen bir sözcüğün altını vurgulayın.", "hoverBackground": "Düzenleyici bağlantı vurgusunun arka plan rengi.", "hoverBorder": "Düzenleyici bağlantı vurgusunun kenarlık rengi.", "activeLinkForeground": "Aktif bağlantıların rengi.", @@ -76,12 +71,6 @@ "diffEditorRemoved": "Çıkarılan metnin arka plan rengi.", "diffEditorInsertedOutline": "Eklenen metnin ana hat rengi.", "diffEditorRemovedOutline": "Çıkarılan metnin ana hat rengi.", - "mergeCurrentHeaderBackground": "Satır içi birleştirme çakışmalarında geçerli üstbilgi arka planı.", - "mergeCurrentContentBackground": "Satır içi birleştirme çakışmalarında geçerli içerik arka planı.", - "mergeIncomingHeaderBackground": "Satır içi birleştirme çakışmalarında gelen üstbilgi arka planı.", - "mergeIncomingContentBackground": "Satır içi birleştirme çakışmalarında gelen içerik arka planı.", - "mergeCommonHeaderBackground": "Satır içi birleştirme çakışmalarında ortak ata üstbilgisi arka planı.", - "mergeCommonContentBackground": "Satır içi birleştirme çakışmalarında ortak ata içeriği arka planı.", "mergeBorder": "Satır içi birleştirme çakışmalarında üst bilgi ve ayırıcıdaki kenarlık rengi.", "overviewRulerCurrentContentForeground": "Satır içi birleştirme çakışmalarında geçerli genel bakış cetveli ön planı.", "overviewRulerIncomingContentForeground": "Satır içi birleştirme çakışmalarında gelen genel bakış cetveli ön planı.", diff --git a/i18n/trk/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json b/i18n/trk/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json new file mode 100644 index 00000000000..0ca04fc5f49 --- /dev/null +++ b/i18n/trk/src/vs/workbench/api/browser/localizationsExtensionPoint.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "requirestring": "`{0}` özelliği zorunludur ve `string` türünde olmalıdır", + "optstring": "`{0}` özelliği atlanabilir veya `string` türünde olmalıdır" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json new file mode 100644 index 00000000000..94c6abc9b61 --- /dev/null +++ b/i18n/trk/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "saveParticipants": "Katılımcıların Kaydedilmesi İşlemi Çalıştırılıyor..." +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json b/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json index a3dd0ab5f95..737337540bf 100644 --- a/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json +++ b/i18n/trk/src/vs/workbench/api/node/extHostTreeViews.i18n.json @@ -4,7 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "treeView.notRegistered": "Kayıtlı '{0}' Id'li ağaç görünümü yok.", - "treeItem.notFound": "'{0}' Id'li ağaç ögesi yok.", - "treeView.duplicateElement": "{0} ögesi zaten kayıtlı" + "treeView.notRegistered": "Kayıtlı '{0}' Id'li ağaç görünümü yok." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json b/i18n/trk/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json index b5c1cbc783e..1658e6a34d6 100644 --- a/i18n/trk/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/actions/toggleSidebarPosition.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "toggleLocation": "Kenar Çubuğu Konumunu Değiştir", "view": "Görüntüle" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json b/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json index a8ba8956df1..43558a9d00d 100644 --- a/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/actions/workspaceActions.i18n.json @@ -7,17 +7,11 @@ "openFile": "Dosya Aç...", "openFolder": "Klasör Aç...", "openFileFolder": "Aç...", - "addFolderToWorkspace": "Çalışma Alanına Klasör Ekle...", - "add": "&&Ekle", - "addFolderToWorkspaceTitle": "Çalışma Alanına Klasör Ekle", "globalRemoveFolderFromWorkspace": "Çalışma Alanından Klasör Kaldır...", - "removeFolderFromWorkspace": "Çalışma Alanından Klasör Kaldır", - "openFolderSettings": "Klasör Ayarlarını Aç", "saveWorkspaceAsAction": "Çalışma Alanını Farklı Kaydet...", "save": "&&Kaydet", "saveWorkspace": "Çalışma Alanını Kaydet", "openWorkspaceAction": "Çalışma Alanı Aç...", "openWorkspaceConfigFile": "Çalışma Alanı Yapılandırma Dosyasını Aç", - "openFolderAsWorkspaceInNewWindow": "Klasörü Yeni Pencerede Çalışma Alanı Olarak Aç", - "workspaceFolderPickerPlaceholder": "Çalışma alanı klasörü seçin" + "openFolderAsWorkspaceInNewWindow": "Klasörü Yeni Pencerede Çalışma Alanı Olarak Aç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/actions/workspaceCommands.i18n.json b/i18n/trk/src/vs/workbench/browser/actions/workspaceCommands.i18n.json new file mode 100644 index 00000000000..1b71f510ec6 --- /dev/null +++ b/i18n/trk/src/vs/workbench/browser/actions/workspaceCommands.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "addFolderToWorkspace": "Çalışma Alanına Klasör Ekle...", + "add": "&&Ekle", + "addFolderToWorkspaceTitle": "Çalışma Alanına Klasör Ekle", + "workspaceFolderPickerPlaceholder": "Çalışma alanı klasörü seçin" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json index 5ff77e04882..4ee34bebb2d 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editor.contribution.i18n.json @@ -13,5 +13,17 @@ "groupThreePicker": "Üçüncü Gruptaki Düzenleyicileri Göster", "allEditorsPicker": "Açık Tüm Düzenleyicileri Göster", "view": "Görüntüle", - "file": "Dosya" + "file": "Dosya", + "close": "Kapat", + "closeOthers": "Diğerlerini Kapat", + "closeRight": "Sağdakileri Kapat", + "closeAllUnmodified": "Değiştirilmeyenleri Kapat", + "closeAll": "Tümünü Kapat", + "keepOpen": "Açık Tut", + "showOpenedEditors": "Açık Düzenleyicileri Göster", + "keepEditor": "Düzenleyiciyi Tut", + "closeEditorsInGroup": "Gruptaki Tüm Düzenleyicileri Kapat", + "closeUnmodifiedEditors": "Gruptaki Değiştirilmemiş Düzenleyicileri Kapat", + "closeOtherEditors": "Diğer Düzenleyicileri Kapat", + "closeRightEditors": "Düzenleyicinin Sağındakileri Kapat" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json index b32e97503d9..3264a4ed56e 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editorActions.i18n.json @@ -17,18 +17,13 @@ "closeEditor": "Düzenleyiciyi Kapat", "revertAndCloseActiveEditor": "Geri Al ve Düzenleyiciyi Kapat", "closeEditorsToTheLeft": "Düzenleyicinin Solundakileri Kapat", - "closeEditorsToTheRight": "Düzenleyicinin Sağındakileri Kapat", "closeAllEditors": "Tüm Düzenleyicileri Kapat", - "closeUnmodifiedEditors": "Gruptaki Değiştirilmemiş Düzenleyicileri Kapat", "closeEditorsInOtherGroups": "Diğer Gruplardaki Tüm Düzenleyicileri Kapat", - "closeOtherEditorsInGroup": "Diğer Düzenleyicileri Kapat", - "closeEditorsInGroup": "Gruptaki Tüm Düzenleyicileri Kapat", "moveActiveGroupLeft": "Düzenleyici Grubunu Sola Taşı", "moveActiveGroupRight": "Düzenleyici Grubunu Sağa Taşı", "minimizeOtherEditorGroups": "Diğer Düzenleyici Gruplarını Küçült", "evenEditorGroups": "Düzenleyici Grup Genişliklerini Eşitle", "maximizeEditor": "Düzenleyici Grubunu Olabildiğince Genişlet ve Kenar Çubuğunu Gizle", - "keepEditor": "Düzenleyiciyi Tut", "openNextEditor": "Sonraki Düzenleyiciyi Aç", "openPreviousEditor": "Önceki Düzenleyiciyi Aç", "nextEditorInGroup": "Gruptaki Sonraki Düzenleyiciyi Aç", @@ -42,7 +37,6 @@ "showEditorsInFirstGroup": "İlk Gruptaki Düzenleyicileri Göster", "showEditorsInSecondGroup": "İkinci Gruptaki Düzenleyicileri Göster", "showEditorsInThirdGroup": "Üçüncü Gruptaki Düzenleyicileri Göster", - "showEditorsInGroup": "Gruptaki Düzenleyicileri Göster", "showAllEditors": "Tüm Düzenleyicileri Göster", "openPreviousRecentlyUsedEditorInGroup": "Gruptaki Son Kullanılan Önceki Düzenleyiciyi Aç", "openNextRecentlyUsedEditorInGroup": "Gruptaki Son Kullanılan Sonraki Düzenleyiciyi Aç", @@ -54,5 +48,8 @@ "moveEditorLeft": "Düzenleyiciyi Sola Taşı", "moveEditorRight": "Düzenleyiciyi Sağa Taşı", "moveEditorToPreviousGroup": "Düzenleyiciyi Önceki Gruba Taşı", - "moveEditorToNextGroup": "Düzenleyiciyi Sonraki Gruba Taşı" + "moveEditorToNextGroup": "Düzenleyiciyi Sonraki Gruba Taşı", + "moveEditorToFirstGroup": "Düzenleyiciyi İlk Gruba Taşı", + "moveEditorToSecondGroup": "Düzenleyiciyi İkinci Gruba Taşı", + "moveEditorToThirdGroup": "Düzenleyiciyi Üçüncü Gruba Taşı" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json index 4eac419d706..0f560d95c00 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/editorCommands.i18n.json @@ -6,7 +6,5 @@ { "editorCommand.activeEditorMove.description": "Aktif düzenleyiciyi sekmeler veya gruplar halinde taşıyın", "editorCommand.activeEditorMove.arg.name": "Aktif düzenleyici taşıma argümanı", - "editorCommand.activeEditorMove.arg.description": "Argüman Özellikleri:\n\t* 'to': Nereye taşınacağını belirten dize değeri.\n\t* 'by': Kaç birim taşınacağını belirten dize değeri. Sekme veya gruba göre.\n\t* 'value': Kaç tane pozisyonun taşınacağını belirten sayı değeri.", - "commandDeprecated": "**{0}** komutu kaldırıldı. Onun yerine **{1}** komutunu kullanabilirsiniz", - "openKeybindings": "Klavye Kısayollarını Yapılandır" + "editorCommand.activeEditorMove.arg.description": "Argüman Özellikleri:\n\t* 'to': Nereye taşınacağını belirten dize değeri.\n\t* 'by': Kaç birim taşınacağını belirten dize değeri. Sekme veya gruba göre.\n\t* 'value': Kaç tane pozisyonun taşınacağını belirten sayı değeri." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json index 9fb7a026e34..e73c3315e6d 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/textDiffEditor.i18n.json @@ -11,6 +11,5 @@ "editableEditorAriaLabel": "Metin dosyası karşılaştırma düzenleyicisi.", "navigate.next.label": "Sonraki Değişiklik", "navigate.prev.label": "Önceki Değişiklik", - "inlineDiffLabel": "Satır İçi Görünüme Geç", - "sideBySideDiffLabel": "Yan Yana Görünüme Geç" + "toggleIgnoreTrimWhitespace.label": "Kırpma Boşluğunu Yoksay" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json index 18e318decfd..d62c167e7b6 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/editor/titleControl.i18n.json @@ -5,11 +5,5 @@ // Do not edit this file. It is machine generated. { "close": "Kapat", - "closeOthers": "Diğerlerini Kapat", - "closeRight": "Sağdakileri Kapat", - "closeAll": "Tümünü Kapat", - "closeAllUnmodified": "Değiştirilmeyenleri Kapat", - "keepOpen": "Açık Tut", - "showOpenedEditors": "Açık Düzenleyicileri Göster", "araLabelEditorActions": "Düzenleyici eylemleri" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json index f143e04de94..1b5f24a5398 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/titlebar/titlebarPart.i18n.json @@ -5,5 +5,7 @@ // Do not edit this file. It is machine generated. { "patchedWindowTitle": "[Desteklenmiyor]", + "userIsAdmin": "[Yönetici]", + "userIsSudo": "[Süper Kullanıcı]", "devExtensionWindowTitlePrefix": "[Eklenti Geliştirme Sunucusu]" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json b/i18n/trk/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json index d61355ad2f9..8b6ad71cd4e 100644 --- a/i18n/trk/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json +++ b/i18n/trk/src/vs/workbench/browser/parts/views/viewsViewlet.i18n.json @@ -3,6 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. -{ - "hideView": "Kenar Çubuğunda Gizle" -} \ No newline at end of file +{} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/common/theme.i18n.json b/i18n/trk/src/vs/workbench/common/theme.i18n.json index 9eb9ad116a5..02c2f8fa5d6 100644 --- a/i18n/trk/src/vs/workbench/common/theme.i18n.json +++ b/i18n/trk/src/vs/workbench/common/theme.i18n.json @@ -6,9 +6,13 @@ { "tabActiveBackground": "Aktif sekme arka plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabInactiveBackground": "Pasif sekme arka plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", + "tabHoverBackground": "Fareyle üzerine gelindiğinde sekme arka plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", + "tabUnfocusedHoverBackground": "Fareyle üzerine gelindiğinde odaklanılmamış bir gruptaki aktif sekmenin arka plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabBorder": "Sekmeleri birbirinden ayıran kenarlığın rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabActiveBorder": "Aktif sekmeleri vurgulayacak kenarlık. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabActiveUnfocusedBorder": "Odaklanılmamış bir gruptaki aktif sekmeleri vurgulayacak kenarlık. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", + "tabHoverBorder": "Fareyle üzerine gelindiğinde sekmeleri vurgulayacak kenarlık. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", + "tabUnfocusedHoverBorder": "Fareyle üzerine gelindiğinde odaklanılmamış bir gruptaki sekmeleri vurgulayacak kenarlık. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabActiveForeground": "Aktif bir gruptaki aktif sekmenin ön plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabInactiveForeground": "Aktif bir gruptaki pasif sekmenin ön plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", "tabUnfocusedActiveForeground": "Odaklanılmamış bir gruptaki aktif sekmenin ön plan rengi. Sekmeler, düzenleyici alanındaki düzenleyicilerin kapsayıcılarıdır. Bir düzenleyici grubunda birden fazla sekme açılabilir. Birden fazla düzenleyici grupları var olabilir.", @@ -16,7 +20,7 @@ "editorGroupBackground": "Bir düzenleyici grubunun arka plan rengi. Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. Arka plan rengi, düzenleyici grubunu sürüklerken gösterilir.", "tabsContainerBackground": "Sekmeler etkinleştirilmiş durumdayken, düzenleyici grubu başlık üstbilgisi arka plan rengi. Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. ", "tabsContainerBorder": "Sekmeler etkinleştirilmiş durumdayken, düzenleyici grubu başlık üstbilgisi kenarlık rengi. Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. ", - "editorGroupHeaderBackground": "Sekmeler devre dışı iken, düzenleyici grubu başlık üstbilgisi arka plan rengi. Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. ", + "editorGroupHeaderBackground": "Sekmeler devre dışı iken, düzenleyici grubu başlık üstbilgisi arka plan rengi (`\"workbench.editor.showTabs\": false`). Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. ", "editorGroupBorder": "Birden fazla düzenleyici grubunu birbirinden ayıracak renk. Düzenleyici grupları, düzenleyicilerin kapsayıcılarıdır. ", "editorDragAndDropBackground": "Düzenleyici grubunu sürüklerken gösterilecek arka plan rengi. Düzenleyici içeriğinin hâlâ iyi görünmeye devam edebilmesi için renk şeffaf olmalıdır.", "panelBackground": "Panel arka plan rengi. Paneller düzenleyici alanının altında gösterilir ve çıktı ve entegre terminal gibi görünümler içerir.", @@ -33,8 +37,8 @@ "statusBarNoFolderBorder": "Hiçbir klasör açık olmadığında durum çubuğunu kenar çubuğundan ve düzenleyiciden ayıran kenarlık rengi. Durum çubuğu, pencerenin alt kısmında gösterilir.", "statusBarItemActiveBackground": "Durum çubuğu ögesi tıklanırken arka plan rengi. Durum çubuğu, pencerenin alt kısmında gösterilir.", "statusBarItemHoverBackground": "Durum çubuğu ögesinin mouse ile üzerine gelindiğindeki arka plan rengi. Durum çubuğu, pencerenin alt kısmında gösterilir.", - "statusBarProminentItemBackground": "Durum çubuğu belirgin ögelerinin arka plan rengi. Belirgin ögeler, önemi belirtmek için diğer durum çubuğu girdilerinden öne çıkarılır. Durum çubuğu, pencerenin alt kısmında gösterilir.", - "statusBarProminentItemHoverBackground": "Durum çubuğu belirgin ögelerinin mouse ile üzerine gelindiğindeki arka plan rengi. Belirgin ögeler, önemi belirtmek için diğer durum çubuğu girdilerinden öne çıkarılır. Durum çubuğu, pencerenin alt kısmında gösterilir.", + "statusBarProminentItemBackground": "Durum çubuğu belirgin ögelerinin arka plan rengi. Belirgin ögeler, önemi belirtmek için diğer durum çubuğu girdilerinden öne çıkarılır. Bir örnek görmek için komut paletinden `Tab Tuşu İle Odak Değiştirmeyi Aç/Kapat` ile modu değiştirin. Durum çubuğu, pencerenin alt kısmında gösterilir.", + "statusBarProminentItemHoverBackground": "Fareyle üzerine gelindiğinde durum çubuğu belirgin ögelerinin arka plan rengi. Belirgin ögeler, önemi belirtmek için diğer durum çubuğu girdilerinden öne çıkarılır. Bir örnek görmek için komut paletinden `Tab Tuşu İle Odak Değiştirmeyi Aç/Kapat` ile modu değiştirin. Durum çubuğu, pencerenin alt kısmında gösterilir.", "activityBarBackground": "Etkinlik çubuğu arka plan rengi. Etkinlik çubuğu, en sol veya en sağda gösterilir ve kenar çubuğunun görünümleriyle yer değiştirmeye izin verir.", "activityBarForeground": "Etkinlik çubuğu ön plan rengi (ör. simgeler için kullanılır). Etkinlik çubuğu, en sol veya en sağda gösterilir ve kenar çubuğunun görünümleriyle yer değiştirmeye izin verir.", "activityBarBorder": "Etkinlik çubuğunu kenar çubuğundan ayıran kenarlığın rengi. Etkinlik çubuğu, en sol veya en sağda gösterilir ve kenar çubuğunun görünümleriyle yer değiştirmeye izin verir.", diff --git a/i18n/trk/src/vs/workbench/common/views.i18n.json b/i18n/trk/src/vs/workbench/common/views.i18n.json new file mode 100644 index 00000000000..d412455fd99 --- /dev/null +++ b/i18n/trk/src/vs/workbench/common/views.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "duplicateId": "`{0}` kimliğine sahip bir görünüm `{1}` konumunda zaten kayıtlı" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json index e3e29379b77..5cb1f86f054 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/actions.i18n.json @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "closeActiveEditor": "Düzenleyiciyi Kapat", "closeWindow": "Pencereyi Kapat", "closeWorkspace": "Çalışma Alanını Kapat", "noWorkspaceOpened": "Şu an bu örnekte kapatmak için açık bir çalışma alanı bulunmuyor.", @@ -52,21 +51,5 @@ "displayLanguage": "VSCode'un görüntüleme dilini tanımlar.", "doc": "Desteklenen dillerin listesi için göz atın: {0}", "restart": "Değeri değiştirirseniz VSCode'u yeniden başlatmanız gerekir.", - "fail.createSettings": " '{0}' oluşturulamadı ({1}).", - "openLogsFolder": "Günlük Klasörünü Aç", - "showLogs": "Günlükleri Göster...", - "mainProcess": "Ana", - "sharedProcess": "Paylaşılan", - "rendererProcess": "Render Alan", - "extensionHost": "Eklenti Sunucusu", - "selectProcess": "İşlem seçin", - "setLogLevel": "Günlük Düzeyini Ayarla", - "trace": "İzle", - "debug": "Hata Ayıklama", - "info": "Bilgi", - "warn": "Uyarı", - "err": "Hata", - "critical": "Kritik", - "off": "Kapalı", - "selectLogLevel": "Günlük düzeyini seçin" + "fail.createSettings": " '{0}' oluşturulamadı ({1})." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json index 8aacc6f4f6e..b66debcf9ce 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/main.contribution.i18n.json @@ -7,8 +7,9 @@ "view": "Görüntüle", "help": "Yardım", "file": "Dosya", - "developer": "Geliştirici", "workspaces": "Çalışma Alanları", + "developer": "Geliştirici", + "workbenchConfigurationTitle": "Çalışma Ekranı", "showEditorTabs": "Açık düzenleyicilerin sekmelerde gösterilip gösterilmeyeceğini denetler", "workbench.editor.labelFormat.default": "Dosyanın adını göster. Sekmeler etkinleştirilmiş ve bir grupta iki dosya aynı ada sahiplerse, her dosyanın yolundaki ayırt edici bölümler eklenir. Sekmeler devre dışı ve düzenleyici aktifse, çalışma alanı klasörüne göreli yol gösterilir.", "workbench.editor.labelFormat.short": "Dosyanın adını ve ardından dizin adını göster.", @@ -20,23 +21,23 @@ "showIcons": "Açık düzenleyicilerin bir simge ile gösterilip gösterilmemelerini denetler. Bu, bir simge temasının etkinleştirilmesini de gerektirir.", "enablePreview": "Açık düzenleyicilerin önizleme olarak gösterilip gösterilmeyeceğini denetler. Önizleme düzenleyicileri kalıcı olarak açılana kadar (ör. çift tıklama veya düzenleme ile) tekrar kullanılırlar ve italik yazı tipiyle gösterilirler.", "enablePreviewFromQuickOpen": "Hızlı Aç'taki açık düzenleyicilerin önizleme olarak gösterilip gösterilmeyeceğini denetler. Önizleme düzenleyicileri kalıcı olarak açılana kadar (ör. çift tıklama veya düzenleme ile) tekrar kullanılırlar.", + "closeOnFileDelete": "Düzenleyicinin gösterdiği bir dosyanın, başka bir işlem tarafından silinmesi veya yeniden adlandırması durumunda dosyayı otomatik olarak kapatıp kapatmamasını denetler. Bunu devre dışı bırakmak, böyle bir durumda düzenleyicinin kaydedilmemiş değişiklikler içeriyor durumunda kalmasını sağlar. Uygulama içinde silmek, düzenleyiciyi her zaman kapatır ve kaydedilmemiş değişiklikler içeren dosyalar, verilerinizin korunması için otomatik olarak kapatılmaz.", "editorOpenPositioning": "Düzenleyicilerin nerede açılacağını denetler. Düzenleyicileri, şu an geçerli olanın soluna veya sağına açmak için 'left' veya 'right' seçeneklerinden birini seçin. Düzenleyicileri, geçerli olandan bağımsız bir şekilde açmak için 'first' veya 'last' seçeneklerinden birini seçin.", "revealIfOpen": "Düzenleyicinin görünen gruplardan herhangi birinde açıldıysa ortaya çıkarılıp çıkarılmayacağını denetler. Devre dışı bırakılırsa; bir düzenleyici, o an aktif düzenleyici grubunda açılmayı tercih edecektir. Etkinleştirilirse; o an aktif düzenleyici grubunda tekrar açılmak yerine, zaten açık olan düzenleyici ortaya çıkarılacaktır. Bu ayarın yok sayılacağı bazı durumların olduğunu unutmayın, ör. bir düzenleyiciyi, belirli bir grupta veya o an aktif grubun yanına açmaya zorladığınızda. ", + "swipeToNavigate": "Yatay olarak üç parmakla kaydırma ile açık dosyalar arasında gezinin.", "commandHistory": "Komut paleti geçmişinde tutulacak son kullanılan komutların sayısını denetler. Komut geçmişini kapatmak için 0 olarak ayarlayın.", "preserveInput": "Komut paletine son girilen girdinin, bir sonraki açılışta tekrar yer alıp almayacağını denetler.", "closeOnFocusLost": "Hızlı Aç'ın odağını kaybettiğinde otomatik olarak kapanıp kapanmayacağını denetler.", "openDefaultSettings": "Ayarları açmanın ayrıca tüm varsayılan ayarları gösteren bir düzenleyici açıp açmayacağını denetler.", "sideBarLocation": "Kenar çubuğunun konumunu denetler. Çalışma ekranının ya solunda ya da sağında gösterilebilir.", + "panelDefaultLocation": "Panelin varsayılan konumunu denetler. Çalışma ekranının ya altında ya da sağında gösterilebilir.", "statusBarVisibility": "Çalışma ekranının altındaki durum çubuğunun görünürlüğünü denetler.", "activityBarVisibility": "Çalışma ekranındaki etkinlik çubuğunun görünürlüğünü denetler.", - "closeOnFileDelete": "Düzenleyicinin gösterdiği bir dosyanın, başka bir işlem tarafından silinmesi veya yeniden adlandırması durumunda dosyayı otomatik olarak kapatıp kapatmamasını denetler. Bunu devre dışı bırakmak, böyle bir durumda düzenleyicinin kaydedilmemiş değişiklikler içeriyor durumunda kalmasını sağlar. Uygulama içinde silmek, düzenleyiciyi her zaman kapatır ve kaydedilmemiş değişiklikler içeren dosyalar, verilerinizin korunması için otomatik olarak kapatılmaz.", - "enableNaturalLanguageSettingsSearch": "Ayarlar için doğal dil arama modunun etkinleştirilip etkinleştirilmeyeceğini denetler.", "fontAliasing": "Çalışma ekranındaki yazı tipi yumuşatma yöntemini denetler.\n- default: Alt-piksel yazı tipi yumuşatma. Bu, çoğu retina olmayan ekranda en keskin metni verir\n- antialiased: Alt-pikselin tersine, pikselin seviyesine göre yazı tipini yumuşat. Yazı tipinin genel olarak daha açık görünmesini sağlayabilir\n- none: Yazı tipi yumuşatmayı devre dışı bırakır. Metin pürüzlü keskin kenarlarla gösterilir.", "workbench.fontAliasing.default": "Alt-piksel yazı tipi yumuşatma. Bu, çoğu retina olmayan ekranda en keskin metni verir.", "workbench.fontAliasing.antialiased": "Alt-pikselin tersine, pikselin seviyesine göre yazı tipini yumuşat. Yazı tipinin genel olarak daha açık görünmesini sağlayabilir.", "workbench.fontAliasing.none": "Yazı tipi yumuşatmayı devre dışı bırakır. Metin pürüzlü keskin kenarlarla gösterilir.", - "swipeToNavigate": "Yatay olarak üç parmakla kaydırma ile açık dosyalar arasında gezinin.", - "workbenchConfigurationTitle": "Çalışma Ekranı", + "enableNaturalLanguageSettingsSearch": "Ayarlar için doğal dil arama modunun etkinleştirilip etkinleştirilmeyeceğini denetler.", "windowConfigurationTitle": "Pencere", "window.openFilesInNewWindow.on": "Dosyalar yeni bir pencerede açılacak", "window.openFilesInNewWindow.off": "Dosyalar, dosyaların klasörünün olduğu pencerede veya son aktif pencerede açılacak", diff --git a/i18n/trk/src/vs/workbench/electron-browser/window.i18n.json b/i18n/trk/src/vs/workbench/electron-browser/window.i18n.json index c583af8e7cc..394ee06ccfd 100644 --- a/i18n/trk/src/vs/workbench/electron-browser/window.i18n.json +++ b/i18n/trk/src/vs/workbench/electron-browser/window.i18n.json @@ -9,5 +9,6 @@ "cut": "Kes", "copy": "Kopyala", "paste": "Yapıştır", - "selectAll": "Tümünü Seç" + "selectAll": "Tümünü Seç", + "runningAsRoot": "[0] uygulamasını root olarak çalıştırmanız önerilmez." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json b/i18n/trk/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json index 01e4868daa1..793bdc84f28 100644 --- a/i18n/trk/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/codeEditor/electron-browser/wordWrapMigration.i18n.json @@ -5,7 +5,7 @@ // Do not edit this file. It is machine generated. { "wordWrapMigration.ok": "Tamam", - "wordWrapMigration.dontShowAgain": "Tekrar gösterme", + "wordWrapMigration.dontShowAgain": "Tekrar Gösterme", "wordWrapMigration.openSettings": "Ayarları Aç", "wordWrapMigration.prompt": "`editor.wrappingColumn` ayarı, `editor.wordWrap` yüzünden kullanım dışıdır." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json index ea94460b89a..bd924b59861 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.i18n.json @@ -19,8 +19,6 @@ "vscode.extension.contributes.debuggers.configurationAttributes": "'launch.json' dosyasını doğrulayacak JSON şema yapılandırmaları.", "vscode.extension.contributes.debuggers.windows": "Windows'a özel ayarlar.", "vscode.extension.contributes.debuggers.windows.runtime": "Windows'da kullanılacak çalışma zamanı.", - "vscode.extension.contributes.debuggers.osx": "OS X'e özel ayarlar.", - "vscode.extension.contributes.debuggers.osx.runtime": "OS X'de kullanılacak çalışma zamanı.", "vscode.extension.contributes.debuggers.linux": "Linux'a özel ayarlar.", "vscode.extension.contributes.debuggers.linux.runtime": "Linux'da kullanılacak çalışma zamanı.", "vscode.extension.contributes.breakpoints": "Kesme noktalarına ekleme yapar.", diff --git a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json index b5f38fd9078..d27710092c4 100644 --- a/i18n/trk/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/debug/electron-browser/terminalSupport.i18n.json @@ -4,6 +4,5 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "debug.terminal.title": "hata ayıklanan", - "debug.terminal.not.available.error": "Entegre terminal mevcut değil" + "debug.terminal.title": "hata ayıklanan" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json index 010a09cd0cb..ca0fb5ce188 100644 --- a/i18n/trk/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/execution/electron-browser/execution.contribution.i18n.json @@ -12,6 +12,5 @@ "globalConsoleActionWin": "Yeni Komut İstemi Aç", "globalConsoleActionMacLinux": "Yeni Terminal Aç", "scopedConsoleActionWin": "Komut İsteminde Aç", - "scopedConsoleActionMacLinux": "Terminalde Aç", - "openFolderInIntegratedTerminal": "Terminalde Aç" + "scopedConsoleActionMacLinux": "Terminalde Aç" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json index 63820e9cd1c..53e00fca247 100644 --- a/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.i18n.json @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "fileBasedRecommendation": "Bu eklenti yakınlarda açtığınız dosyalara dayanarak tavsiye ediliyor.", + "neverShowAgain": "Tekrar gösterme", + "close": "Kapat", "workspaceRecommendation": "Bu eklenti geçerli çalışma alanı kullanıcıları tarafından tavsiye ediliyor.", + "fileBasedRecommendation": "Bu eklenti yakınlarda açtığınız dosyalara dayanarak tavsiye ediliyor.", "exeBasedRecommendation": "Bu eklenti, sizde {0} kurulu olduğu için tavsiye ediliyor.", "reallyRecommended2": "'{0}' eklentisi bu dosya türü için tavsiye edilir.", "reallyRecommendedExtensionPack": "'{0}' eklenti paketi bu dosya türü için tavsiye edilir.", "showRecommendations": "Tavsiyeleri Göster", "install": "Yükle", - "neverShowAgain": "Tekrar gösterme", - "close": "Kapat", "workspaceRecommended": "Bu çalışma alanı bazı eklentileri tavsiye ediyor.", "installAll": "Tümünü Yükle", "ignoreExtensionRecommendations": "Tüm eklenti tavsiyelerini yok saymak istiyor musunuz?", diff --git a/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json new file mode 100644 index 00000000000..0b6bb4e4396 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedback.contribution.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "workbenchConfigurationTitle": "Çalışma Ekranı" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json b/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json new file mode 100644 index 00000000000..f2a7a6f5dc4 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "hide": "Gizle" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json index 09b50f5c819..101a33d0a50 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.i18n.json @@ -7,5 +7,26 @@ "filesCategory": "Dosya", "revealInSideBar": "Kenar Çubuğunda Ortaya Çıkar", "acceptLocalChanges": "Değişikliklerinizi kullanın ve diskteki içeriklerin üzerine yazın", - "revertLocalChanges": "Değişikliklerinizi göz ardı edin ve diskteki içeriğe geri dönün" + "revertLocalChanges": "Değişikliklerinizi göz ardı edin ve diskteki içeriğe geri dönün", + "copyPathOfActive": "Aktif Dosyanın Yolunu Kopyala", + "saveAllInGroup": "Gruptaki Tümünü Kadet", + "saveFiles": "Tüm Dosyaları Kaydet", + "revert": "Dosyayı Geri Döndür", + "compareActiveWithSaved": "Aktif Dosyayı Kaydedilenle Karşılaştır", + "closeEditor": "Düzenleyiciyi Kapat", + "view": "Görüntüle", + "openToSide": "Yana Aç", + "revealInWindows": "Gezginde Ortaya Çıkar", + "revealInMac": "Finder'da Ortaya Çıkar", + "openContainer": "İçeren Klasörü Aç", + "copyPath": "Yolu Kopyala", + "saveAll": "Tümünü Kaydet", + "compareWithSaved": "Kaydedilenle Karşılaştır", + "compareWithSelected": "Seçilenle Karşılaştır", + "compareSource": "Karşılaştırma İçin Seç", + "close": "Kapat", + "closeOthers": "Diğerlerini Kapat", + "closeUnmodified": "Değiştirilmeyenleri Kapat", + "closeAll": "Tümünü Kapat", + "deleteFile": "Kalıcı Olarak Sil" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json index 2be3f4a5668..e326729b004 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileActions.i18n.json @@ -4,10 +4,13 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "retry": "Yeniden Dene", - "rename": "Yeniden Adlandır", "newFile": "Yeni Dosya", "newFolder": "Yeni Klasör", + "rename": "Yeniden Adlandır", + "delete": "Sil", + "copyFile": "Kopyala", + "pasteFile": "Yapıştır", + "retry": "Yeniden Dene", "openFolderFirst": "İçinde dosyalar veya klasörler oluşturmak için ilk olarak bir klasör açın.", "newUntitledFile": "Yeni İsimsiz Dosya", "createNewFile": "Yeni Dosya", @@ -28,26 +31,16 @@ "confirmDeleteMessageFile": "'{0}' öğesini kalıcı olarak silmek istediğinizden emin misiniz?", "irreversible": "Bu eylem geri döndürülemez!", "permDelete": "Kalıcı Olarak Sil", - "delete": "Sil", "importFiles": "Dosya İçe Aktar", "confirmOverwrite": "Hedef klasörde aynı ada sahip bir dosya veya klasör zaten var. Değiştirmek istiyor musunuz?", "replaceButtonLabel": "&&Değiştir", - "copyFile": "Kopyala", - "pasteFile": "Yapıştır", + "fileDeleted": "Dosya bu arada silindi veya taşındı", + "fileIsAncestor": "Hedef klasör, kopyalanacak klasörün içinde yer alıyor", "duplicateFile": "Çoğalt", - "openToSide": "Yana Aç", - "compareSource": "Karşılaştırma İçin Seç", "globalCompareFile": "Aktif Dosyayı Karşılaştır...", "openFileToCompare": "Bir başka dosya ile karşılaştırmak için ilk olarak bir dosya açın.", - "compareWith": "'{0}' dosyasını '{1}' ile karşılaştır", - "compareFiles": "Dosyaları Karşılaştır", "refresh": "Yenile", - "save": "Kaydet", - "saveAs": "Farklı Kaydet...", - "saveAll": "Tümünü Kaydet", "saveAllInGroup": "Gruptaki Tümünü Kadet", - "saveFiles": "Tüm Dosyaları Kaydet", - "revert": "Dosyayı Geri Döndür", "focusOpenEditors": "Açık Düzenleyiciler Görünümüne Odakla", "focusFilesExplorer": "Dosya Gezginine Odakla", "showInExplorer": "Aktif Dosyayı Kenar Çubuğunda Ortaya Çıkar", @@ -56,20 +49,11 @@ "refreshExplorer": "Gezgini Yenile", "openFileInNewWindow": "Aktif Dosyayı Yeni Pencerede Aç", "openFileToShowInNewWindow": "Yeni pencerede açmak için ilk olarak bir dosya açın", - "revealInWindows": "Gezginde Ortaya Çıkar", - "revealInMac": "Finder'da Ortaya Çıkar", - "openContainer": "İçeren Klasörü Aç", - "revealActiveFileInWindows": "Aktif Dosyayı Windows Gezgini'nde Ortaya Çıkar", - "revealActiveFileInMac": "Aktif Dosyayı Finder'da Ortaya Çıkar", - "openActiveFileContainer": "Aktif Dosyayı İçeren Klasörü Aç", "copyPath": "Yolu Kopyala", - "copyPathOfActive": "Aktif Dosyanın Yolunu Kopyala", "emptyFileNameError": "Bir dosya veya klasör adı sağlanması gerekiyor.", "fileNameExistsError": "Bu konumda bir **{0}** dosyası veya klasörü zaten mevcut. Lütfen başka bir ad seçin.", "invalidFileNameError": "**{0}** adı, bir dosya veya klasör adı olarak geçerli değildir. Lütfen başka bir ad seçin.", "filePathTooLongError": "**{0}** adı çok uzun bir yol ile sonuçlanıyor. Lütfen daha kısa bir ad seçin.", - "compareWithSaved": "Aktif Dosyayı Kaydedilenle Karşılaştır", - "modifiedLabel": "{0} (diskte) ↔ {1}", "compareWithClipboard": "Aktif Dosyayı Panodakiyle Karşılaştır", "clipboardComparisonLabel": "Pano ↔ {0}" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json index 699305824d3..c0c7d53c884 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/fileCommands.i18n.json @@ -4,6 +4,15 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openFileToCopy": "Yolunu kopyalamak için ilk olarak bir dosya açın", - "openFileToReveal": "Ortaya çıkarmak için ilk olarak bir dosya açın" + "revealInWindows": "Gezginde Ortaya Çıkar", + "revealInMac": "Finder'da Ortaya Çıkar", + "openContainer": "İçeren Klasörü Aç", + "saveAs": "Farklı Kaydet...", + "save": "Kaydet", + "saveAll": "Tümünü Kaydet", + "removeFolderFromWorkspace": "Çalışma Alanından Klasör Kaldır", + "genericRevertError": "'{0}' geri döndürülemedi: {1}", + "modifiedLabel": "{0} (diskte) ↔ {1}", + "openFileToReveal": "Ortaya çıkarmak için ilk olarak bir dosya açın", + "openFileToCopy": "Yolunu kopyalamak için ilk olarak bir dosya açın" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json index 4948cddf5c4..642be842a15 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/files.contribution.i18n.json @@ -36,8 +36,6 @@ "editorConfigurationTitle": "Düzenleyici", "formatOnSave": "Dosyayı kaydederken biçimlendir. Bir biçimlendirici mevcut olmalıdır, dosya otomatik olarak kaydedilmemelidir, ve düzenleyici kapanmıyor olmalıdır.", "explorerConfigurationTitle": "Dosya Gezgini", - "openEditorsVisible": "Açık Editörler bölmesinde gösterilen düzenleyici sayısı. Bölmeyi gizlemek için 0 olarak ayarlayın.", - "dynamicHeight": "Açık düzenleyiciler bölümü yüksekliğinin öge sayısına göre dinamik olarak uyarlanıp uyarlanmayacağını denetler.", "autoReveal": "Gezginin dosyaları açarken, onları otomatik olarak ortaya çıkartmasını ve seçmesini denetler.", "enableDragAndDrop": "Gezgeinin sürükle bırak ile dosyaları ve klasörleri taşımaya izin verip vermeyeceğini denetler.", "confirmDragAndDrop": "Gezginin, sürükle bırak ile dosyalar ve klasörlerin taşındığı zaman onay isteyip istemeyeceğini denetler.", diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json index 660d16789d0..a7b5a9c8bb9 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.i18n.json @@ -5,10 +5,14 @@ // Do not edit this file. It is machine generated. { "userGuide": "Değişikliklerinizi **geri al**mak veya diskteki içeriğin **üzerine yaz**mak için düzenleyicideki araç çubuğunu kullanabilirsiniz", - "discard": "At", + "overwriteElevated": "Yönetici Olarak Üzerine Yaz...", + "saveElevated": "Yönetici Olarak Yeniden Dene...", "overwrite": "Üzerine Yaz", "retry": "Yeniden Dene", - "readonlySaveError": "'{0}' kaydedilemedi: Dosya yazmaya karşı korunuyor. Korumayı kaldırmak için 'Üzerine Yaz'ı seçin.", + "discard": "At", + "readonlySaveErrorAdmin": "'{0}' kaydedilemedi: Dosya yazmaya karşı korunuyor. Yönetici olarak denemek için 'Yönetici Olarak Üzerine Yaz'ı seçin.", + "readonlySaveError": "'{0}' kaydedilemedi: Dosya yazmaya karşı korunuyor. Korumayı kaldırmayı denemek için 'Üzerine Yaz'ı seçin.", + "permissionDeniedSaveError": "'{0}' kaydedilemedi: Yetersiz yetki. Yönetici olarak denemek için 'Yönetici Olarak Yeniden Dene'yi seçin.", "genericSaveError": "'{0}' kaydedilemedi: ({1}).", "staleSaveError": "'{0}' kaydedilemedi: Diskteki içerik daha yeni. Sizdeki sürüm ile disktekini karşılaştırmak için **Karşılaştır**a tıklayın.", "compareChanges": "Karşılaştır", diff --git a/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json b/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json index 9f1cee51d98..d1e6467f5d8 100644 --- a/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.i18n.json @@ -6,11 +6,5 @@ { "openEditors": "Açık Düzenleyiciler", "openEditosrSection": "Açık Düzenleyiciler Bölümü", - "dirtyCounter": "{0} kaydedilmemiş", - "saveAll": "Tümünü Kaydet", - "closeAllUnmodified": "Değiştirilmeyenleri Kapat", - "closeAll": "Tümünü Kapat", - "compareWithSaved": "Kaydedilenle Karşılaştır", - "close": "Kapat", - "closeOthers": "Diğerlerini Kapat" + "dirtyCounter": "{0} kaydedilmemiş" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json new file mode 100644 index 00000000000..d1c3589857b --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logs.contribution.i18n.json @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "mainLog": "Günlük (Temel)", + "sharedLog": "Günlük (Ortak)", + "rendererLog": "Günlük (Pencere)", + "developer": "Geliştirici" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json b/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json new file mode 100644 index 00000000000..06c087ca4a9 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/logs/electron-browser/logsActions.i18n.json @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "openLogsFolder": "Günlük Klasörünü Aç", + "showLogs": "Günlükleri Göster...", + "mainProcess": "Temel", + "sharedProcess": "Ortak", + "rendererProcess": "Pencere", + "extensionHost": "Eklenti Sunucusu", + "selectProcess": "İşlem seçin", + "setLogLevel": "Günlük Düzeyini Ayarla", + "trace": "İzle", + "debug": "Hata Ayıklama", + "info": "Bilgi", + "warn": "Uyarı", + "err": "Hata", + "selectLogLevel": "Günlük düzeyini seçin" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/markers/common/messages.i18n.json b/i18n/trk/src/vs/workbench/parts/markers/common/messages.i18n.json index fe543da8a99..ca58bfe5d32 100644 --- a/i18n/trk/src/vs/workbench/parts/markers/common/messages.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/markers/common/messages.i18n.json @@ -5,8 +5,6 @@ // Do not edit this file. It is machine generated. { "viewCategory": "Görüntüle", - "problems.view.toggle.label": "Sorunları Aç/Kapat", - "problems.view.focus.label": "Sorunlara Odakla", "problems.panel.configuration.title": "Sorunlar Görünümü", "problems.panel.configuration.autoreveal": "Sorunlar görünümünün; dosyalar açılırken, dosyaları otomatik olarak ortaya çıkarıp çıkarmayacağını denetler.", "markers.panel.title.problems": "Sorunlar", diff --git a/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json new file mode 100644 index 00000000000..fe8f6125b1a --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/output/electron-browser/output.contribution.i18n.json @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "output": "Çıktı", + "viewCategory": "Görüntüle", + "clearOutput.label": "Çıktıyı Temizle" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json b/i18n/trk/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json new file mode 100644 index 00000000000..8b6ad71cd4e --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/output/electron-browser/outputServices.i18n.json @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json index dad393ec3bf..dc51088525e 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/browser/preferencesWidgets.i18n.json @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "defaultSettingsFuzzyPrompt": "Doğal dil aramasını deneyin!", "defaultSettings": "Geçersiz kılmak için ayarlarınızı sağ taraftaki düzeyiciye ekleyin.", "noSettingsFound": "Hiçbir Ayar Bulunamadı.", "settingsSwitcherBarAriaLabel": "Ayar Değiştirici", "userSettings": "Kullanıcı Ayarları", "workspaceSettings": "Çalışma Alanı Ayarları", - "folderSettings": "Klasör Ayarları", - "enableFuzzySearch": "Doğal dil aramasını etkinleştir" + "folderSettings": "Klasör Ayarları" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json b/i18n/trk/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json index ad4ed40e889..dc4c28efe52 100644 --- a/i18n/trk/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/preferences/common/preferencesModels.i18n.json @@ -5,6 +5,5 @@ // Do not edit this file. It is machine generated. { "commonlyUsed": "Yaygın Olarak Kullanılan", - "mostRelevant": "En Uygun", "defaultKeybindingsHeader": "Tuş bağları dosyanıza yerleştirerek tuş bağlarının üzerine yazın." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json index fe14853bad6..018ca1806dd 100644 --- a/i18n/trk/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/quickopen/browser/quickopen.contribution.i18n.json @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "view": "Görüntüle", "commandsHandlerDescriptionDefault": "Komutları Göster ve Çalıştır", "gotoLineDescriptionMac": "Satıra Git", "gotoLineDescriptionWin": "Satıra Git", diff --git a/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json index 06bd99d62b1..137024a0daf 100644 --- a/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/scm/electron-browser/scm.contribution.i18n.json @@ -7,5 +7,6 @@ "toggleGitViewlet": "Git'i Göster", "source control": "Kaynak Kontrolü", "toggleSCMViewlet": "SCM'yi Göster", - "view": "Görüntüle" + "view": "Görüntüle", + "scmConfigurationTitle": "SCM" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json index cf14cf9120f..d06d8e0857e 100644 --- a/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/browser/searchActions.i18n.json @@ -12,9 +12,7 @@ "previousSearchTerm": "Önceki Arama Terimini Göster", "showSearchViewlet": "Aramayı Göster", "findInFiles": "Dosyalarda Bul", - "findInFilesWithSelectedText": "Seçili Metni Dosyalarda Bul", "replaceInFiles": "Dosyalardakileri Değiştir", - "replaceInFilesWithSelectedText": "Dosyalardaki Seçili Metni Değiştir", "RefreshAction.label": "Yenile", "CollapseDeepestExpandedLevelAction.label": "Tümünü Daralt", "ClearSearchResultsAction.label": "Temizle", diff --git a/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json index fd6f32d47d6..5643091fd7a 100644 --- a/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/search/electron-browser/search.contribution.i18n.json @@ -4,13 +4,16 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "findInFolder": "Klasörde Bul...", + "findInWorkspace": "Çalışma Alanında Bul...", "showTriggerActions": "Çalışma Alanında Sembole Git...", "name": "Ara", "search": "Ara", + "showSearchViewlet": "Aramayı Göster", "view": "Görüntüle", + "findInFiles": "Dosyalarda Bul", "openAnythingHandlerDescription": "Dosyaya Git", "openSymbolDescriptionNormal": "Çalışma Alanında Sembole Git", - "searchOutputChannelTitle": "Ara", "searchConfigurationTitle": "Ara", "exclude": "Aramalarda dosyaları ve klasörleri hariç tutmak için glob desenlerini yapılandırın. files.exclude ayarından, tüm glob desenlerini devralır.", "exclude.boolean": "Dosya yollarının eşleştirileceği glob deseni. Deseni etkinleştirmek veya devre dışı bırakmak için true veya false olarak ayarlayın.", diff --git a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json new file mode 100644 index 00000000000..a6843828675 --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/configureSnippets.i18n.json @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "global.1": "({0})", + "preferences": "Tercihler" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json index 11671c7d0b4..7e1c6237303 100644 --- a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.i18n.json @@ -4,10 +4,6 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "openSnippet.pickLanguage": "Parçacık için Dil seçin", - "openSnippet.errorOnCreate": "{0} oluşturulamadı", - "openSnippet.label": "Kullanıcı Parçacıklarını Aç", - "preferences": "Tercihler", "snippetSchema.json.default": "Boş parçacık", "snippetSchema.json": "Kullanıcı parçacığı yapılandırması", "snippetSchema.json.prefix": "Parçacığı IntelliSense'de seçerken kullanılacak ön ek", diff --git a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json new file mode 100644 index 00000000000..d246a5f624d --- /dev/null +++ b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsFile.i18n.json @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +// Do not edit this file. It is machine generated. +{ + "source.snippet": "Kullanıcı Parçacığı" +} \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json index ebad445a20b..8257fed50b0 100644 --- a/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/snippets/electron-browser/snippetsService.i18n.json @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { - "invalid.language": "`contributes.{0}.language` ögesinde bilinmeyen dil. Sağlanan değer: {1}", "invalid.path.0": "`contributes.{0}.path` ögesinde dize bekleniyor. Sağlanan değer: {1}", + "invalid.language": "`contributes.{0}.language` ögesinde bilinmeyen dil. Sağlanan değer: {1}", "invalid.path.1": "`contributes.{0}.path` ögesinin ({1}) eklentinin klasöründe ({2}) yer alması bekleniyor. Bu, eklentiyi taşınamaz yapabilir.", "vscode.extension.contributes.snippets": "Parçacıklara ekleme yapar.", "vscode.extension.contributes.snippets-language": "Bu parçacığın ekleneceği dilin tanımlayıcısı.", "vscode.extension.contributes.snippets-path": "Parçacıklar dosyasının yolu. Yol, eklenti klasörüne görecelidir ve genellikle './snippets/' ile başlar.", "badVariableUse": "'{0}' eklentisindeki bir veya daha çok parçacık yüksek olasılıkla parçacık değişkenleri ile parçacık yer tutucularını karıştırıyor (daha fazla bilgi için https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax adresini ziyaret edin).", "badFile": "Parçacık dosyası \"{0}\" okunamadı.", - "source.snippet": "Kullanıcı Parçacığı", "detail.snippet": "{0} ({1})", "snippetSuggest.longLabel": "{0}, {1}" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json index a994ebe0909..644e7e44a52 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalColorRegistry.i18n.json @@ -8,6 +8,5 @@ "terminal.foreground": "Terminalin ön plan rengi.", "terminalCursor.foreground": "Terminal imlecinin ön plan rengi.", "terminalCursor.background": "Terminal imlecinin arka plan rengi. Bir blok imlecinin kapladığı bir karakterin rengini özelleştirmeyi sağlar.", - "terminal.selectionBackground": "Terminalin seçim arkaplanı rengi.", - "terminal.ansiColor": "Terminalde '{0}' ANSI rengi." + "terminal.selectionBackground": "Terminalin seçim arkaplanı rengi." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json index a30794054e1..2c0a6d7607f 100644 --- a/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/terminal/electron-browser/terminalService.i18n.json @@ -7,7 +7,6 @@ "terminal.integrated.chooseWindowsShellInfo": "Özelleştir butonuna tıklayıp varsayılan terminal kabuğunu seçebilirsiniz.", "customize": "Özelleştir", "cancel": "İptal", - "never again": "Tamam, Tekrar Gösterme", "terminal.integrated.chooseWindowsShell": "Tercih ettiğiniz terminal kabuğunu seçin, bunu daha sonra ayarlarınızdan değiştirebilirsiniz", "terminalService.terminalCloseConfirmationSingular": "Aktif bir terminal oturumu var, sonlandırmak istiyor musunuz?", "terminalService.terminalCloseConfirmationPlural": "{0} aktif terminal oturumu var, bunları sonlandırmak istiyor musunuz?" diff --git a/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json b/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json index 61ebe35f50c..64fe6d494db 100644 --- a/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json +++ b/i18n/trk/src/vs/workbench/parts/update/electron-browser/update.i18n.json @@ -23,6 +23,7 @@ "commandPalette": "Komut Paleti...", "settings": "Ayarlar", "keyboardShortcuts": "Klavye Kısayolları", + "userSnippets": "Kullanıcı Parçacıkları", "selectTheme.label": "Renk Teması", "themes.selectIconTheme.label": "Dosya Simgesi Teması", "not available": "Güncelleştirme Yok", diff --git a/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json b/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json index 320c074b5d2..699613ce8f0 100644 --- a/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/files/electron-browser/remoteFileService.i18n.json @@ -4,5 +4,7 @@ *--------------------------------------------------------------------------------------------*/ // Do not edit this file. It is machine generated. { + "fileIsDirectoryError": "Dosya bir dizindir", + "fileNotModifiedError": "Dosya şu tarihten beri değiştirilmemiş:", "fileBinaryError": "Dosya ikili olarak görünüyor ve metin olarak açılamıyor" } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json b/i18n/trk/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json index 5284725dbcb..f0547df6a62 100644 --- a/i18n/trk/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/textfile/electron-browser/textFileService.i18n.json @@ -6,8 +6,6 @@ { "saveChangesMessage": "{0} dosyasına yaptığınız değişiklikleri kaydetmek istiyor musunuz?", "saveChangesMessages": "Aşağıdaki {0} dosyaya yaptığınız değişiklikleri kaydetmek istiyor musunuz?", - "moreFile": "...1 ek dosya gösterilmiyor", - "moreFiles": "...{0} ek dosya gösterilmiyor", "saveAll": "&&Tümünü Kaydet", "save": "&&Kaydet", "dontSave": "Kaydet&&me", diff --git a/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json b/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json index 06e828ba73e..f60dda6f647 100644 --- a/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.i18n.json @@ -11,7 +11,6 @@ "noIconThemeDesc": "Dosya simgesi yok", "iconThemeError": "Dosya simgesi teması bilinmiyor veya yüklenmemiş.", "workbenchColors": "Şu an seçili renk temasındaki renkleri geçersiz kılar.", - "editorColors": "Şu an seçili renk temasındaki düzenleyici renklerini ve yazı tipi stilini geçersiz kılar.", "editorColors.comments": "Yorumların rengini ve stillerini ayarlar", "editorColors.strings": "Dizelerin rengini ve stillerini ayarlar.", "editorColors.keywords": "Anahtar sözcüklerin rengini ve stillerini ayarlar.", @@ -19,5 +18,6 @@ "editorColors.types": "Tür bildirimi ve başvurularının rengini ve stillerini ayarlar.", "editorColors.functions": "Fonksiyon bildirimi ve başvurularının rengini ve stillerini ayarlar.", "editorColors.variables": "Değişken bildirimi ve başvurularının rengini ve stillerini ayarlar.", - "editorColors.textMateRules": "Textmate tema kurallarını kullanarak renkleri ve stilleri ayarlar (gelişmiş)." + "editorColors.textMateRules": "Textmate tema kurallarını kullanarak renkleri ve stilleri ayarlar (gelişmiş).", + "editorColors": "Şu an seçili renk temasındaki düzenleyici renklerini ve yazı tipi stilini geçersiz kılar." } \ No newline at end of file diff --git a/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json b/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json index 38e103f1ee8..19e6e2498a4 100644 --- a/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json +++ b/i18n/trk/src/vs/workbench/services/workspace/node/workspaceEditingService.i18n.json @@ -7,9 +7,5 @@ "errorInvalidTaskConfiguration": "Çalışma alanı yapılandırma dosyasına yazılamıyor. Lütfen dosyadaki hata/uyarıları düzeltmek için dosyayı açın ve tekrar deneyin.", "errorWorkspaceConfigurationFileDirty": "Kaydedilmemiş değişiklikler içerdiği için çalışma alanı yapılandırma dosyasına yazılamıyor. Lütfen dosyayı kaydedin ve tekrar deneyin.", "openWorkspaceConfigurationFile": "Çalışma Alanı Yapılandırma Dosyasını Aç", - "close": "Kapat", - "enterWorkspace.close": "Kapat", - "enterWorkspace.dontShowAgain": "Tekrar Gösterme", - "enterWorkspace.moreInfo": "Daha Fazla Bilgi", - "enterWorkspace.prompt": "VS Code'da birden çok klasörle çalışmak hakkında daha fazla bilgi edinin." + "close": "Kapat" } \ No newline at end of file diff --git a/package.json b/package.json index aa70e1e524a..96561cc6b67 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.20.0", - "distro": "3e04fd7a1141705f5e82fb1175edc03d0d4ddf9c", + "distro": "d41bd1b8193403ffe9849b49fc37153e3d5b5a49", "author": { "name": "Microsoft Corporation" }, @@ -18,6 +18,7 @@ "gulp": "gulp --max_old_space_size=4096", "7z": "7z", "update-grammars": "node build/npm/update-all-grammars.js", + "update-localization-extension": "node build/npm/update-localization-extension.js", "smoketest": "cd test/smoke && mocha" }, "dependencies": { @@ -38,14 +39,14 @@ "node-pty": "0.7.4", "nsfw": "1.0.16", "semver": "4.3.6", - "spdlog": "0.5.0", + "spdlog": "0.6.0", "sudo-prompt": "^8.0.0", "v8-inspect-profiler": "^0.0.7", "vscode-chokidar": "1.6.2", "vscode-debugprotocol": "1.25.0", "vscode-ripgrep": "^0.7.1-patch.0", "vscode-textmate": "^3.2.0", - "vscode-xterm": "3.1.0-beta2", + "vscode-xterm": "3.1.0-beta11", "yauzl": "2.8.0" }, "devDependencies": { @@ -115,7 +116,7 @@ "vinyl": "^0.4.5", "vinyl-fs": "^2.4.3", "vsce": "1.33.2", - "vscode-nls-dev": "^2.0.1" + "vscode-nls-dev": "^3.0.5" }, "repository": { "type": "git", diff --git a/scripts/code.bat b/scripts/code.bat index 3b403b1c64c..b23ee223546 100644 --- a/scripts/code.bat +++ b/scripts/code.bat @@ -17,6 +17,10 @@ set CODE=".build\electron\%NAMESHORT%" node build\lib\electron.js if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js electron +:: Get built-in extensions +node build\lib\builtInExtensions.js +if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js download-builtin-extensions + :: Build if not exist out node .\node_modules\gulp\bin\gulp.js compile diff --git a/scripts/code.sh b/scripts/code.sh index 6339ad06bd4..7f52ded6fe5 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -24,6 +24,9 @@ function code() { # Get electron node build/lib/electron.js || ./node_modules/.bin/gulp electron + # Get built-in extensions + node build/lib/builtInExtensions.js || ./node_modules/.bin/gulp download-builtin-extensions + # Build test -d out || ./node_modules/.bin/gulp compile diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index b9a95fa62c9..9a779446e2c 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -9,7 +9,10 @@ if not "%APPVEYOR%" == "" ( 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% +call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +if %errorlevel% neq 0 exit /b %errorlevel% + +call .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace.code-workspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --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% diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index 6159dc88aa9..ba10a8cfd69 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -13,7 +13,8 @@ fi cd $ROOT # Tests in the extension host -./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started +./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace.code-workspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started ./scripts/code.sh $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started ./scripts/code.sh $ROOT/extensions/emmet/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disableExtensions --user-data-dir=$VSCODEUSERDATADIR --skip-getting-started diff --git a/src/bootstrap-amd.js b/src/bootstrap-amd.js index b5e142fca8e..8b91b77b671 100644 --- a/src/bootstrap-amd.js +++ b/src/bootstrap-amd.js @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ var path = require('path'); +var fs = require('fs'); var loader = require('./vs/loader'); function uriFromPath(_path) { @@ -16,9 +17,40 @@ function uriFromPath(_path) { return encodeURI('file://' + pathName); } +function readFile(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, 'utf8', function(err, data) { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + var rawNlsConfig = process.env['VSCODE_NLS_CONFIG']; var nlsConfig = rawNlsConfig ? JSON.parse(rawNlsConfig) : { availableLanguages: {} }; +// We have a special location of the nls files. They come from a language pack +if (nlsConfig._resolvedLanguagePackCoreLocation) { + let bundles = Object.create(null); + nlsConfig.loadBundle = function(bundle, language, cb) { + let result = bundles[bundle]; + if (result) { + cb(undefined, result); + return; + } + let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json'); + readFile(bundleFile).then(function (content) { + let json = JSON.parse(content); + bundles[bundle] = json; + cb(undefined, json); + }) + .catch(cb); + }; +} + loader.config({ baseUrl: uriFromPath(__dirname), catchError: true, diff --git a/src/main.js b/src/main.js index 6e29b5203a6..127e6500797 100644 --- a/src/main.js +++ b/src/main.js @@ -2,44 +2,41 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - 'use strict'; -var perf = require('./vs/base/common/performance'); +let perf = require('./vs/base/common/performance'); perf.mark('main:started'); // Perf measurements global.perfStartTime = Date.now(); -var app = require('electron').app; -var fs = require('fs'); -var path = require('path'); -var minimist = require('minimist'); -var paths = require('./paths'); +let app = require('electron').app; +let fs = require('fs'); +let path = require('path'); +let minimist = require('minimist'); +let paths = require('./paths'); -var args = minimist(process.argv, { +let args = minimist(process.argv, { string: ['user-data-dir', 'locale'] }); function stripComments(content) { - var regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; - var result = content.replace(regexp, function (match, m1, m2, m3, m4) { + let regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; + let result = content.replace(regexp, function (match, m1, m2, m3, m4) { // Only one of m1, m2, m3, m4 matches if (m3) { // A block comment. Replace with nothing return ''; - } - else if (m4) { + } else if (m4) { // A line comment. If it ends in \r?\n then keep it. - var length_1 = m4.length; + let length_1 = m4.length; if (length_1 > 2 && m4[length_1 - 1] === '\n') { return m4[length_1 - 2] === '\r' ? '\r\n' : '\n'; } else { return ''; } - } - else { + } else { // We match a string return match; } @@ -47,71 +44,309 @@ function stripComments(content) { return result; } -function getNLSConfiguration() { - var locale = args['locale']; +let _commit; +function getCommit() { + if (_commit) { + return _commit; + } + if (_commit === null) { + return undefined; + } + try { + let productJson = require(path.join(__dirname, '../product.json')); + if (productJson.commit) { + _commit = productJson.commit; + } else { + _commit = null; + } + } catch (exp) { + _commit = null; + } +} - if (!locale) { - var userData = app.getPath('userData'); - var localeConfig = path.join(userData, 'User', 'locale.json'); - if (fs.existsSync(localeConfig)) { - try { - var content = stripComments(fs.readFileSync(localeConfig, 'utf8')); - var value = JSON.parse(content).locale; - if (value && typeof value === 'string') { - locale = value; +function mkdirp(dir) { + return mkdir(dir) + .then(null, (err) => { + if (err && err.code === 'ENOENT') { + let parent = path.dirname(dir); + if (parent !== dir) { // if not arrived at root + return mkdirp(parent) + .then(() => { + return mkdir(dir); + }); + } + } + throw err; + }); +} + +function mkdir(dir) { + return new Promise((resolve, reject) => { + fs.mkdir(dir, (err) => { + if (err && err.code !== 'EEXIST') { + reject(err); + } else { + resolve(dir); + } + }); + }); +} + +function exists(file) { + return new Promise((resolve) => { + fs.exists(file, (result) => { + resolve(result); + }); + }); +} + +function readFile(file) { + return new Promise((resolve, reject) => { + fs.readFile(file, 'utf8', (err, data) => { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + +function writeFile(file, content) { + return new Promise((resolve, reject) => { + fs.writeFile(file, content, 'utf8', (err) => { + if (err) { + reject(err); + return; + } + resolve(undefined); + }); + }); +} + +function touch(file) { + return new Promise((resolve, reject) => { + let d = new Date(); + fs.utimes(file, d, d, (err) => { + if (err) { + reject(err); + return; + } + resolve(undefined); + }); + }); +} + +// Language tags are case insensitve however an amd loader is case sensitive +// To make this work on case preserving & insensitive FS we do the following: +// the language bundles have lower case language tags and we always lower case +// the locale we receive from the user or OS. + +function getUserDefinedLocale() { + let locale = args['locale']; + if (locale) { + return Promise.resolve(locale.toLowerCase()); + } + + let userData = app.getPath('userData'); + let localeConfig = path.join(userData, 'User', 'locale.json'); + return exists(localeConfig).then((result) => { + if (result) { + return readFile(localeConfig).then((content) => { + content = stripComments(content); + try { + let value = JSON.parse(content).locale; + return value && typeof value === 'string' ? value.toLowerCase() : undefined; + } catch (e) { + return undefined; + } + }); + } else { + return undefined; + } + }); +} + +function getLanguagePackConfigurations() { + let userData = app.getPath('userData'); + let configFile = path.join(userData, 'languagepacks.json'); + try { + return require(configFile); + } catch (err) { + // Do nothing. If we can't read the file we have no + // language pack config. + } + return undefined; +} + +function resolveLanguagePackLocale(config, locale) { + try { + while (locale) { + if (config[locale]) { + return locale; + } else { + let index = locale.lastIndexOf('-'); + if (index > 0) { + locale = locale.substring(0, index); + } else { + return undefined; } - } catch (e) { - // noop } } + } catch (err) { + console.error('Resolving language pack configuration failed.', err); + } + return undefined; +} + +function getNLSConfiguration(locale) { + if (locale === 'pseudo') { + return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true }); } - var appLocale = app.getLocale(); - locale = locale || appLocale; - // Language tags are case insensitve however an amd loader is case sensitive - // To make this work on case preserving & insensitive FS we do the following: - // the language bundles have lower case language tags and we always lower case - // the locale we receive from the user or OS. - locale = locale ? locale.toLowerCase() : locale; - if (locale === 'pseudo') { - return { locale: locale, availableLanguages: {}, pseudo: true }; - } - var initialLocale = locale; if (process.env['VSCODE_DEV']) { - return { locale: locale, availableLanguages: {} }; + return Promise.resolve({ locale: locale, availableLanguages: {} }); } + let userData = app.getPath('userData'); + // We have a built version so we have extracted nls file. Try to find // the right file to use. // Check if we have an English locale. If so fall to default since that is our // English translation (we don't ship *.nls.en.json files) if (locale && (locale == 'en' || locale.startsWith('en-'))) { - return { locale: locale, availableLanguages: {} }; + return Promise.resolve({ locale: locale, availableLanguages: {} }); } + let initialLocale = locale; + function resolveLocale(locale) { while (locale) { - var candidate = path.join(__dirname, 'vs', 'code', 'electron-main', 'main.nls.') + locale + '.js'; + let candidate = path.join(__dirname, 'vs', 'code', 'electron-main', 'main.nls.') + locale + '.js'; if (fs.existsSync(candidate)) { return { locale: initialLocale, availableLanguages: { '*': locale } }; } else { - var index = locale.lastIndexOf('-'); + let index = locale.lastIndexOf('-'); if (index > 0) { locale = locale.substring(0, index); } else { - locale = null; + locale = undefined; } } } - return null; + return undefined; } - var resolvedLocale = resolveLocale(locale); - if (!resolvedLocale && appLocale && appLocale !== locale) { - resolvedLocale = resolveLocale(appLocale); + let isCoreLangaguage = true; + if (locale) { + isCoreLangaguage = ['de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'tr', 'zh-cn', 'zh-tw'].some((language) => { + return locale === language || locale.startsWith(language + '-'); + }); + } + + if (isCoreLangaguage) { + return Promise.resolve(resolveLocale(locale)); + } else { + perf.mark('nlsGeneration:start'); + let defaultResult = function() { + perf.mark('nlsGeneration:end'); + return Promise.resolve({ locale: locale, availableLanguages: {} }); + }; + try { + let commit = getCommit(); + if (!commit) { + return defaultResult(); + } + let configs = getLanguagePackConfigurations(); + if (!configs) { + return defaultResult(); + } + let initialLocale = locale; + locale = resolveLanguagePackLocale(configs, locale); + if (!locale) { + return defaultResult(); + } + let packConfigs = configs[locale]; + if (!packConfigs || !Array.isArray(packConfigs) || packConfigs.length === 0) { + return defaultResult(); + } + // We take the first install language pack. No idea what to do if we have more + // than one :-) + let packConfig = packConfigs[0]; + if (typeof packConfig.translations !== 'string' || typeof packConfig.version !== 'string' || packConfig.version.match(/\d+\.\d+\.\d+/) === null) { + return defaultResult(); + } + return exists(packConfig.translations).then((fileExists) => { + if (!fileExists) { + return defaultResult(); + } + let packId = packConfig.extensionIdentifier.id + '-' + packConfig.version; + let cacheRoot = path.join(userData, 'clp', packId); + let coreLocation = path.join(cacheRoot, commit); + let result = { + locale: initialLocale, + availableLanguages: { '*': locale }, + _languagePackId: packId, + _languagePackLocation: packConfig.translations, + _cacheRoot: cacheRoot, + _resolvedLanguagePackCoreLocation: coreLocation + }; + return exists(coreLocation).then((fileExists) => { + if (fileExists) { + // We don't wait for this. No big harm if we can't touch + touch(coreLocation).catch(() => {}); + perf.mark('nlsGeneration:end'); + return result; + } + return mkdirp(coreLocation).then(() => { + return Promise.all([readFile(path.join(__dirname, 'nls.metadata.json')), readFile(path.join(packConfig.translations, 'main.i18n.json'))]); + }).then((values) => { + let metadata = JSON.parse(values[0]); + let packData = JSON.parse(values[1]).contents; + let bundles = Object.keys(metadata.bundles); + let writes = []; + for (let bundle of bundles) { + let modules = metadata.bundles[bundle]; + let target = Object.create(null); + for (let module of modules) { + let keys = metadata.keys[module]; + let defaultMessages = metadata.messages[module]; + let translations = packData[module]; + let targetStrings; + if (translations) { + targetStrings = []; + for (let i = 0; i < keys.length; i++) { + let elem = keys[i]; + let key = typeof elem === 'string' ? elem : elem.key; + let translatedMessage = translations[key]; + if (translatedMessage === undefined) { + translatedMessage = defaultMessages[i]; + } + targetStrings.push(translatedMessage); + } + } else { + targetStrings = defaultMessages; + } + target[module] = targetStrings; + } + writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g,'!') + '.nls.json'), JSON.stringify(target))); + } + return Promise.all(writes); + }).then(() => { + perf.mark('nlsGeneration:end'); + return result; + }).catch((err) => { + console.error('Generating translation files failed.', err); + return defaultResult(); + }); + }); + }); + } catch (err) { + console.error('Generating translation files failed.', err); + return defaultResult(); + } } - return resolvedLocale ? resolvedLocale : { locale: initialLocale, availableLanguages: {} }; } function getNodeCachedDataDir() { @@ -126,52 +361,24 @@ function getNodeCachedDataDir() { } // find commit id - var productJson = require(path.join(__dirname, '../product.json')); - if (!productJson.commit) { + let commit = getCommit(); + if (!commit) { return Promise.resolve(undefined); } - var dir = path.join(app.getPath('userData'), 'CachedData', productJson.commit); + let dir = path.join(app.getPath('userData'), 'CachedData', commit); return mkdirp(dir).then(undefined, function () { /*ignore*/ }); } -function mkdirp(dir) { - return mkdir(dir) - .then(null, function (err) { - if (err && err.code === 'ENOENT') { - var parent = path.dirname(dir); - if (parent !== dir) { // if not arrived at root - return mkdirp(parent) - .then(function () { - return mkdir(dir); - }); - } - } - throw err; - }); -} - -function mkdir(dir) { - return new Promise(function (resolve, reject) { - fs.mkdir(dir, function (err) { - if (err && err.code !== 'EEXIST') { - reject(err); - } else { - resolve(dir); - } - }); - }); -} - // Set userData path before app 'ready' event and call to process.chdir -var userData = path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform)); +let userData = path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform)); app.setPath('userData', userData); // Update cwd based on environment and platform try { if (process.platform === 'win32') { - process.env['VSCODE_CWD'] = process.cwd(); // remember as environment variable + process.env['VSCODE_CWD'] = process.cwd(); // remember as environment letiable process.chdir(path.dirname(app.getPath('exe'))); // always set application folder as cwd } else if (process.env['VSCODE_CWD']) { process.chdir(process.env['VSCODE_CWD']); @@ -187,8 +394,8 @@ app.on('open-file', function (event, path) { global.macOpenFiles.push(path); }); -var openUrls = []; -var onOpenUrl = function (event, url) { +let openUrls = []; +let onOpenUrl = function (event, url) { event.preventDefault(); openUrls.push(url); }; @@ -205,7 +412,7 @@ global.getOpenUrls = function () { // use '/CachedData'-directory to store // node/v8 cached data. -var nodeCachedDataDir = getNodeCachedDataDir().then(function (value) { +let nodeCachedDataDir = getNodeCachedDataDir().then(function (value) { if (value) { // store the data directory process.env['VSCODE_NODE_CACHED_DATA_DIR_' + process.pid] = value; @@ -214,15 +421,56 @@ var nodeCachedDataDir = getNodeCachedDataDir().then(function (value) { // but because we generate cached data it makes subsequent startups much faster app.commandLine.appendSwitch('--js-flags', '--nolazy'); } + return value; +}); + +let nlsConfiguration = undefined; +let userDefinedLocale = getUserDefinedLocale(); +userDefinedLocale.then((locale) => { + if (locale && !nlsConfiguration) { + nlsConfiguration = getNLSConfiguration(locale); + } }); // Load our code once ready app.once('ready', function () { perf.mark('main:appReady'); - var nlsConfig = getNLSConfiguration(); - process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); - - nodeCachedDataDir.then(function () { - require('./bootstrap-amd').bootstrap('vs/code/electron-main/main'); + Promise.all([nodeCachedDataDir, userDefinedLocale]).then((values) => { + let locale = values[1]; + if (locale && !nlsConfiguration) { + nlsConfiguration = getNLSConfiguration(locale); + } + if (!nlsConfiguration) { + nlsConfiguration = Promise.resolve(undefined); + } + // We first need to test a user defined locale. If it fails we try the app locale. + // If that fails we fall back to English. + nlsConfiguration.then((nlsConfig) => { + let boot = (nlsConfig) => { + process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig); + require('./bootstrap-amd').bootstrap('vs/code/electron-main/main'); + }; + // We recevied a valid nlsConfig from a user defined locale + if (nlsConfig) { + boot(nlsConfig); + } else { + // Try to use the app locale. Please note that the app locale is only + // valid after we have received the app ready event. This is why the + // code is here. + let appLocale = app.getLocale(); + if (!appLocale) { + boot({ locale: 'en', availableLanguages: {} }); + } else { + // See above the comment about the loader and case sensitiviness + appLocale.toLowerCase(); + getNLSConfiguration(appLocale).then((nlsConfig) => { + if (!nlsConfig) { + nlsConfig = { locale: appLocale, availableLanguages: {} }; + } + boot(nlsConfig); + }); + } + } + }); }, console.error); }); diff --git a/src/typings/iconv-lite.d.ts b/src/typings/iconv-lite.d.ts index 84c54e320cf..5ad19bb95b7 100644 --- a/src/typings/iconv-lite.d.ts +++ b/src/typings/iconv-lite.d.ts @@ -6,13 +6,13 @@ /// declare module 'iconv-lite' { - export function decode(buffer: NodeBuffer, encoding: string, options?: any): string; + export function decode(buffer: NodeBuffer, encoding: string): string; - export function encode(content: string, encoding: string, options?: any): NodeBuffer; + export function encode(content: string, encoding: string, options?: { addBOM?: boolean }): NodeBuffer; export function encodingExists(encoding: string): boolean; export function decodeStream(encoding: string): NodeJS.ReadWriteStream; - export function encodeStream(encoding: string): NodeJS.ReadWriteStream; + export function encodeStream(encoding: string, options?: { addBOM?: boolean }): NodeJS.ReadWriteStream; } \ No newline at end of file diff --git a/src/typings/node.d.ts b/src/typings/node.d.ts index 37db4dd80f0..4fa18421982 100644 --- a/src/typings/node.d.ts +++ b/src/typings/node.d.ts @@ -1720,6 +1720,7 @@ declare module "child_process" { uid?: number; gid?: number; shell?: boolean | string; + windowsVerbatimArguments?: boolean; } export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess; diff --git a/src/typings/vscode-xterm.d.ts b/src/typings/vscode-xterm.d.ts index a8000eec916..df8bf449cea 100644 --- a/src/typings/vscode-xterm.d.ts +++ b/src/typings/vscode-xterm.d.ts @@ -8,6 +8,11 @@ */ declare module 'vscode-xterm' { + /** + * A string representing text font weight. + */ + export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + /** * An object containing start up options for the terminal. */ @@ -57,6 +62,16 @@ declare module 'vscode-xterm' { */ fontFamily?: string; + /** + * The font weight used to render non-bold text. + */ + fontWeight?: FontWeight; + + /** + * The font weight used to render bold text. + */ + fontWeightBold?: FontWeight; + /** * The spacing in whole pixels between characters.. */ @@ -67,6 +82,11 @@ declare module 'vscode-xterm' { */ lineHeight?: number; + /** + * Whether to treat option as the meta key. + */ + macOptionIsMeta?: boolean; + /** * The number of rows in the terminal. */ @@ -332,6 +352,12 @@ declare module 'vscode-xterm' { */ deregisterLinkMatcher(matcherId: number): void; + /** + * Enters screen reader navigation mode. This will only work when + * the screenReaderMode option is true. + */ + enterNavigationMode(): void; + /** * Gets whether the terminal has an active selection. */ @@ -416,7 +442,7 @@ declare module 'vscode-xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; + getOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell'): boolean; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -461,7 +487,7 @@ declare module 'vscode-xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; + setOption(key: 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'debug' | 'disableStdin' | 'enableBold' | 'macOptionIsMeta' | 'popOnBell' | 'screenKeys' | 'useFlowControl' | 'visualBell', value: boolean): void; /** * Sets an option on the terminal. * @param key The option key. diff --git a/src/typings/windows-mutex.ts b/src/typings/windows-mutex.ts index 039dffcc2ad..a3acc8f4430 100644 --- a/src/typings/windows-mutex.ts +++ b/src/typings/windows-mutex.ts @@ -9,4 +9,6 @@ declare module 'windows-mutex' { isActive(): boolean; release(): void; } + + export function isActive(name: string): boolean; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index c6ed333a2e4..2de68902c7c 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -7,7 +7,7 @@ import 'vs/css!./list'; import { IDisposable } from 'vs/base/common/lifecycle'; import { range } from 'vs/base/common/arrays'; import { IDelegate, IRenderer, IListEvent } from './list'; -import { List, IListOptions, IListStyles } from './listWidget'; +import { List, IListStyles, IListOptions } from './listWidget'; import { IPagedModel } from 'vs/base/common/paging'; import Event, { mapEvent } from 'vs/base/common/event'; @@ -67,7 +67,7 @@ export class PagedList { container: HTMLElement, delegate: IDelegate, renderers: IPagedRenderer[], - options: IListOptions = {} // TODO@Joao: should be IListOptions + options: IListOptions = {} ) { const pagedRenderers = renderers.map(r => new PagedRenderer>(r, () => this.model)); this.list = new List(container, delegate, pagedRenderers, options); diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index afa154bc231..d1c7b582008 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -344,21 +344,23 @@ class KeyboardController implements IDisposable { } } -function isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { +export function isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; } -function isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { +export function isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { return event.browserEvent.shiftKey; } -function isSelectionChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { - return isSelectionSingleChangeEvent(event) || isSelectionRangeChangeEvent(event); -} +const DefaultMultipleSelectionContoller = { + isSelectionSingleChangeEvent, + isSelectionRangeChangeEvent +}; class MouseController implements IDisposable { private multipleSelectionSupport: boolean; + private multipleSelectionController: IMultipleSelectionController | undefined; private didJustPressContextMenuKey: boolean = false; private disposables: IDisposable[] = []; @@ -398,7 +400,11 @@ class MouseController implements IDisposable { private view: ListView, private options: IListOptions = {} ) { - this.multipleSelectionSupport = options.multipleSelectionSupport !== false; + this.multipleSelectionSupport = !(options.multipleSelectionSupport === false); + + if (this.multipleSelectionSupport) { + this.multipleSelectionController = options.multipleSelectionController || DefaultMultipleSelectionContoller; + } view.onMouseDown(this.onMouseDown, this, this.disposables); view.onMouseClick(this.onPointer, this, this.disposables); @@ -408,6 +414,26 @@ class MouseController implements IDisposable { Gesture.addTarget(view.domNode); } + private isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + if (this.multipleSelectionController) { + return this.multipleSelectionController.isSelectionSingleChangeEvent(event); + } + + return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; + } + + private isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + if (this.multipleSelectionController) { + return this.multipleSelectionController.isSelectionRangeChangeEvent(event); + } + + return event.browserEvent.shiftKey; + } + + private isSelectionChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + return this.isSelectionSingleChangeEvent(event) || this.isSelectionRangeChangeEvent(event); + } + private onMouseDown(e: IListMouseEvent | IListTouchEvent): void { if (this.options.focusOnMouseDown === false) { e.browserEvent.preventDefault(); @@ -419,14 +445,14 @@ class MouseController implements IDisposable { let reference = this.list.getFocus()[0]; reference = reference === undefined ? this.list.getSelection()[0] : reference; - if (this.multipleSelectionSupport && isSelectionRangeChangeEvent(e)) { + if (this.multipleSelectionSupport && this.isSelectionRangeChangeEvent(e)) { return this.changeSelection(e, reference); } const focus = e.index; this.list.setFocus([focus]); - if (this.multipleSelectionSupport && isSelectionChangeEvent(e)) { + if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return this.changeSelection(e, reference); } @@ -437,7 +463,7 @@ class MouseController implements IDisposable { } private onPointer(e: IListMouseEvent): void { - if (this.multipleSelectionSupport && isSelectionChangeEvent(e)) { + if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return; } @@ -449,7 +475,7 @@ class MouseController implements IDisposable { } private onDoubleClick(e: IListMouseEvent): void { - if (this.multipleSelectionSupport && isSelectionChangeEvent(e)) { + if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return; } @@ -461,7 +487,7 @@ class MouseController implements IDisposable { private changeSelection(e: IListMouseEvent | IListTouchEvent, reference: number | undefined): void { const focus = e.index; - if (isSelectionRangeChangeEvent(e) && reference !== undefined) { + if (this.isSelectionRangeChangeEvent(e) && reference !== undefined) { const min = Math.min(reference, focus); const max = Math.max(reference, focus); const rangeSelection = range(min, max + 1); @@ -475,7 +501,7 @@ class MouseController implements IDisposable { const newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange)); this.list.setSelection(newSelection); - } else if (isSelectionSingleChangeEvent(e)) { + } else if (this.isSelectionSingleChangeEvent(e)) { const selection = this.list.getSelection(); const newSelection = selection.filter(i => i !== focus); @@ -492,6 +518,11 @@ class MouseController implements IDisposable { } } +export interface IMultipleSelectionController { + isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean; + isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean; +} + export interface IListOptions extends IListViewOptions, IListStyles { identityProvider?: IIdentityProvider; ariaLabel?: string; @@ -501,6 +532,7 @@ export interface IListOptions extends IListViewOptions, IListStyles { keyboardSupport?: boolean; verticalScrollMode?: ScrollbarVisibility; multipleSelectionSupport?: boolean; + multipleSelectionController?: IMultipleSelectionController; } export interface IListStyles { @@ -664,6 +696,7 @@ export class List implements ISpliceable, IDisposable { private spliceable: ISpliceable; protected disposables: IDisposable[]; private styleElement: HTMLStyleElement; + private mouseController: MouseController; @memoize get onFocusChange(): Event> { return mapEvent(this.eventBufferer.wrapEvent(this.focus.onChange), e => this.toListEvent(e)); @@ -744,9 +777,9 @@ export class List implements ISpliceable, IDisposable { } if (typeof options.mouseSupport !== 'boolean' || options.mouseSupport) { - const controller = new MouseController(this, this.view, options); - this.disposables.push(controller); - this.onContextMenu = controller.onContextMenu; + this.mouseController = new MouseController(this, this.view, options); + this.disposables.push(this.mouseController); + this.onContextMenu = this.mouseController.onContextMenu; } this.onFocusChange(this._onFocusChange, this, this.disposables); diff --git a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts b/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts deleted file mode 100644 index 9f1e41502d2..00000000000 --- a/src/vs/base/browser/ui/resourceviewer/resourceViewer.ts +++ /dev/null @@ -1,243 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import 'vs/css!./resourceviewer'; -import nls = require('vs/nls'); -import mimes = require('vs/base/common/mime'); -import URI from 'vs/base/common/uri'; -import paths = require('vs/base/common/paths'); -import { Builder, $ } from 'vs/base/browser/builder'; -import DOM = require('vs/base/browser/dom'); -import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; -import { LRUCache } from 'vs/base/common/map'; -import { Schemas } from 'vs/base/common/network'; - -interface MapExtToMediaMimes { - [index: string]: string; -} - -// Known media mimes that we can handle -const mapExtToMediaMimes: MapExtToMediaMimes = { - '.bmp': 'image/bmp', - '.gif': 'image/gif', - '.jpg': 'image/jpg', - '.jpeg': 'image/jpg', - '.jpe': 'image/jpg', - '.png': 'image/png', - '.tiff': 'image/tiff', - '.tif': 'image/tiff', - '.ico': 'image/x-icon', - '.tga': 'image/x-tga', - '.psd': 'image/vnd.adobe.photoshop', - '.webp': 'image/webp', - '.mid': 'audio/midi', - '.midi': 'audio/midi', - '.mp4a': 'audio/mp4', - '.mpga': 'audio/mpeg', - '.mp2': 'audio/mpeg', - '.mp2a': 'audio/mpeg', - '.mp3': 'audio/mpeg', - '.m2a': 'audio/mpeg', - '.m3a': 'audio/mpeg', - '.oga': 'audio/ogg', - '.ogg': 'audio/ogg', - '.spx': 'audio/ogg', - '.aac': 'audio/x-aac', - '.wav': 'audio/x-wav', - '.wma': 'audio/x-ms-wma', - '.mp4': 'video/mp4', - '.mp4v': 'video/mp4', - '.mpg4': 'video/mp4', - '.mpeg': 'video/mpeg', - '.mpg': 'video/mpeg', - '.mpe': 'video/mpeg', - '.m1v': 'video/mpeg', - '.m2v': 'video/mpeg', - '.ogv': 'video/ogg', - '.qt': 'video/quicktime', - '.mov': 'video/quicktime', - '.webm': 'video/webm', - '.mkv': 'video/x-matroska', - '.mk3d': 'video/x-matroska', - '.mks': 'video/x-matroska', - '.wmv': 'video/x-ms-wmv', - '.flv': 'video/x-flv', - '.avi': 'video/x-msvideo', - '.movie': 'video/x-sgi-movie' -}; - -export interface IResourceDescriptor { - resource: URI; - name: string; - size: number; - etag: string; - mime: string; -} - -// Chrome is caching images very aggressively and so we use the ETag information to find out if -// we need to bypass the cache or not. We could always bypass the cache everytime we show the image -// however that has very bad impact on memory consumption because each time the image gets shown, -// memory grows (see also https://github.com/electron/electron/issues/6275) -const IMAGE_RESOURCE_ETAG_CACHE = new LRUCache(100); -function imageSrc(descriptor: IResourceDescriptor): string { - if (descriptor.resource.scheme === Schemas.data) { - return descriptor.resource.toString(true /* skip encoding */); - } - - const src = descriptor.resource.toString(); - - let cached = IMAGE_RESOURCE_ETAG_CACHE.get(src); - if (!cached) { - cached = { etag: descriptor.etag, src }; - IMAGE_RESOURCE_ETAG_CACHE.set(src, cached); - } - - if (cached.etag !== descriptor.etag) { - cached.etag = descriptor.etag; - cached.src = `${src}?${Date.now()}`; // bypass cache with this trick - } - - return cached.src; -} - -/** - * Helper to actually render the given resource into the provided container. Will adjust scrollbar (if provided) automatically based on loading - * progress of the binary resource. - */ -export class ResourceViewer { - - private static readonly KB = 1024; - private static readonly MB = ResourceViewer.KB * ResourceViewer.KB; - private static readonly GB = ResourceViewer.MB * ResourceViewer.KB; - private static readonly TB = ResourceViewer.GB * ResourceViewer.KB; - - private static readonly MAX_IMAGE_SIZE = ResourceViewer.MB; // showing images inline is memory intense, so we have a limit - - public static show( - descriptor: IResourceDescriptor, - container: Builder, - scrollbar: DomScrollableElement, - openExternal: (uri: URI) => void, - metadataClb?: (meta: string) => void - ): void { - - // Ensure CSS class - $(container).setClass('monaco-resource-viewer'); - - // Lookup media mime if any - let mime = descriptor.mime; - if (!mime && descriptor.resource.scheme === Schemas.file) { - const ext = paths.extname(descriptor.resource.toString()); - if (ext) { - mime = mapExtToMediaMimes[ext.toLowerCase()]; - } - } - - if (!mime) { - mime = mimes.MIME_BINARY; - } - - // Show Image inline unless they are large - if (mime.indexOf('image/') >= 0) { - if (ResourceViewer.inlineImage(descriptor)) { - $(container) - .empty() - .addClass('image') - .img({ src: imageSrc(descriptor) }) - .on(DOM.EventType.LOAD, (e, img) => { - const imgElement = img.getHTMLElement(); - if (imgElement.naturalWidth > imgElement.width || imgElement.naturalHeight > imgElement.height) { - $(container).addClass('oversized'); - - img.on(DOM.EventType.CLICK, (e, img) => { - $(container).toggleClass('full-size'); - - scrollbar.scanDomNode(); - }); - } - - if (metadataClb) { - metadataClb(nls.localize('imgMeta', "{0}x{1} {2}", imgElement.naturalWidth, imgElement.naturalHeight, ResourceViewer.formatSize(descriptor.size))); - } - - scrollbar.scanDomNode(); - }); - } else { - const imageContainer = $(container) - .empty() - .p({ - text: nls.localize('largeImageError', "The image is too large to display in the editor. ") - }); - - if (descriptor.resource.scheme !== Schemas.data) { - imageContainer.append($('a', { - role: 'button', - class: 'open-external', - text: nls.localize('resourceOpenExternalButton', "Open image using external program?") - }).on(DOM.EventType.CLICK, (e) => { - openExternal(descriptor.resource); - })); - } - } - } - - // Handle generic Binary Files - else { - $(container) - .empty() - .span({ - text: nls.localize('nativeBinaryError', "The file will not be displayed in the editor because it is either binary, very large or uses an unsupported text encoding.") - }); - - if (metadataClb) { - metadataClb(ResourceViewer.formatSize(descriptor.size)); - } - - scrollbar.scanDomNode(); - } - } - - private static inlineImage(descriptor: IResourceDescriptor): boolean { - let skipInlineImage: boolean; - - // Data URI - if (descriptor.resource.scheme === Schemas.data) { - const BASE64_MARKER = 'base64,'; - const base64MarkerIndex = descriptor.resource.path.indexOf(BASE64_MARKER); - const hasData = base64MarkerIndex >= 0 && descriptor.resource.path.substring(base64MarkerIndex + BASE64_MARKER.length).length > 0; - - skipInlineImage = !hasData || descriptor.size > ResourceViewer.MAX_IMAGE_SIZE || descriptor.resource.path.length > ResourceViewer.MAX_IMAGE_SIZE; - } - - // File URI - else { - skipInlineImage = typeof descriptor.size !== 'number' || descriptor.size > ResourceViewer.MAX_IMAGE_SIZE; - } - - return !skipInlineImage; - } - - private static formatSize(size: number): string { - if (size < ResourceViewer.KB) { - return nls.localize('sizeB', "{0}B", size); - } - - if (size < ResourceViewer.MB) { - return nls.localize('sizeKB', "{0}KB", (size / ResourceViewer.KB).toFixed(2)); - } - - if (size < ResourceViewer.GB) { - return nls.localize('sizeMB', "{0}MB", (size / ResourceViewer.MB).toFixed(2)); - } - - if (size < ResourceViewer.TB) { - return nls.localize('sizeGB', "{0}GB", (size / ResourceViewer.GB).toFixed(2)); - } - - return nls.localize('sizeTB', "{0}TB", (size / ResourceViewer.TB).toFixed(2)); - } -} diff --git a/src/vs/base/browser/ui/splitview/grid.ts b/src/vs/base/browser/ui/splitview/grid.ts new file mode 100644 index 00000000000..fd0c585ff11 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/grid.ts @@ -0,0 +1,149 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import Event, { anyEvent } from 'vs/base/common/event'; +import { Orientation } from 'vs/base/browser/ui/sash/sash'; +import { append, $ } from 'vs/base/browser/dom'; +import { SplitView, IView } from 'vs/base/browser/ui/splitview/splitview'; +export { Orientation } from 'vs/base/browser/ui/sash/sash'; + +export class GridNode implements IView { + + get minimumSize(): number { + let result = 0; + + for (const child of this.children) { + for (const grandchild of child.children) { + result += grandchild.minimumSize; + } + } + + return result === 0 ? 50 : result; + } + + readonly maximumSize = Number.MAX_VALUE; + + private _onDidChange: Event = Event.None; + get onDidChange(): Event { + return this._onDidChange; + } + + protected orientation: Orientation | undefined; + protected size: number | undefined; + protected orthogonalSize: number | undefined; + private splitview: SplitView | undefined; + private children: GridNode[] = []; + private color: string | undefined; + + constructor(private parent?: GridNode, orthogonalSize?: number, color?: string) { + this.orthogonalSize = orthogonalSize; + this.color = color || `hsl(${Math.round(Math.random() * 360)}, 72%, 72%)`; + } + + render(container: HTMLElement): void { + container = append(container, $('.node')); + container.style.backgroundColor = this.color; + + append(container, $('.action', { onclick: () => this.split(container, Orientation.HORIZONTAL) }, '⬌')); + append(container, $('.action', { onclick: () => this.split(container, Orientation.VERTICAL) }, '⬍')); + } + + protected split(container: HTMLElement, orientation: Orientation): void { + if (this.parent && this.parent.orientation === orientation) { + const index = this.parent.children.indexOf(this); + this.parent.addChild(this.size / 2, this.orthogonalSize, index + 1); + } else { + this.branch(container, orientation); + } + } + + protected branch(container: HTMLElement, orientation: Orientation): void { + this.orientation = orientation; + container.innerHTML = ''; + + this.splitview = new SplitView(container, { orientation }); + this.layout(this.size); + this.orthogonalLayout(this.orthogonalSize); + + this.addChild(this.orthogonalSize / 2, this.size, 0, this.color); + this.addChild(this.orthogonalSize / 2, this.size); + } + + layout(size: number): void { + this.size = size; + + for (const child of this.children) { + child.orthogonalLayout(size); + } + } + + orthogonalLayout(size: number): void { + this.orthogonalSize = size; + + if (this.splitview) { + this.splitview.layout(size); + } + } + + private addChild(size: number, orthogonalSize: number, index?: number, color?: string): void { + const child = new GridNode(this, orthogonalSize, color); + this.splitview.addView(child, size, index); + + if (typeof index === 'number') { + this.children.splice(index, 0, child); + } else { + this.children.push(child); + } + + this._onDidChange = anyEvent(...this.children.map(c => c.onDidChange)); + } +} + +export class RootGridNode extends GridNode { + + private width: number; + private height: number; + + protected branch(container: HTMLElement, orientation: Orientation): void { + if (orientation === Orientation.VERTICAL) { + this.size = this.width; + this.orthogonalSize = this.height; + } else { + this.size = this.height; + this.orthogonalSize = this.width; + } + + super.branch(container, orientation); + } + + layoutBox(width: number, height: number): void { + if (this.orientation === Orientation.VERTICAL) { + this.layout(width); + this.orthogonalLayout(height); + } else if (this.orientation === Orientation.HORIZONTAL) { + this.layout(height); + this.orthogonalLayout(width); + } else { + this.width = width; + this.height = height; + } + } +} + +export class Grid { + + private root: RootGridNode; + + constructor(container: HTMLElement) { + this.root = new RootGridNode(); + this.root.render(container); + } + + layout(width: number, height: number): void { + this.root.layoutBox(width, height); + } +} diff --git a/src/vs/base/browser/ui/splitview/splitview.css b/src/vs/base/browser/ui/splitview/splitview.css index 41d3de5c826..045645a3f68 100644 --- a/src/vs/base/browser/ui/splitview/splitview.css +++ b/src/vs/base/browser/ui/splitview/splitview.css @@ -20,4 +20,5 @@ .monaco-split-view2.horizontal > .split-view-view { height: 100%; + display: inline-block; } diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index 9c6657154b8..833a2180803 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -161,7 +161,7 @@ export class SplitView implements IDisposable { } view.render(container, this.orientation); - this.relayout(); + this.relayout(index); this.state = State.Idle; } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index dee1ce7c360..93c6dda80c2 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -255,7 +255,7 @@ export class ThrottledDelayer extends Delayer> { this.throttler = new Throttler(); } - trigger(promiseFactory: ITask>, delay?: number): Promise { + trigger(promiseFactory: ITask>, delay?: number): TPromise { return super.trigger(() => this.throttler.queue(promiseFactory), delay); } } diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index 92568a683f7..d5bec85ebaf 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -576,7 +576,7 @@ export function fuzzyScore(pattern: string, word: string, patternMaxWhitespaceIg _matchesCount = 0; _topScore = -100; _patternStartPos = patternStartPos; - _findAllMatches(patternLen, wordLen, 0, new LazyArray(), false); + _findAllMatches(patternLen, wordLen, patternLen === wordLen ? 1 : 0, new LazyArray(), false); if (_matchesCount === 0) { return undefined; diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index 7314589644a..451a01bb666 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -220,8 +220,12 @@ function parseRegExp(pattern: string): string { } } - // Tail: Add the slash we had split on if there is more to come and the next one is not a globstar - if (index < segments.length - 1 && segments[index + 1] !== GLOBSTAR) { + // Tail: Add the slash we had split on if there is more to come and the remaining pattern is not a globstar + // For example if pattern: some/**/*.js we want the "/" after some to be included in the RegEx to prevent + // a folder called "something" to match as well. + // However, if pattern: some/**, we tolerate that we also match on "something" because our globstar behaviour + // is to match 0-N segments. + if (index < segments.length - 1 && (segments[index + 1] !== GLOBSTAR || index + 2 < segments.length)) { regEx += PATH_REGEX; } diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 3012d4a5b15..bbc5c6ca223 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -38,8 +38,13 @@ export function isEqual(first: uri, second: uri, ignoreCase?: boolean): boolean } export function dirname(resource: uri): uri { + const dirname = paths.dirname(resource.path); + if (resource.authority && dirname && !paths.isAbsolute(dirname)) { + return null; // If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character + } + return resource.with({ - path: paths.dirname(resource.path) + path: dirname }); } diff --git a/src/vs/base/node/encoding.ts b/src/vs/base/node/encoding.ts index 4177f3ffab5..1d134c65767 100644 --- a/src/vs/base/node/encoding.ts +++ b/src/vs/base/node/encoding.ts @@ -28,11 +28,11 @@ export function bomLength(encoding: string): number { return 0; } -export function decode(buffer: NodeBuffer, encoding: string, options?: any): string { - return iconv.decode(buffer, toNodeEncoding(encoding), options); +export function decode(buffer: NodeBuffer, encoding: string): string { + return iconv.decode(buffer, toNodeEncoding(encoding)); } -export function encode(content: string, encoding: string, options?: any): NodeBuffer { +export function encode(content: string, encoding: string, options?: { addBOM?: boolean }): NodeBuffer { return iconv.encode(content, toNodeEncoding(encoding), options); } @@ -44,6 +44,10 @@ export function decodeStream(encoding: string): NodeJS.ReadWriteStream { return iconv.decodeStream(toNodeEncoding(encoding)); } +export function encodeStream(encoding: string, options?: { addBOM?: boolean }): NodeJS.ReadWriteStream { + return iconv.encodeStream(toNodeEncoding(encoding), options); +} + function toNodeEncoding(enc: string): string { if (enc === UTF8_with_bom) { return UTF8; // iconv does not distinguish UTF 8 with or without BOM, so we need to help it diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts index b3a4121079e..963a9a3905e 100644 --- a/src/vs/base/node/extfs.ts +++ b/src/vs/base/node/extfs.ts @@ -54,7 +54,7 @@ export function copy(source: string, target: string, callback: (error: Error) => } if (!stat.isDirectory()) { - return pipeFs(source, target, stat.mode & 511, callback); + return doCopyFile(source, target, stat.mode & 511, callback); } if (copiedSources[source]) { @@ -75,6 +75,38 @@ export function copy(source: string, target: string, callback: (error: Error) => }); } +function doCopyFile(source: string, target: string, mode: number, callback: (error: Error) => void): void { + const reader = fs.createReadStream(source); + const writer = fs.createWriteStream(target, { mode }); + + let finished = false; + const finish = (error?: Error) => { + if (!finished) { + finished = true; + + // in error cases, pass to callback + if (error) { + callback(error); + } + + // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104 + else { + fs.chmod(target, mode, callback); + } + } + }; + + // handle errors properly + reader.once('error', error => finish(error)); + writer.once('error', error => finish(error)); + + // we are done (underlying fd has been closed) + writer.once('close', () => finish()); + + // start piping + reader.pipe(writer); +} + export function mkdirp(path: string, mode?: number): TPromise { const mkdir = () => nfcall(fs.mkdir, path, mode) .then(null, (err: NodeJS.ErrnoException) => { @@ -88,11 +120,12 @@ export function mkdirp(path: string, mode?: number): TPromise { return TPromise.wrapError(err); }); - // is root? + // stop at root if (path === paths.dirname(path)) { return TPromise.as(true); } + // recursively mkdir return mkdir().then(null, (err: NodeJS.ErrnoException) => { if (err.code === 'ENOENT') { return mkdirp(paths.dirname(path), mode).then(mkdir); @@ -102,40 +135,6 @@ export function mkdirp(path: string, mode?: number): TPromise { }); } -function pipeFs(source: string, target: string, mode: number, callback: (error: Error) => void): void { - let callbackHandled = false; - - const readStream = fs.createReadStream(source); - const writeStream = fs.createWriteStream(target, { mode: mode }); - - const onError = (error: Error) => { - if (!callbackHandled) { - callbackHandled = true; - callback(error); - } - }; - - readStream.on('error', onError); - writeStream.on('error', onError); - - readStream.on('end', () => { - (writeStream).end(() => { // In this case the write stream is known to have an end signature with callback - if (!callbackHandled) { - callbackHandled = true; - - fs.chmod(target, mode, callback); // we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104 - } - }); - }); - - // In node 0.8 there is no easy way to find out when the pipe operation has finished. As such, we use the end property = false - // so that we are in charge of calling end() on the write stream and we will be notified when the write stream is really done. - // We can do this because file streams have an end() method that allows to pass in a callback. - // In node 0.10 there is an event 'finish' emitted from the write stream that can be used. See - // https://groups.google.com/forum/?fromgroups=#!topic/nodejs/YWQ1sRoXOdI - readStream.pipe(writeStream, { end: false }); -} - // Deletes the given path by first moving it out of the workspace. This has two benefits. For one, the operation can return fast because // after the rename, the contents are out of the workspace although not yet deleted. The greater benefit however is that this operation // will fail in case any file is used by another process. fs.unlink() in node will not bail if a file unlinked is used by another process. @@ -320,15 +319,101 @@ export function mv(source: string, target: string, callback: (error: Error) => v }); } +let canFlush = true; +export function writeFileAndFlush(path: string, data: string | NodeBuffer | NodeJS.ReadableStream, options: { mode?: number; flag?: string; }, callback: (error?: Error) => void): void { + options = ensureOptions(options); + + if (typeof data === 'string' || Buffer.isBuffer(data)) { + doWriteFileAndFlush(path, data, options, callback); + } else { + doWriteFileStreamAndFlush(path, data, options, callback); + } +} + +function doWriteFileStreamAndFlush(path: string, reader: NodeJS.ReadableStream, options: { mode?: number; flag?: string; }, callback: (error?: Error) => void): void { + + // finish only once + let finished = false; + const finish = (error?: Error) => { + if (!finished) { + finished = true; + + // in error cases we need to manually close streams + // if the write stream was successfully opened + if (error) { + if (isOpen) { + writer.once('close', () => callback(error)); + writer.close(); + } else { + callback(error); + } + } + + // otherwise just return without error + else { + callback(); + } + } + }; + + // create writer to target. we set autoClose: false because we want to use the streams + // file descriptor to call fs.fdatasync to ensure the data is flushed to disk + const writer = fs.createWriteStream(path, { mode: options.mode, flags: options.flag, autoClose: false }); + + // Event: 'open' + // Purpose: save the fd for later use + // Notes: will not be called when there is an error opening the file descriptor! + let fd: number; + let isOpen: boolean; + writer.once('open', descriptor => { + fd = descriptor; + isOpen = true; + }); + + // Event: 'error' + // Purpose: to return the error to the outside and to close the write stream (does not happen automatically) + reader.once('error', error => finish(error)); + writer.once('error', error => finish(error)); + + // Event: 'finish' + // Purpose: use fs.fdatasync to flush the contents to disk + // Notes: event is called when the writer has finished writing to the underlying resource. we must call writer.close() + // because we have created the WriteStream with autoClose: false + writer.once('finish', () => { + + // flush to disk + if (canFlush && isOpen) { + fs.fdatasync(fd, (syncError: Error) => { + + // In some exotic setups it is well possible that node fails to sync + // In that case we disable flushing and warn to the console + if (syncError) { + console.warn('[node.js fs] fdatasync is now disabled for this session because it failed: ', syncError); + canFlush = false; + } + + writer.close(); + }); + } else { + writer.close(); + } + }); + + // Event: 'close' + // Purpose: signal we are done to the outside + // Notes: event is called when the writer's filedescriptor is closed + writer.once('close', () => finish()); + + // start data piping + reader.pipe(writer); +} + // Calls fs.writeFile() followed by a fs.sync() call to flush the changes to disk // We do this in cases where we want to make sure the data is really on disk and // not in some cache. // // See https://github.com/nodejs/node/blob/v5.10.0/lib/fs.js#L1194 -let canFlush = true; -export function writeFileAndFlush(path: string, data: string | NodeBuffer, options: { mode?: number; flag?: string; }, callback: (error: Error) => void): void { - options = ensureOptions(options); - +function doWriteFileAndFlush(path: string, data: string | NodeBuffer, options: { mode?: number; flag?: string; }, callback: (error?: Error) => void): void { if (!canFlush) { return fs.writeFile(path, data, options, callback); } diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index b949384de1e..9ebc819fd02 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -101,6 +101,7 @@ const writeFilePathQueue: { [path: string]: Queue } = Object.create(null); export function writeFile(path: string, data: string, options?: { mode?: number; flag?: string; }): TPromise; export function writeFile(path: string, data: NodeBuffer, options?: { mode?: number; flag?: string; }): TPromise; +export function writeFile(path: string, data: NodeJS.ReadableStream, options?: { mode?: number; flag?: string; }): TPromise; export function writeFile(path: string, data: any, options?: { mode?: number; flag?: string; }): TPromise { let queueKey = toQueueKey(path); diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index a6fe1a58b1a..bc330457fa8 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -393,11 +393,11 @@ suite('Filters', () => { // issue #17836 // assertTopScore(fuzzyScore, 'TEdit', 1, 'TextEditorDecorationType', 'TextEdit', 'TextEditor'); - assertTopScore(fuzzyScore, 'p', 0, 'parse', 'posix', 'pafdsa', 'path', 'p'); + assertTopScore(fuzzyScore, 'p', 4, 'parse', 'posix', 'pafdsa', 'path', 'p'); assertTopScore(fuzzyScore, 'pa', 0, 'parse', 'pafdsa', 'path'); // issue #14583 - assertTopScore(fuzzyScore, 'log', 3, 'HTMLOptGroupElement', 'ScrollLogicalPosition', 'SVGFEMorphologyElement', 'log'); + assertTopScore(fuzzyScore, 'log', 3, 'HTMLOptGroupElement', 'ScrollLogicalPosition', 'SVGFEMorphologyElement', 'log', 'logger'); assertTopScore(fuzzyScore, 'e', 2, 'AbstractWorker', 'ActiveXObject', 'else'); // issue #14446 @@ -415,6 +415,8 @@ suite('Filters', () => { assertTopScore(fuzzyScore, 'is', 0, 'isValidViewletId', 'import statement'); assertTopScore(fuzzyScore, 'title', 1, 'files.trimTrailingWhitespace', 'window.title'); + + assertTopScore(fuzzyScore, 'const', 1, 'constructor', 'const', 'cuOnstrul'); }); test('Unexpected suggestion scoring, #28791', function () { diff --git a/src/vs/base/test/common/resources.test.ts b/src/vs/base/test/common/resources.test.ts index f9275777a53..e29e625f4c7 100644 --- a/src/vs/base/test/common/resources.test.ts +++ b/src/vs/base/test/common/resources.test.ts @@ -6,7 +6,8 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; -import { distinctParents } from 'vs/base/common/resources'; +import { distinctParents, dirname } from 'vs/base/common/resources'; +import { normalize } from 'vs/base/common/paths'; suite('Resources', () => { @@ -40,4 +41,14 @@ suite('Resources', () => { assert.equal(distinct[1].toString(), resources[3].toString()); assert.equal(distinct[2].toString(), resources[4].toString()); }); + + test('dirname', (done) => { + const f = URI.file('/some/file/test.txt'); + const d = dirname(f); + assert.equal(d.fsPath, normalize('/some/file', true)); + + // does not explode (https://github.com/Microsoft/vscode/issues/41987) + dirname(URI.from({ scheme: 'file', authority: '/users/someone/portal.h' })); + done(); + }); }); \ No newline at end of file diff --git a/src/vs/base/test/node/extfs/extfs.test.ts b/src/vs/base/test/node/extfs/extfs.test.ts index 06ecf0b8ba0..f521abbfd01 100644 --- a/src/vs/base/test/node/extfs/extfs.test.ts +++ b/src/vs/base/test/node/extfs/extfs.test.ts @@ -15,6 +15,8 @@ import uuid = require('vs/base/common/uuid'); import strings = require('vs/base/common/strings'); import extfs = require('vs/base/node/extfs'); import { onError } from 'vs/base/test/common/utils'; +import { Readable } from 'stream'; +import { isLinux } from 'vs/base/common/platform'; const ignore = () => { }; @@ -22,6 +24,38 @@ const mkdirp = (path: string, mode: number, callback: (error) => void) => { extfs.mkdirp(path, mode).done(() => callback(null), error => callback(error)); }; +const chunkSize = 64 * 1024; +const readError = 'Error while reading'; +function toReadable(value: string, throwError?: boolean): Readable { + const totalChunks = Math.ceil(value.length / chunkSize); + const stringChunks: string[] = []; + + for (let i = 0, j = 0; i < totalChunks; ++i, j += chunkSize) { + stringChunks[i] = value.substr(j, chunkSize); + } + + let counter = 0; + return new Readable({ + read: function () { + if (throwError) { + this.emit('error', new Error(readError)); + } + + let res: string; + let canPush = true; + while (canPush && (res = stringChunks[counter++])) { + canPush = this.push(res); + } + + // EOS + if (!res) { + this.push(null); + } + }, + encoding: 'utf8' + }); +} + suite('Extfs', () => { test('mkdirp', function (done: () => void) { @@ -174,7 +208,7 @@ suite('Extfs', () => { } }); - test('writeFileAndFlush', function (done: () => void) { + test('writeFileAndFlush (string)', function (done: () => void) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); const newDir = path.join(parentDir, 'extfs', id); @@ -209,6 +243,196 @@ suite('Extfs', () => { }); }); + test('writeFileAndFlush (stream)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => { + if (error) { + return onError(error, done); + } + + assert.equal(fs.readFileSync(testFile), 'Hello World'); + + const largeString = (new Array(100 * 1024)).join('Large String\n'); + + extfs.writeFileAndFlush(testFile, toReadable(largeString), null, error => { + if (error) { + return onError(error, done); + } + + assert.equal(fs.readFileSync(testFile), largeString); + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + }); + + test('writeFileAndFlush (file stream)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const sourceFile = require.toUrl('./fixtures/index.html'); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => { + if (error) { + return onError(error, done); + } + + assert.equal(fs.readFileSync(testFile).toString(), fs.readFileSync(sourceFile).toString()); + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + + test('writeFileAndFlush (string, error handling)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + extfs.writeFileAndFlush(testFile, 'Hello World', null, error => { + if (!error) { + return onError(new Error('Expected error for writing to readonly file'), done); + } + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + + test('writeFileAndFlush (stream, error handling EISDIR)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => { + if (!error || (error).code !== 'EISDIR') { + return onError(new Error('Expected EISDIR error for writing to folder but got: ' + (error ? (error).code : 'no error')), done); + } + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + + test('writeFileAndFlush (stream, error handling READERROR)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + extfs.writeFileAndFlush(testFile, toReadable('Hello World', true /* throw error */), null, error => { + if (!error || error.message !== readError) { + return onError(new Error('Expected error for writing to folder'), done); + } + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + + test('writeFileAndFlush (stream, error handling EACCES)', function (done: () => void) { + if (isLinux) { + return done(); // somehow this test fails on Linux in our TFS builds + } + + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + fs.writeFileSync(testFile, ''); + fs.chmodSync(testFile, 33060); // make readonly + + extfs.writeFileAndFlush(testFile, toReadable('Hello World'), null, error => { + if (!error || !((error).code !== 'EACCES' || (error).code !== 'EPERM')) { + return onError(new Error('Expected EACCES/EPERM error for writing to folder but got: ' + (error ? (error).code : 'no error')), done); + } + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + + test('writeFileAndFlush (file stream, error handling)', function (done: () => void) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const sourceFile = require.toUrl('./fixtures/index.html'); + const newDir = path.join(parentDir, 'extfs', id); + const testFile = path.join(newDir, 'flushed.txt'); + + mkdirp(newDir, 493, error => { + if (error) { + return onError(error, done); + } + + assert.ok(fs.existsSync(newDir)); + + fs.mkdirSync(testFile); // this will trigger an error because testFile is now a directory! + + extfs.writeFileAndFlush(testFile, fs.createReadStream(sourceFile), null, error => { + if (!error) { + return onError(new Error('Expected error for writing to folder'), done); + } + + extfs.del(parentDir, os.tmpdir(), done, ignore); + }); + }); + }); + test('writeFileAndFlushSync', function (done: () => void) { const id = uuid.generateUuid(); const parentDir = path.join(os.tmpdir(), 'vsctests', id); diff --git a/src/vs/base/test/node/glob.test.ts b/src/vs/base/test/node/glob.test.ts index 25dc9c517a6..df770c9c862 100644 --- a/src/vs/base/test/node/glob.test.ts +++ b/src/vs/base/test/node/glob.test.ts @@ -301,6 +301,22 @@ suite('Glob', () => { assert(!glob.match(p, '/xpackage.json')); }); + test('issue 41724', function () { + let p = 'some/**/*.js'; + + assert(glob.match(p, 'some/foo.js')); + assert(glob.match(p, 'some/folder/foo.js')); + assert(!glob.match(p, 'something/foo.js')); + assert(!glob.match(p, 'something/folder/foo.js')); + + p = 'some/**/*'; + + assert(glob.match(p, 'some/foo.js')); + assert(glob.match(p, 'some/folder/foo.js')); + assert(!glob.match(p, 'something/foo.js')); + assert(!glob.match(p, 'something/folder/foo.js')); + }); + test('brace expansion', function () { let p = '*.{html,js}'; diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index f94e19b95b8..0293acbb5be 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -21,6 +21,7 @@ exports.collectModules= function() { createModuleDescription('vs/code/electron-main/main', []), createModuleDescription('vs/code/node/cli', []), createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']), - createModuleDescription('vs/code/electron-browser/sharedProcess/sharedProcessMain', []) + createModuleDescription('vs/code/electron-browser/sharedProcess/sharedProcessMain', []), + createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []) ]; }; \ No newline at end of file diff --git a/src/vs/code/electron-browser/issue/issueReporter.html b/src/vs/code/electron-browser/issue/issueReporter.html new file mode 100644 index 00000000000..695de78a4cb --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporter.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/vs/code/electron-browser/issue/issueReporter.js b/src/vs/code/electron-browser/issue/issueReporter.js new file mode 100644 index 00000000000..06cbab83f42 --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporter.js @@ -0,0 +1,144 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const path = require('path'); +const fs = require('fs'); +const remote = require('electron').remote; + +function parseURLQueryArgs() { + const search = window.location.search || ''; + + return search.split(/[?&]/) + .filter(function (param) { return !!param; }) + .map(function (param) { return param.split('='); }) + .filter(function (param) { return param.length === 2; }) + .reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {}); +} + +function createScript(src, onload) { + const script = document.createElement('script'); + script.src = src; + script.addEventListener('load', onload); + + const head = document.getElementsByTagName('head')[0]; + head.insertBefore(script, head.lastChild); +} + +function uriFromPath(_path) { + var pathName = path.resolve(_path).replace(/\\/g, '/'); + if (pathName.length > 0 && pathName.charAt(0) !== '/') { + pathName = '/' + pathName; + } + + return encodeURI('file://' + pathName); +} + +function readFile(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, 'utf8', function(err, data) { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + +function main() { + const args = parseURLQueryArgs(); + const configuration = JSON.parse(args['config'] || '{}') || {}; + + const extractKey = function (e) { + return [ + e.ctrlKey ? 'ctrl-' : '', + e.metaKey ? 'meta-' : '', + e.altKey ? 'alt-' : '', + e.shiftKey ? 'shift-' : '', + e.keyCode + ].join(''); + }; + + const TOGGLE_DEV_TOOLS_KB = (process.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I + const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R + + window.addEventListener('keydown', function (e) { + const key = extractKey(e); + if (key === TOGGLE_DEV_TOOLS_KB) { + remote.getCurrentWebContents().toggleDevTools(); + } else if (key === RELOAD_KB) { + remote.getCurrentWindow().reload(); + } + }); + + // Load the loader and start loading the workbench + const rootUrl = uriFromPath(configuration.appRoot) + '/out'; + + // Get the nls configuration into the process.env as early as possible. + var nlsConfig = { availableLanguages: {} }; + const config = process.env['VSCODE_NLS_CONFIG']; + if (config) { + process.env['VSCODE_NLS_CONFIG'] = config; + try { + nlsConfig = JSON.parse(config); + } catch (e) { /*noop*/ } + } + + if (nlsConfig._resolvedLanguagePackCoreLocation) { + let bundles = Object.create(null); + nlsConfig.loadBundle = function(bundle, language, cb) { + let result = bundles[bundle]; + if (result) { + cb(undefined, result); + return; + } + let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json'); + readFile(bundleFile).then(function (content) { + let json = JSON.parse(content); + bundles[bundle] = json; + cb(undefined, json); + }) + .catch(cb); + }; + } + + var locale = nlsConfig.availableLanguages['*'] || 'en'; + if (locale === 'zh-tw') { + locale = 'zh-Hant'; + } else if (locale === 'zh-cn') { + locale = 'zh-Hans'; + } + + window.document.documentElement.setAttribute('lang', locale); + + // In the bundled version the nls plugin is packaged with the loader so the NLS Plugins + // loads as soon as the loader loads. To be able to have pseudo translation + createScript(rootUrl + '/vs/loader.js', function () { + define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code + + window.MonacoEnvironment = {}; + + require.config({ + baseUrl: rootUrl, + 'vs/nls': nlsConfig, + nodeCachedDataDir: configuration.nodeCachedDataDir, + nodeModules: [/*BUILD->INSERT_NODE_MODULES*/] + }); + + if (nlsConfig.pseudo) { + require(['vs/nls'], function (nlsPlugin) { + nlsPlugin.setPseudoTranslation(nlsConfig.pseudo); + }); + } + + require(['vs/code/electron-browser/issue/issueReporterMain'], (issueReporter) => { + issueReporter.startup(configuration); + }); + }); +} + +main(); diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts new file mode 100644 index 00000000000..e851e2e65b1 --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -0,0 +1,463 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/css!./media/issueReporter'; +import { shell, ipcRenderer, webFrame, remote } from 'electron'; +import { localize } from 'vs/nls'; +import { $ } from 'vs/base/browser/dom'; +import * as collections from 'vs/base/common/collections'; +import * as browser from 'vs/base/browser/browser'; +import product from 'vs/platform/node/product'; +import pkg from 'vs/platform/node/package'; +import * as os from 'os'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser'; +import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; +import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows'; +import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; +import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; +import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc'; +import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { IssueReporterModel, IssueType } from 'vs/code/electron-browser/issue/issueReporterModel'; +import { IssueReporterData, IssueReporterStyles } from 'vs/platform/issue/common/issue'; +import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage'; +import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { debounce } from 'vs/base/common/decorators'; + +export interface IssueReporterConfiguration extends IWindowConfiguration { + data: IssueReporterData; +} + +export function startup(configuration: IssueReporterConfiguration) { + document.body.innerHTML = BaseHtml(); + const issueReporter = new IssueReporter(configuration); + + // workaround for flickering on page load as css is applied + setTimeout(() => { + issueReporter.render(); + document.body.style.display = 'block'; + }, 10); +} + +export class IssueReporter extends Disposable { + private environmentService: IEnvironmentService; + private telemetryService: ITelemetryService; + private issueReporterModel: IssueReporterModel; + + constructor(configuration: IssueReporterConfiguration) { + super(); + + this.initServices(configuration); + + this.issueReporterModel = new IssueReporterModel({ + issueType: IssueType.Bug, + includeSystemInfo: true, + includeWorkspaceInfo: true, + includeProcessInfo: true, + includeExtensions: true, + versionInfo: { + vscodeVersion: `${pkg.name} ${pkg.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`, + os: `${os.type()} ${os.arch()} ${os.release()}` + }, + extensionsDisabled: this.environmentService.disableExtensions + }); + + ipcRenderer.on('issueInfoResponse', (event, info) => { + this.issueReporterModel.update(info); + + this.updateAllBlocks(this.issueReporterModel.getData()); + + const submitButton = document.getElementById('github-submit-btn'); + submitButton.disabled = false; + submitButton.textContent = localize('previewOnGitHub', "Preview on GitHub"); + }); + + ipcRenderer.send('issueInfoRequest'); + + if (window.document.documentElement.lang !== 'en') { + show(document.getElementById('english')); + } + + this.setEventHandlers(); + this.applyZoom(configuration.data.zoomLevel); + this.applyStyles(configuration.data.styles); + this.handleExtensionData(configuration.data.enabledExtensions); + } + + render(): void { + this.renderBlocks(); + } + + private applyZoom(zoomLevel: number) { + webFrame.setZoomLevel(zoomLevel); + browser.setZoomFactor(webFrame.getZoomFactor()); + // See https://github.com/Microsoft/vscode/issues/26151 + // Cannot be trusted because the webFrame might take some time + // until it really applies the new zoom level + browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false); + } + + private applyStyles(styles: IssueReporterStyles) { + const styleTag = document.createElement('style'); + const content: string[] = []; + + if (styles.inputBackground) { + content.push(`input, textarea, select { background-color: ${styles.inputBackground}; }`); + } + + if (styles.inputBorder) { + content.push(`input, textarea, select { border: 1px solid ${styles.inputBorder}; }`); + } else { + content.push(`input, textarea, select { border: 1px solid transparent; }`); + } + + if (styles.inputForeground) { + content.push(`input, textarea, select { color: ${styles.inputForeground}; }`); + } + + if (styles.inputErrorBorder) { + content.push(`.invalid-input, .invalid-input:focus { border: 1px solid ${styles.inputErrorBorder} !important; }`); + content.push(`.validation-error { color: ${styles.inputErrorBorder}; }`); + } + + if (styles.inputActiveBorder) { + content.push(`input[type='text']:focus, textarea:focus, select:focus, summary:focus { border: 1px solid ${styles.inputActiveBorder}; outline-style: none; }`); + } + + if (styles.textLinkColor) { + content.push(`a { color: ${styles.textLinkColor}; }`); + } + + if (styles.buttonBackground) { + content.push(`button { background-color: ${styles.buttonBackground}; }`); + } + + if (styles.buttonForeground) { + content.push(`button { color: ${styles.buttonForeground}; }`); + } + + if (styles.buttonHoverBackground) { + content.push(`button:hover:enabled { background-color: ${styles.buttonHoverBackground}; }`); + } + + if (styles.textLinkColor) { + content.push(`a { color: ${styles.textLinkColor}; }`); + } + + styleTag.innerHTML = content.join('\n'); + document.head.appendChild(styleTag); + document.body.style.color = styles.color; + } + + private handleExtensionData(extensions: ILocalExtension[]) { + const { nonThemes, themes } = collections.groupBy(extensions, ext => { + const manifestKeys = ext.manifest.contributes ? Object.keys(ext.manifest.contributes) : []; + const onlyTheme = !ext.manifest.activationEvents && manifestKeys.length === 1 && manifestKeys[0] === 'themes'; + return onlyTheme ? 'themes' : 'nonThemes'; + }); + + const numberOfThemeExtesions = themes && themes.length; + this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes }); + this.updateExtensionTable(nonThemes, numberOfThemeExtesions); + } + + private initServices(configuration: IWindowConfiguration): void { + const serviceCollection = new ServiceCollection(); + const mainProcessClient = new ElectronIPCClient(String(`window${configuration.windowId}`)); + + const windowsChannel = mainProcessClient.getChannel('windows'); + serviceCollection.set(IWindowsService, new WindowsChannelClient(windowsChannel)); + this.environmentService = new EnvironmentService(configuration, configuration.execPath); + + const sharedProcess = (serviceCollection.get(IWindowsService)).whenSharedProcessReady() + .then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${configuration.windowId}`)); + + const instantiationService = new InstantiationService(serviceCollection, true); + if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) { + const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender'))); + const appender = new TelemetryAppenderClient(channel); + const commonProperties = resolveCommonProperties(product.commit, pkg.version, configuration.machineId, this.environmentService.installSourcePath); + const piiPaths = [this.environmentService.appRoot, this.environmentService.extensionsPath]; + const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths }; + + const telemetryService = instantiationService.createInstance(TelemetryService, config); + this._register(telemetryService); + + this.telemetryService = telemetryService; + } else { + this.telemetryService = NullTelemetryService; + } + } + + private setEventHandlers(): void { + document.getElementById('issue-type').addEventListener('change', (event: Event) => { + this.issueReporterModel.update({ issueType: parseInt((event.target).value) }); + this.render(); + }); + + ['includeSystemInfo', 'includeProcessInfo', 'includeWorkspaceInfo', 'includeExtensions'].forEach(elementId => { + document.getElementById(elementId).addEventListener('click', (event: Event) => { + event.stopPropagation(); + this.issueReporterModel.update({ [elementId]: !this.issueReporterModel.getData()[elementId] }); + }); + }); + + document.getElementById('description').addEventListener('blur', (event: Event) => { + this.issueReporterModel.update({ issueDescription: (event.target).value }); + }); + + document.getElementById('issue-title').addEventListener('input', this.searchGitHub); + + document.getElementById('github-submit-btn').addEventListener('click', () => this.createIssue()); + + document.onkeydown = (e: KeyboardEvent) => { + if (e.shiftKey && e.keyCode === 13) { + // Close the window if the issue was successfully created + if (this.createIssue()) { + remote.getCurrentWindow().close(); + } + } + }; + } + + @debounce(300) + private searchGitHub(event: Event) { + const title = (event.target).value; + const similarIssues = document.getElementById('similar-issues'); + if (title) { + const query = `is:issue+repo:microsoft/vscode+${title}`; + window.fetch(`https://api.github.com/search/issues?q=${query}`).then((response) => { + response.json().then(result => { + similarIssues.innerHTML = ''; + if (result && result.items && result.items.length) { + const issues = $('ul'); + const issuesText = $('div.list-title'); + issuesText.textContent = localize('similarIssues', "Similar issues"); + + const { items } = result; + const numResultsToDisplay = items.length < 5 ? items.length : 5; + for (let i = 0; i < numResultsToDisplay; i++) { + const link = $('a', { href: items[i].html_url }); + link.textContent = items[i].title; + link.addEventListener('click', (event) => { + shell.openExternal((event.target).href); + }); + + const item = $('li', {}, link); + issues.appendChild(item); + } + + similarIssues.appendChild(issuesText); + similarIssues.appendChild(issues); + } + }); + }).catch((error) => { + console.log(error); + }); + } else { + similarIssues.innerHTML = ''; + } + } + + private renderBlocks(): void { + // Depending on Issue Type, we render different blocks and text + const { issueType } = this.issueReporterModel.getData(); + const systemBlock = document.querySelector('.block-system'); + const processBlock = document.querySelector('.block-process'); + const workspaceBlock = document.querySelector('.block-workspace'); + const extensionsBlock = document.querySelector('.block-extensions'); + + const descriptionTitle = document.getElementById('issue-description-label'); + const descriptionSubtitle = document.getElementById('issue-description-subtitle'); + + if (issueType === IssueType.Bug) { + show(systemBlock); + hide(processBlock); + hide(workspaceBlock); + show(extensionsBlock); + + descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} *`; + show(descriptionSubtitle); + descriptionSubtitle.innerHTML = localize('bugDescription', "How did you encounter this problem? Please provide clear steps to reproduce the problem during our investigation. What did you expect to happen and what actually did happen?"); + } else if (issueType === IssueType.PerformanceIssue) { + show(systemBlock); + show(processBlock); + show(workspaceBlock); + show(extensionsBlock); + + descriptionTitle.innerHTML = `${localize('stepsToReproduce', "Steps to Reproduce")} *`; + show(descriptionSubtitle); + descriptionSubtitle.innerHTML = localize('performanceIssueDesciption', "When did this performance issue happen? For example, does it occur on startup or after a specific series of actions? Any details you can provide help our investigation."); + } else { + hide(systemBlock); + hide(processBlock); + hide(workspaceBlock); + hide(extensionsBlock); + + descriptionTitle.innerHTML = `${localize('description', "Description")} *`; + hide(descriptionSubtitle); + } + } + + private validateInput(inputId: string): boolean { + const inputElement = (document.getElementById(inputId)); + if (!inputElement.value) { + show(document.getElementById(`${inputId}-validation-error`)); + inputElement.classList.add('invalid-input'); + return false; + } else { + hide(document.getElementById(`${inputId}-validation-error`)); + inputElement.classList.remove('invalid-input'); + return true; + } + } + + private validateInputs(): boolean { + let isValid = true; + ['issue-title', 'description'].forEach(elementId => { + isValid = this.validateInput(elementId) && isValid; + + }); + + return isValid; + } + + private createIssue(): boolean { + if (!this.validateInputs()) { + // If inputs are invalid, set focus to the first one and add listeners on them + // to detect further changes + (document.getElementsByClassName('invalid-input')[0]).focus(); + + document.getElementById('issue-title').addEventListener('input', (event) => { + this.validateInput('issue-title'); + }); + + document.getElementById('description').addEventListener('input', (event) => { + this.validateInput('description'); + }); + + return false; + } + + if (this.telemetryService) { + /* __GDPR__ + "issueReporterSubmit" : { + "issueType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('issueReporterSubmit', { issueType: this.issueReporterModel.getData().issueType }); + } + + const issueTitle = (document.getElementById('issue-title')).value; + const baseUrl = `https://github.com/microsoft/vscode/issues/new?title=${issueTitle}&body=`; + const issueBody = this.issueReporterModel.serialize(); + shell.openExternal(baseUrl + encodeURIComponent(issueBody)); + return true; + } + + /** + * Update blocks + */ + + private updateAllBlocks(state) { + this.updateSystemInfo(state); + this.updateProcessInfo(state); + this.updateWorkspaceInfo(state); + } + + private updateSystemInfo = (state) => { + const target = document.querySelector('.block-system .block-info'); + let tableHtml = ''; + Object.keys(state.systemInfo).forEach(k => { + tableHtml += ` + + ${k} + ${state.systemInfo[k]} + `; + }); + target.innerHTML = `${tableHtml}
`; + } + + private updateProcessInfo = (state) => { + const target = document.querySelector('.block-process .block-info'); + + let tableHtml = ` + + pid + CPU % + Memory (MB) + Name + `; + + state.processInfo.forEach(p => { + tableHtml += ` + + ${p.pid} + ${p.cpu} + ${p.memory} + ${p.name} + `; + }); + + target.innerHTML = `${tableHtml}
`; + } + + private updateWorkspaceInfo = (state) => { + document.querySelector('.block-workspace .block-info code').textContent = '\n' + state.workspaceInfo; + } + + private updateExtensionTable(extensions: ILocalExtension[], numThemeExtensions: number): void { + const target = document.querySelector('.block-extensions .block-info'); + + if (this.environmentService.disableExtensions) { + target.innerHTML = localize('disabledExtensions', "Extensions are disabled"); + return; + } + + const themeExclusionStr = numThemeExtensions ? `\n(${numThemeExtensions} theme extensions excluded)` : ''; + extensions = extensions || []; + + if (!extensions.length) { + target.innerHTML = 'Extensions: none' + themeExclusionStr; + return; + } + + let table = ` + + Extension + Author (truncated) + Version + `; + + extensions.forEach(extension => { + table += ` + + ${extension.manifest.name} + ${extension.manifest.publisher.substr(0, 3)} + ${extension.manifest.version} + `; + }); + + target.innerHTML = `${table}
${themeExclusionStr}`; + } +} + +// helper functions + +function hide(el) { + el.classList.add('hidden'); +} +function show(el) { + el.classList.remove('hidden'); +} diff --git a/src/vs/code/electron-browser/issue/issueReporterModel.ts b/src/vs/code/electron-browser/issue/issueReporterModel.ts new file mode 100644 index 00000000000..3da55c9d6cc --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporterModel.ts @@ -0,0 +1,188 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { assign } from 'vs/base/common/objects'; +import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; + +export enum IssueType { + Bug, + PerformanceIssue, + FeatureRequest +} + +export interface IssueReporterData { + issueType?: IssueType; + issueDescription?: string; + versionInfo?: any; + systemInfo?: any; + processInfo?: any; + workspaceInfo?: any; + includeSystemInfo?: boolean; + includeWorkspaceInfo?: boolean; + includeProcessInfo?: boolean; + includeExtensions?: boolean; + numberOfThemeExtesions?: number; + enabledNonThemeExtesions?: ILocalExtension[]; + extensionsDisabled?: boolean; +} + +export class IssueReporterModel { + private _data: IssueReporterData; + + constructor(initialData?: IssueReporterData) { + this._data = initialData || {}; + } + + getData(): IssueReporterData { + return this._data; + } + + update(newData: IssueReporterData): void { + assign(this._data, newData); + } + + serialize(): string { + return ` +### Issue Type +${this.getIssueTypeTitle()} + +### Description + +${this._data.issueDescription} + +### VS Code Info + +VS Code version: ${this._data.versionInfo && this._data.versionInfo.vscodeVersion} +OS version: ${this._data.versionInfo && this._data.versionInfo.os} + +${this.getInfos()} + + +`; + } + + private getIssueTypeTitle(): string { + if (this._data.issueType === IssueType.Bug) { + return 'Bug'; + } else if (this._data.issueType === IssueType.PerformanceIssue) { + return 'Performance Issue'; + } else { + return 'Feature Request'; + } + } + + private getInfos(): string { + let info = ''; + + if (this._data.includeSystemInfo) { + info += this.generateSystemInfoMd(); + } + + if (this._data.issueType === IssueType.Bug) { + if (this._data.includeExtensions) { + info += this.generateExtensionsMd(); + } + } + + if (this._data.issueType === IssueType.PerformanceIssue) { + + if (this._data.includeProcessInfo) { + info += this.generateProcessInfoMd(); + } + + if (this._data.includeWorkspaceInfo) { + info += this.generateWorkspaceInfoMd(); + } + + if (this._data.includeExtensions) { + info += this.generateExtensionsMd(); + } + } + + return info; + } + + private generateSystemInfoMd(): string { + let md = `
+System Info + +|Item|Value| +|---|---| +`; + + Object.keys(this._data.systemInfo).forEach(k => { + md += `|${k}|${this._data.systemInfo[k]}|\n`; + }); + + md += '\n
'; + + return md; + } + + private generateProcessInfoMd(): string { + let md = `
+Process Info + +|pid|CPU|Memory (MB)|Name| +|---|---|---|---| +`; + + this._data.processInfo.forEach(p => { + md += `|${p.pid}|${p.cpu}|${p.memory}|${p.name}|\n`; + }); + + md += '\n
'; + + return md; + } + + private generateWorkspaceInfoMd(): string { + return `
+Workspace Info + +\`\`\` +${this._data.workspaceInfo}; +\`\`\` + +
+`; + } + + private generateExtensionsMd(): string { + if (this._data.extensionsDisabled) { + return 'Extensions disabled'; + } + + const themeExclusionStr = this._data.numberOfThemeExtesions ? `\n(${this._data.numberOfThemeExtesions} theme extensions excluded)` : ''; + + if (!this._data.enabledNonThemeExtesions) { + return 'Extensions: none' + themeExclusionStr; + } + + let tableHeader = `Extension|Author (truncated)|Version +---|---|---`; + const table = this._data.enabledNonThemeExtesions.map(e => { + return `${e.manifest.name}|${e.manifest.publisher.substr(0, 3)}|${e.manifest.version}`; + }).join('\n'); + + const extensionTable = `
Extensions (${this._data.enabledNonThemeExtesions.length}) + +${tableHeader} +${table} +${themeExclusionStr} + +
`; + + // 2000 chars is browsers de-facto limit for URLs, 400 chars are allowed for other string parts of the issue URL + // http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers + if (encodeURIComponent(extensionTable).length > 1600) { + return 'the listing length exceeds browsers\' URL characters limit'; + } + + return extensionTable; + } +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/issue/issueReporterPage.ts b/src/vs/code/electron-browser/issue/issueReporterPage.ts new file mode 100644 index 00000000000..19085c508fa --- /dev/null +++ b/src/vs/code/electron-browser/issue/issueReporterPage.ts @@ -0,0 +1,113 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { escape } from 'vs/base/common/strings'; +import { localize } from 'vs/nls'; +import * as os from 'os'; +import pkg from 'vs/platform/node/package'; + +export default (): string => ` +
+ + +
+ + +
+ +
+ + + + + + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+
+ ${escape(localize('systemInfo', "My System Info"))} + + + + +
+ +
+
+
+
+
+ ${escape(localize('processes', "Currently Running Processes"))} + + + + +
+ +
+
+
+
+
+ ${escape(localize('workspaceStats', "My Workspace Stats"))} + + + + +
+					
+						
+					
+				
+
+
+
+
+ ${escape(localize('extensions', "My Extensions"))} + + + + +
+ +
+
+
+
+ +
+ + + + +
+ ${escape(localize('githubMarkdown', "We support GitHub-flavored Markdown. You will still be able to edit your issue and add screenshots when we preview it on GitHub."))} + + +
+
+ + +
`; \ No newline at end of file diff --git a/src/vs/code/electron-browser/issue/media/issueReporter.css b/src/vs/code/electron-browser/issue/media/issueReporter.css new file mode 100644 index 00000000000..1444e6cd944 --- /dev/null +++ b/src/vs/code/electron-browser/issue/media/issueReporter.css @@ -0,0 +1,223 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Table + */ + +table { + width: 100%; + max-width: 100%; + margin-bottom: 1rem; + background-color: transparent; + border-collapse: collapse; +} +th { + vertical-align: bottom; + border-bottom: 2px solid #e9ecef; + padding: .75rem; + border-top: 1px solid #e9ecef; + text-align: inherit; +} +tr:nth-of-type(even) { + background-color: rgba(0,0,0,.05); +} +td { + padding: .75rem; + vertical-align: top; + border-top: 1px solid #e9ecef; +} + +/** + * Forms + */ +input, textarea { + display: block; + width: 100%; + padding: .375rem .75rem; + margin: 0; + font-size: 1rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + border-radius: .25rem; + border: 1px solid #ced4da; +} +textarea { + overflow: auto; + resize: vertical; +} +small { + color: #868e96; + display: block; + margin-top: .25rem; + font-size: 80%; + font-weight: 400; +} + +/** + * Button + */ +button { + display: inline-block; + font-weight: 400; + line-height: 1.25; + text-align: center; + white-space: nowrap; + vertical-align: middle; + user-select: none; + padding: .5rem 1rem; + font-size: 1rem; + border-radius: .25rem; + background: none; +} + +select { + height: calc(2.25rem + 2px); + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + border-radius: 0.25rem; + border: none; +} + +* { + box-sizing: border-box; +} +html { + font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif; + color: #CCCCCC; +} + +body { + margin: 0; +} + +.hidden { + display: none; +} + +#block-container { + margin-top: 1em; +} + +.block .block-info { + width: 100%; + font-family: 'Menlo', 'Courier New', 'Courier', monospace; + font-size: 14px; + overflow: auto; + overflow-wrap: break-word; +} +pre { + margin: 0; +} +pre code { + font-family: 'Menlo', 'Courier New', 'Courier', monospace; +} + +button:hover:enabled { + cursor: pointer; +} + +button:disabled { + cursor: auto; +} + +#issue-reporter { + max-width: 80vw; + margin-left: auto; + margin-right: auto; + margin-top: 2em; +} + +#github-submit-btn { + float: right; + margin-top: 10px; + margin-bottom: 10px; + +} + +.two-col { + display: inline-block; + width: 49%; +} + +#vscode-version { + width: 90%; +} + +.input-group { + margin-bottom: 1em; +} + +select, input, textarea { + border: 1px solid transparent; + margin-top: 10px; +} + +summary { + border: 1px solid transparent; + padding: 10px; + margin-bottom: 5px; +} + +.validation-error { + font-size: 12px; + margin-top: 1em; +} + +.caption { + display: inline-block; + font-size: 12px; + vertical-align: middle; + height: 18px; +} + +input[type="checkbox"] { + margin-left: 1em; + height: 18px; + width: auto; + display: inline-block; + margin-top: 0; + vertical-align: middle; +} + +input:disabled { + opacity: 0.6; +} + +.list-title { + margin-top: 1em; + margin-left: 1em; +} + +/* Default styles, overwritten if a theme is provided */ +input, select, textarea { + background-color: #3c3c3c; + border: none; + color: #cccccc; +} + +a { + color: #CCCCCC; +} + +.invalid-input { + border: 1px solid #be1100; +} + +.required-input, .validation-error { + color: #be1100; +} + +button { + background-color: #007ACC; + color: #fff; + border: none; +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts new file mode 100644 index 00000000000..16c41488e74 --- /dev/null +++ b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel'; + +suite('IssueReporter', () => { + + test('serializes model', () => { + const issueReporterModel = new IssueReporterModel(); + assert.equal(issueReporterModel.serialize(), + ` +### Issue Type +Feature Request + +### Description + +undefined + +### VS Code Info + +VS Code version: undefined +OS version: undefined + + + + +`); + }); +}); diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts b/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts index 9690ef75a7c..593d731262f 100644 --- a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts +++ b/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts @@ -7,7 +7,12 @@ import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { LanguagePackExtensions } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackExtensions'; +import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; -export function createSharedProcessContributions(service: IInstantiationService): void { - service.createInstance(NodeCachedDataCleaner); +export function createSharedProcessContributions(service: IInstantiationService): IDisposable { + return combinedDisposable([ + service.createInstance(NodeCachedDataCleaner), + service.createInstance(LanguagePackExtensions) + ]); } diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/languagePackExtensions.ts b/src/vs/code/electron-browser/sharedProcess/contrib/languagePackExtensions.ts new file mode 100644 index 00000000000..824a6c2ee62 --- /dev/null +++ b/src/vs/code/electron-browser/sharedProcess/contrib/languagePackExtensions.ts @@ -0,0 +1,110 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as pfs from 'vs/base/node/pfs'; +import { IExtensionManagementService, ILocalExtension, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { join } from 'vs/base/common/paths'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Limiter } from 'vs/base/common/async'; +import { areSameExtensions, getGalleryExtensionIdFromLocal, getIdFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { ILogService } from 'vs/platform/log/common/log'; + +interface ILanguageSource { + extensionIdentifier: IExtensionIdentifier; + version: string; + translations: string; +} + +export class LanguagePackExtensions extends Disposable { + + private languagePacksFilePath: string; + private languagePacksFileLimiter: Limiter; + + constructor( + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IEnvironmentService environmentService: IEnvironmentService, + @ILogService private logService: ILogService + ) { + super(); + this.languagePacksFilePath = join(environmentService.userDataPath, 'languagepacks.json'); + this.languagePacksFileLimiter = new Limiter(1); + + this._register(extensionManagementService.onDidInstallExtension(({ local }) => this.onDidInstallExtension(local))); + this._register(extensionManagementService.onDidUninstallExtension(({ identifier }) => this.onDidUninstallExtension(identifier))); + + this.reset(); + } + + private reset(): void { + this.extensionManagementService.getInstalled() + .then(installed => { + this.withLanguagePacks(languagePacks => { + for (const language of Object.keys(languagePacks)) { + languagePacks[language] = []; + } + this.addLanguagePacksFromExtensions(languagePacks, ...installed); + }); + }); + } + + private onDidInstallExtension(extension: ILocalExtension): void { + if (extension && extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) { + this.logService.debug('Adding language packs from the extension', extension.identifier.id); + this.withLanguagePacks(languagePacks => { + this.removeLanguagePacksFromExtensions(languagePacks, { id: getGalleryExtensionIdFromLocal(extension), uuid: extension.identifier.uuid }); + this.addLanguagePacksFromExtensions(languagePacks, extension); + }); + } + } + + private onDidUninstallExtension(identifier: IExtensionIdentifier): void { + this.logService.debug('Removing language packs from the extension', identifier.id); + this.withLanguagePacks(languagePacks => this.removeLanguagePacksFromExtensions(languagePacks, { id: getIdFromLocalExtensionId(identifier.id), uuid: identifier.uuid })); + } + + private addLanguagePacksFromExtensions(languagePacks: { [language: string]: ILanguageSource[] }, ...extensions: ILocalExtension[]): void { + for (const extension of extensions) { + if (extension && extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) { + const extensionIdentifier = { id: getGalleryExtensionIdFromLocal(extension), uuid: extension.identifier.uuid }; + for (const localizationContribution of extension.manifest.contributes.localizations) { + if (localizationContribution.languageId && localizationContribution.translations) { + const languageSources = languagePacks[localizationContribution.languageId] || []; + languageSources.splice(0, 0, { extensionIdentifier, translations: join(extension.path, localizationContribution.translations), version: extension.manifest.version }); + languagePacks[localizationContribution.languageId] = languageSources; + } + } + } + } + } + + private removeLanguagePacksFromExtensions(languagePacks: { [language: string]: ILanguageSource[] }, ...extensionIdentifiers: IExtensionIdentifier[]): void { + for (const language of Object.keys(languagePacks)) { + languagePacks[language] = languagePacks[language].filter(languageSource => !extensionIdentifiers.some(extensionIdentifier => areSameExtensions(extensionIdentifier, languageSource.extensionIdentifier))); + } + } + + private withLanguagePacks(fn: (languagePacks: { [language: string]: ILanguageSource[] }) => T): TPromise { + return this.languagePacksFileLimiter.queue(() => { + let result: T = null; + return pfs.readFile(this.languagePacksFilePath, 'utf8') + .then(null, err => err.code === 'ENOENT' ? TPromise.as('{}') : TPromise.wrapError(err)) + .then<{ [language: string]: ILanguageSource[] }>(raw => { try { return JSON.parse(raw); } catch (e) { return {}; } }) + .then(languagePacks => { result = fn(languagePacks); return languagePacks; }) + .then(languagePacks => { + for (const language of Object.keys(languagePacks)) { + if (!(languagePacks[language] && languagePacks[language].length)) { + delete languagePacks[language]; + } + } + const raw = JSON.stringify(languagePacks); + this.logService.debug('Writing language packs', raw); + return pfs.writeFile(this.languagePacksFilePath, raw); + }) + .then(() => result, error => this.logService.error(error)); + }); + } +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js index 5f4f1dae5bd..94481666801 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcess.js +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcess.js @@ -6,6 +6,7 @@ 'use strict'; const path = require('path'); +const fs = require('fs'); function assign(destination, source) { return Object.keys(source) @@ -40,6 +41,18 @@ function uriFromPath(_path) { return encodeURI('file://' + pathName); } +function readFile(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, 'utf8', function(err, data) { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + function main() { const args = parseURLQueryArgs(); const configuration = JSON.parse(args['config'] || '{}') || {}; @@ -57,6 +70,24 @@ function main() { } catch (e) { /*noop*/ } } + if (nlsConfig._resolvedLanguagePackCoreLocation) { + let bundles = Object.create(null); + nlsConfig.loadBundle = function(bundle, language, cb) { + let result = bundles[bundle]; + if (result) { + cb(undefined, result); + return; + } + let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json'); + readFile(bundleFile).then(function (content) { + let json = JSON.parse(content); + bundles[bundle] = json; + cb(undefined, json); + }) + .catch(cb); + }; + } + var locale = nlsConfig.availableLanguages['*'] || 'en'; if (locale === 'zh-tw') { locale = 'zh-Hant'; diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 2f0521cf00e..f13a6d2c95f 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -38,7 +38,8 @@ import { ipcRenderer } from 'electron'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createSharedProcessContributions } from 'vs/code/electron-browser/sharedProcess/contrib/contributions'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; -import { ILogService } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -51,6 +52,7 @@ export function startup(configuration: ISharedProcessConfiguration) { interface ISharedProcessInitData { sharedIPCHandle: string; args: ParsedArgs; + logLevel: LogLevel; } class ActiveWindowManager implements IDisposable { @@ -81,7 +83,8 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I const services = new ServiceCollection(); const environmentService = new EnvironmentService(initData.args, process.execPath); - const logService = createSpdLogService('sharedprocess', environmentService); + const logLevelClient = new LogLevelSetterChannelClient(server.getChannel('loglevel', { route: () => 'main' })); + const logService = new FollowerLogService(logLevelClient, createSpdLogService('sharedprocess', initData.logLevel, environmentService.logsPath)); process.once('exit', () => logService.dispose()); logService.info('main', JSON.stringify(configuration)); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index ca4a569c0f6..06ce9b9d2f0 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -16,7 +16,6 @@ import { CodeMenu } from 'vs/code/electron-main/menus'; import { getShellEnvironment } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; import { UpdateChannel } from 'vs/platform/update/common/updateIpc'; -import { UpdateService } from 'vs/platform/update/electron-main/updateService'; import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main'; import { Server, connect, Client } from 'vs/base/parts/ipc/node/ipc.net'; import { SharedProcess } from 'vs/code/electron-main/sharedProcess'; @@ -52,6 +51,13 @@ import URI from 'vs/base/common/uri'; import { WorkspacesChannel } from 'vs/platform/workspaces/common/workspacesIpc'; import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { getMachineId } from 'vs/base/node/id'; +import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32'; +import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux'; +import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin'; +import { IIssueService } from 'vs/platform/issue/common/issue'; +import { IssueChannel } from 'vs/platform/issue/common/issueIpc'; +import { IssueService } from 'vs/platform/issue/electron-main/issueService'; +import { LogLevelSetterChannel } from 'vs/platform/log/common/logIpc'; export class CodeApplication { @@ -126,8 +132,16 @@ export class CodeApplication { } }); - const isValidWebviewSource = (source: string) => - !source || (URI.parse(source.toLowerCase()).toString() as any).startsWith(URI.file(this.environmentService.appRoot.toLowerCase()).toString()); + const isValidWebviewSource = (source: string): boolean => { + if (!source) { + return false; + } + if (source === 'data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E') { + return true; + } + const srcUri: any = URI.parse(source.toLowerCase()).toString(); + return srcUri.startsWith(URI.file(this.environmentService.appRoot.toLowerCase()).toString()); + }; app.on('web-contents-created', (_event: any, contents) => { contents.on('will-attach-webview', (event: Electron.Event, webPreferences, params) => { @@ -259,7 +273,7 @@ export class CodeApplication { this.logService.trace(`Resolved machine identifier: ${machineId}`); // Spawn shared process - this.sharedProcess = new SharedProcess(this.environmentService, machineId, this.userEnv); + this.sharedProcess = new SharedProcess(this.environmentService, machineId, this.userEnv, this.logService); this.toDispose.push(this.sharedProcess); this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main')); @@ -296,10 +310,18 @@ export class CodeApplication { private initServices(machineId: string): IInstantiationService { const services = new ServiceCollection(); - services.set(IUpdateService, new SyncDescriptor(UpdateService)); + if (process.platform === 'win32') { + services.set(IUpdateService, new SyncDescriptor(Win32UpdateService)); + } else if (process.platform === 'linux') { + services.set(IUpdateService, new SyncDescriptor(LinuxUpdateService)); + } else if (process.platform === 'darwin') { + services.set(IUpdateService, new SyncDescriptor(DarwinUpdateService)); + } + services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, machineId)); services.set(IWindowsService, new SyncDescriptor(WindowsService, this.sharedProcess)); services.set(ILaunchService, new SyncDescriptor(LaunchService)); + services.set(IIssueService, new SyncDescriptor(IssueService, machineId)); // Telemtry if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) { @@ -344,6 +366,10 @@ export class CodeApplication { const urlChannel = appInstantiationService.createInstance(URLChannel, urlService); this.electronIpcServer.registerChannel('url', urlChannel); + const issueService = accessor.get(IIssueService); + const issueChannel = new IssueChannel(issueService); + this.electronIpcServer.registerChannel('issue', issueChannel); + const workspacesService = accessor.get(IWorkspacesMainService); const workspacesChannel = appInstantiationService.createInstance(WorkspacesChannel, workspacesService); this.electronIpcServer.registerChannel('workspaces', workspacesChannel); @@ -353,6 +379,11 @@ export class CodeApplication { this.electronIpcServer.registerChannel('windows', windowsChannel); this.sharedProcessClient.done(client => client.registerChannel('windows', windowsChannel)); + // Log level management + const logLevelChannel = new LogLevelSetterChannel(accessor.get(ILogService)); + this.electronIpcServer.registerChannel('loglevel', logLevelChannel); + this.sharedProcessClient.done(client => client.registerChannel('loglevel', logLevelChannel)); + // Lifecycle this.lifecycleService.ready(); diff --git a/src/vs/code/electron-main/diagnostics.ts b/src/vs/code/electron-main/diagnostics.ts index a1720cc0568..926ce809c15 100644 --- a/src/vs/code/electron-main/diagnostics.ts +++ b/src/vs/code/electron-main/diagnostics.ts @@ -17,6 +17,75 @@ import { isWindows } from 'vs/base/common/platform'; import { app } from 'electron'; import { basename } from 'path'; +export interface VersionInfo { + vscodeVersion: string; + os: string; +} + +export interface SystemInfo { + CPUs?: string; + 'Memory (System)': string; + 'Load (avg)'?: string; + VM: string; + 'Screen Reader': string; + 'Process Argv': string; +} + +export interface ProcessInfo { + cpu: number; + memory: number; + pid: number; + name: string; +} + +export interface DiagnosticInfo { + systemInfo?: SystemInfo; + processInfo?: ProcessInfo[]; + workspaceInfo?: string; +} + +export function buildDiagnostics(info: IMainProcessInfo): Promise { + return listProcesses(info.mainPID).then(rootProcess => { + const workspaceInfoMessages = []; + + // Workspace Stats + if (info.windows.some(window => window.folders && window.folders.length > 0)) { + info.windows.forEach(window => { + if (window.folders.length === 0) { + return; + } + + workspaceInfoMessages.push(`| Window (${window.title})`); + + window.folders.forEach(folder => { + try { + const stats = collectWorkspaceStats(folder, ['node_modules', '.git']); + let countMessage = `${stats.fileCount} files`; + if (stats.maxFilesReached) { + countMessage = `more than ${countMessage}`; + } + workspaceInfoMessages.push(`| Folder (${basename(folder)}): ${countMessage}`); + workspaceInfoMessages.push(formatWorkspaceStats(stats)); + + const launchConfigs = collectLaunchConfigs(folder); + if (launchConfigs.length > 0) { + workspaceInfoMessages.push(formatLaunchConfigs(launchConfigs)); + } + } catch (error) { + workspaceInfoMessages.push(`| Error: Unable to collect workpsace stats for folder ${folder} (${error.toString()})`); + } + }); + }); + } + + return { + systemInfo: getSystemInfo(info), + processInfo: getProcessList(info, rootProcess), + workspaceInfo: workspaceInfoMessages.join('\n') + }; + }); +} + export function printDiagnostics(info: IMainProcessInfo): Promise { return listProcesses(info.mainPID).then(rootProcess => { @@ -83,7 +152,6 @@ function formatWorkspaceStats(workspaceStats: WorkspaceStats): string { line += item; }; - // File Types let line = '| File types:'; const maxShown = 10; @@ -118,6 +186,73 @@ function formatLaunchConfigs(configs: WorkspaceStatItem[]): string { return output.join('\n'); } +function getSystemInfo(info: IMainProcessInfo): SystemInfo { + const MB = 1024 * 1024; + const GB = 1024 * MB; + + const systemInfo: SystemInfo = { + 'Memory (System)': `${(os.totalmem() / GB).toFixed(2)}GB (${(os.freemem() / GB).toFixed(2)}GB free)`, + VM: `${Math.round((virtualMachineHint.value() * 100))}%`, + 'Screen Reader': `${app.isAccessibilitySupportEnabled() ? 'yes' : 'no'}`, + 'Process Argv': `${info.mainArguments.join(' ')}` + }; + + const cpus = os.cpus(); + if (cpus && cpus.length > 0) { + systemInfo.CPUs = `${cpus[0].model} (${cpus.length} x ${cpus[0].speed})`; + } + + if (!isWindows) { + systemInfo['Load (avg)'] = `${os.loadavg().map(l => Math.round(l)).join(', ')}`; + } + + + return systemInfo; +} + +function getProcessList(info: IMainProcessInfo, rootProcess: ProcessItem): ProcessInfo[] { + const mapPidToWindowTitle = new Map(); + info.windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title)); + + const processes: ProcessInfo[] = []; + + if (rootProcess) { + getProcessItem(mapPidToWindowTitle, processes, rootProcess, 0); + } + + return processes; +} + +function getProcessItem(mapPidToWindowTitle: Map, processes: ProcessInfo[], item: ProcessItem, indent: number): void { + const isRoot = (indent === 0); + + const MB = 1024 * 1024; + + // Format name with indent + let name: string; + if (isRoot) { + name = `${product.applicationName} main`; + } else { + name = `${repeat('--', indent)} ${item.name}`; + + if (item.name === 'window') { + name = `${name} (${mapPidToWindowTitle.get(item.pid)})`; + } + } + const memory = process.platform === 'win32' ? item.mem : (os.totalmem() * (item.mem / 100)); + processes.push({ + cpu: Number(item.load.toFixed(0)), + memory: Number((memory / MB).toFixed(0)), + pid: Number((item.pid).toFixed(0)), + name + }); + + // Recurse into children if any + if (Array.isArray(item.children)) { + item.children.forEach(child => getProcessItem(mapPidToWindowTitle, processes, child, indent + 1)); + } +} + function formatEnvironment(info: IMainProcessInfo): string { const MB = 1024 * 1024; const GB = 1024 * MB; @@ -178,4 +313,4 @@ function formatProcessItem(mapPidToWindowTitle: Map, output: str if (Array.isArray(item.children)) { item.children.forEach(child => formatProcessItem(mapPidToWindowTitle, output, child, indent + 1)); } -} \ No newline at end of file +} diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index 22f9d83c99b..17f5ac6ffde 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -214,4 +214,4 @@ export class LaunchService implements ILaunchService { folders } as IWindowInfo; } -} \ No newline at end of file +} diff --git a/src/vs/code/electron-main/logUploader.ts b/src/vs/code/electron-main/logUploader.ts index f4a034627d3..ce74d852eed 100644 --- a/src/vs/code/electron-main/logUploader.ts +++ b/src/vs/code/electron-main/logUploader.ts @@ -46,6 +46,7 @@ export async function uploadLogs( const logsPath = await channel.call('get-logs-path', null); if (await promptUserToConfirmLogUpload(logsPath)) { + console.log(localize('beginUploading', 'Uploading...')); const outZip = await zipLogs(logsPath); const result = await postLogs(endpoint, outZip, requestService); console.log(localize('didUploadLogs', 'Uploaded logs ID: {0}', result.blob_id)); @@ -55,18 +56,20 @@ export async function uploadLogs( } async function promptUserToConfirmLogUpload( - logsPath: string + logsPath: string, ): Promise { + const message = localize('logUploadPromptHeader', 'Upload session logs to secure endpoint?') + + '\n\n' + localize('logUploadPromptBody', 'Please review your log files here: \'{0}\'', logsPath) + + '\n\n' + localize('logUploadPromptBodyDetails', 'Logs may contain personal information such as full paths and file contents.') + + '\n\n' + localize('logUploadPromptKey', 'I have reviewed my logs (enter \'y\' to confirm upload)'); + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new TPromise(resolve => - rl.question( - localize('logUploadPromptHeader', 'Upload session logs to secure endpoint?') - + '\n\n' + localize('logUploadPromptBody', 'Please review your log files: \'{0}\'', logsPath) - + '\n\n' + localize('logUploadPromptKey', 'Enter \'y\' to confirm upload...'), + rl.question(message, (answer: string) => { rl.close(); resolve(answer && answer.trim()[0].toLowerCase() === 'y'); @@ -83,10 +86,9 @@ async function postLogs( result = await requestService.request({ url: endpoint.url, type: 'POST', - data: fs.createReadStream(outZip), + data: new Buffer(fs.readFileSync(outZip)).toString('base64'), headers: { - 'Content-Type': 'application/zip', - 'Content-Length': fs.statSync(outZip).size + 'Content-Type': 'application/zip' } }); } catch (e) { @@ -94,12 +96,28 @@ async function postLogs( throw e; } - try { - return JSON.parse(result.stream.toString()); - } catch (e) { - console.log(localize('parseError', 'Error parsing response')); - throw e; - } + return new TPromise((res, reject) => { + const parts: Buffer[] = []; + result.stream.on('data', data => { + parts.push(data); + }); + + result.stream.on('end', () => { + try { + const response = Buffer.concat(parts).toString('utf-8'); + if (result.res.statusCode === 200) { + res(JSON.parse(response)); + } else { + const errorMessage = localize('responseError', 'Error posting logs. Got {0}', result.res.statusCode); + console.log(errorMessage); + reject(new Error(errorMessage)); + } + } catch (e) { + console.log(localize('parseError', 'Error parsing response')); + reject(e); + } + }); + }); } function zipLogs( diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index ea7bf733406..8dd60aec8a2 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -21,7 +21,7 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { ILogService, ConsoleLogMainService, MultiplexLogService } from 'vs/platform/log/common/log'; +import { ILogService, ConsoleLogMainService, MultiplexLogService, getLogLevel } from 'vs/platform/log/common/log'; import { StateService } from 'vs/platform/state/node/stateService'; import { IStateService } from 'vs/platform/state/common/state'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; @@ -45,12 +45,15 @@ import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { printDiagnostics } from 'vs/code/electron-main/diagnostics'; import { BufferLogService } from 'vs/platform/log/common/bufferLog'; +import { uploadLogs } from 'vs/code/electron-main/logUploader'; +import { IChoiceService } from 'vs/platform/message/common/message'; +import { ChoiceCliService } from 'vs/platform/message/node/messageCli'; function createServices(args: ParsedArgs, bufferLogService: BufferLogService): IInstantiationService { const services = new ServiceCollection(); const environmentService = new EnvironmentService(args, process.execPath); - const consoleLogService = new ConsoleLogMainService(environmentService); + const consoleLogService = new ConsoleLogMainService(getLogLevel(environmentService)); const logService = new MultiplexLogService([consoleLogService, bufferLogService]); process.once('exit', () => logService.dispose()); @@ -68,6 +71,7 @@ function createServices(args: ParsedArgs, bufferLogService: BufferLogService): I services.set(IRequestService, new SyncDescriptor(RequestService)); services.set(IURLService, new SyncDescriptor(URLService, args['open-url'] ? args._urls : [])); services.set(IBackupMainService, new SyncDescriptor(BackupMainService)); + services.set(IChoiceService, new SyncDescriptor(ChoiceCliService)); return new InstantiationService(services, true); } @@ -198,8 +202,7 @@ function setupIPC(accessor: ServicesAccessor): TPromise { // Log uploader if (environmentService.args['upload-logs']) { - return import('vs/code/electron-main/logUploader') - .then(logUploader => logUploader.uploadLogs(channel, requestService)) + return uploadLogs(channel, requestService) .then(() => TPromise.wrapError(new ExpectedError())); } @@ -320,7 +323,7 @@ function main() { return instantiationService.invokeFunction(a => createPaths(a.get(IEnvironmentService))) .then(() => instantiationService.invokeFunction(setupIPC)) .then(mainIpcServer => { - bufferLogService.logger = createSpdLogService('main', environmentService); + bufferLogService.logger = createSpdLogService('main', bufferLogService.getLevel(), environmentService.logsPath); return instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnv).startup(); }); }).done(null, err => instantiationService.invokeFunction(quit, err)); diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 59229fbc739..f6f96d5cf64 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -14,7 +14,7 @@ import { OpenContext, IRunActionInWindowRequest } from 'vs/platform/windows/comm import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { AutoSaveConfiguration } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; +import { IUpdateService, StateType } from 'vs/platform/update/common/update'; import product from 'vs/platform/node/product'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -327,7 +327,7 @@ export class CodeMenu { const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' }); const quit = new MenuItem(this.likeAction('workbench.action.quit', { label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => { - if (this.windowsMainService.getWindowCount() === 0 || !!this.windowsMainService.getFocusedWindow()) { + if (this.windowsMainService.getWindowCount() === 0 || !!BrowserWindow.getFocusedWindow()) { this.windowsMainService.quit(); // fix for https://github.com/Microsoft/vscode/issues/39191 } } @@ -683,6 +683,7 @@ export class CodeMenu { } const commands = this.createMenuItem(nls.localize({ key: 'miCommandPalette', comment: ['&& denotes a mnemonic'] }, "&&Command Palette..."), 'workbench.action.showCommands'); + const openView = this.createMenuItem(nls.localize({ key: 'miOpenView', comment: ['&& denotes a mnemonic'] }, "&&Open View..."), 'workbench.action.openView'); const fullscreen = new MenuItem(this.withKeybinding('workbench.action.toggleFullScreen', { label: this.mnemonicLabel(nls.localize({ key: 'miToggleFullScreen', comment: ['&& denotes a mnemonic'] }, "Toggle &&Full Screen")), click: () => this.windowsMainService.getLastActiveWindow().toggleFullScreen(), enabled: this.windowsMainService.getWindowCount() > 0 })); const toggleZenMode = this.createMenuItem(nls.localize('miToggleZenMode', "Toggle Zen Mode"), 'workbench.action.toggleZenMode'); @@ -729,6 +730,7 @@ export class CodeMenu { arrays.coalesce([ commands, + openView, __separator__(), explorer, search, @@ -942,7 +944,7 @@ export class CodeMenu { const label = nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue"); if (this.windowsMainService.getWindowCount() > 0) { - reportIssuesItem = this.createMenuItem(label, 'workbench.action.reportIssues'); + reportIssuesItem = this.createMenuItem(label, 'workbench.action.openIssueReporter'); } else { reportIssuesItem = new MenuItem({ label: this.mnemonicLabel(label), click: () => this.openUrl(product.reportIssueUrl, 'openReportIssues') }); } @@ -1040,45 +1042,51 @@ export class CodeMenu { } private getUpdateMenuItems(): Electron.MenuItem[] { - switch (this.updateService.state) { - case UpdateState.Uninitialized: + const state = this.updateService.state; + + switch (state.type) { + case StateType.Uninitialized: return []; - case UpdateState.UpdateDownloaded: + case StateType.Idle: return [new MenuItem({ - label: nls.localize('miRestartToUpdate', "Restart to Update..."), click: () => { - this.reportMenuActionTelemetry('RestartToUpdate'); - this.updateService.quitAndInstall(); - } - })]; - - case UpdateState.CheckingForUpdate: - return [new MenuItem({ label: nls.localize('miCheckingForUpdates', "Checking For Updates..."), enabled: false })]; - - case UpdateState.UpdateAvailable: - if (isLinux) { - return [new MenuItem({ - label: nls.localize('miDownloadUpdate', "Download Available Update"), click: () => { - this.updateService.quitAndInstall(); - } - })]; - } - - const updateAvailableLabel = isWindows - ? nls.localize('miDownloadingUpdate', "Downloading Update...") - : nls.localize('miInstallingUpdate', "Installing Update..."); - - return [new MenuItem({ label: updateAvailableLabel, enabled: false })]; - - default: - const result = [new MenuItem({ label: nls.localize('miCheckForUpdates', "Check for Updates..."), click: () => setTimeout(() => { this.reportMenuActionTelemetry('CheckForUpdate'); this.updateService.checkForUpdates(true); }, 0) })]; - return result; + case StateType.CheckingForUpdates: + return [new MenuItem({ label: nls.localize('miCheckingForUpdates', "Checking For Updates..."), enabled: false })]; + + case StateType.AvailableForDownload: + return [new MenuItem({ + label: nls.localize('miDownloadUpdate', "Download Available Update"), click: () => { + this.updateService.downloadUpdate(); + } + })]; + + case StateType.Downloading: + return [new MenuItem({ label: nls.localize('miDownloadingUpdate', "Downloading Update..."), enabled: false })]; + + case StateType.Downloaded: + return [new MenuItem({ + label: nls.localize('miInstallUpdate', "Install Update..."), click: () => { + this.reportMenuActionTelemetry('InstallUpdate'); + this.updateService.applyUpdate(); + } + })]; + + case StateType.Updating: + return [new MenuItem({ label: nls.localize('miInstallingUpdate', "Installing Update..."), enabled: false })]; + + case StateType.Ready: + return [new MenuItem({ + label: nls.localize('miRestartToUpdate', "Restart to Update..."), click: () => { + this.reportMenuActionTelemetry('RestartToUpdate'); + this.updateService.quitAndInstall(); + } + })]; } } diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index ff9f904cb68..e402ec33a5d 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -12,6 +12,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { BrowserWindow, ipcMain } from 'electron'; import { ISharedProcess } from 'vs/platform/windows/electron-main/windows'; import { Barrier } from 'vs/base/common/async'; +import { ILogService } from 'vs/platform/log/common/log'; export class SharedProcess implements ISharedProcess { @@ -23,7 +24,8 @@ export class SharedProcess implements ISharedProcess { constructor( private environmentService: IEnvironmentService, private readonly machineId: string, - private readonly userEnv: IProcessEnvironment + private readonly userEnv: IProcessEnvironment, + private readonly logService: ILogService ) { } @memoize @@ -75,7 +77,8 @@ export class SharedProcess implements ISharedProcess { ipcMain.once('handshake:hello', ({ sender }: { sender: any }) => { sender.send('handshake:hey there', { sharedIPCHandle: this.environmentService.sharedIPCHandle, - args: this.environmentService.args + args: this.environmentService.args, + logLevel: this.logService.getLevel() }); ipcMain.once('handshake:im ready', () => c(null)); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 4c37dd6e993..dbe69eb291e 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -565,6 +565,7 @@ export class CodeWindow implements ICodeWindow { // Set window ID windowConfiguration.windowId = this._win.id; + windowConfiguration.logLevel = this.logService.getLevel(); // Set zoomlevel const windowConfig = this.configurationService.getValue('window'); @@ -593,7 +594,7 @@ export class CodeWindow implements ICodeWindow { const environment = parseArgs(process.argv); const config = objects.assign(environment, windowConfiguration); for (let key in config) { - if (!config[key]) { + if (config[key] === void 0 || config[key] === null || config[key] === '') { delete config[key]; // only send over properties that have a true value } } @@ -953,7 +954,7 @@ export class CodeWindow implements ICodeWindow { const segments: ITouchBarSegment[] = items.map(item => { let icon: Electron.NativeImage; if (item.iconPath) { - icon = nativeImage.createFromPath(item.iconPath); + icon = nativeImage.createFromPath(item.iconPath.dark); if (icon.isEmpty()) { icon = void 0; } diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 073f7dc441f..b1bdea73fb4 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -1318,7 +1318,10 @@ export class WindowsManager implements IWindowsMainService { } if (e.window.config && !!e.window.config.extensionDevelopmentPath) { - return; // do not ask to save workspace when doing extension development + // do not ask to save workspace when doing extension development + // but still delete it. + this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); + return; } if (windowClosing && !isMacintosh && this.getWindowCount() === 1) { @@ -1326,7 +1329,17 @@ export class WindowsManager implements IWindowsMainService { } // Handle untitled workspaces with prompt as needed - e.veto(this.workspacesManager.promptToSaveUntitledWorkspace(this.getWindowById(e.window.id), workspace)); + e.veto(this.workspacesManager.promptToSaveUntitledWorkspace(this.getWindowById(e.window.id), workspace).then(veto => { + if (veto) { + return veto; + } + + // Bug in electron: somehow we need this timeout so that the window closes properly. That + // might be related to the fact that the untitled workspace prompt shows up async and this + // code can execute before the dialog is fully closed which then blocks the window from closing. + // Issue: https://github.com/Microsoft/vscode/issues/41989 + return TPromise.timeout(0).then(() => veto); + })); } public focusLastActive(cli: ParsedArgs, context: OpenContext): CodeWindow { @@ -1706,8 +1719,8 @@ class Dialogs { class WorkspacesManager { constructor( - private workspacesService: IWorkspacesMainService, - private backupService: IBackupMainService, + private workspacesMainService: IWorkspacesMainService, + private backupMainService: IBackupMainService, private environmentService: IEnvironmentService, private windowsMainService: IWindowsMainService ) { @@ -1731,7 +1744,7 @@ class WorkspacesManager { return TPromise.as(null); // return early if the workspace is not valid } - return this.workspacesService.createWorkspace(folders).then(workspace => { + return this.workspacesMainService.createWorkspace(folders).then(workspace => { return this.doSaveAndOpenWorkspace(window, workspace, path); }); }); @@ -1748,7 +1761,7 @@ class WorkspacesManager { } // Prevent overwriting a workspace that is currently opened in another window - if (findWindowOnWorkspace(this.windowsMainService.getWindows(), { id: this.workspacesService.getWorkspaceId(path), configPath: path })) { + if (findWindowOnWorkspace(this.windowsMainService.getWindows(), { id: this.workspacesMainService.getWorkspaceId(path), configPath: path })) { const options: Electron.MessageBoxOptions = { title: product.nameLong, type: 'info', @@ -1767,7 +1780,7 @@ class WorkspacesManager { private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise { let savePromise: TPromise; if (path) { - savePromise = this.workspacesService.saveWorkspace(workspace, path); + savePromise = this.workspacesMainService.saveWorkspace(workspace, path); } else { savePromise = TPromise.as(workspace); } @@ -1778,7 +1791,7 @@ class WorkspacesManager { // Register window for backups and migrate current backups over let backupPath: string; if (!window.config.extensionDevelopmentPath) { - backupPath = this.backupService.registerWorkspaceBackupSync(workspace, window.config.backupPath); + backupPath = this.backupMainService.registerWorkspaceBackupSync(workspace, window.config.backupPath); } // Update window configuration properly based on transition to workspace @@ -1851,7 +1864,7 @@ class WorkspacesManager { // Don't Save: delete workspace case ConfirmResult.DONT_SAVE: - this.workspacesService.deleteUntitledWorkspaceSync(workspace); + this.workspacesMainService.deleteUntitledWorkspaceSync(workspace); return false; // Save: save workspace, but do not veto unload @@ -1863,7 +1876,7 @@ class WorkspacesManager { defaultPath: this.getUntitledWorkspaceSaveDialogDefaultPath(workspace) }, window).then(target => { if (target) { - return this.workspacesService.saveWorkspace(workspace, target).then(() => false, () => false); + return this.workspacesMainService.saveWorkspace(workspace, target).then(() => false, () => false); } return true; // keep veto if no target was provided @@ -1879,7 +1892,7 @@ class WorkspacesManager { return dirname(workspace); } - const resolvedWorkspace = this.workspacesService.resolveWorkspaceSync(workspace.configPath); + const resolvedWorkspace = this.workspacesMainService.resolveWorkspaceSync(workspace.configPath); if (resolvedWorkspace && resolvedWorkspace.folders.length > 0) { for (const folder of resolvedWorkspace.folders) { if (folder.uri.scheme === Schemas.file) { diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index b47a0015178..ca0c7cdb8ab 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -123,7 +123,7 @@ export async function main(argv: string[]): TPromise { const processCallbacks: ((child: ChildProcess) => Thenable)[] = []; - const verbose = args.verbose || args.status; + const verbose = args.verbose || args.status || args['upload-logs']; if (verbose) { env['ELECTRON_ENABLE_LOGGING'] = '1'; @@ -311,7 +311,9 @@ export async function main(argv: string[]): TPromise { env }; - if (!verbose) { + if (args['upload-logs']) { + options['stdio'] = [process.stdin, 'pipe', 'pipe']; + } else if (!verbose) { options['stdio'] = 'ignore'; } @@ -347,6 +349,6 @@ function eventuallyExit(code: number): void { main(process.argv) .then(() => eventuallyExit(0)) .then(null, err => { - console.error(err.stack ? err.stack : err); + console.error(err.message || err.stack || err); eventuallyExit(1); }); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 0d99eadec4f..a01bebe6cf7 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -36,7 +36,7 @@ import { getBaseLabel } from 'vs/base/common/labels'; import { IStateService } from 'vs/platform/state/common/state'; import { StateService } from 'vs/platform/state/node/stateService'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; -import { ILogService } from 'vs/platform/log/common/log'; +import { ILogService, getLogLevel } from 'vs/platform/log/common/log'; import { isPromiseCanceledError } from 'vs/base/common/errors'; const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id); @@ -196,7 +196,7 @@ export function main(argv: ParsedArgs): TPromise { const services = new ServiceCollection(); const environmentService = new EnvironmentService(argv, process.execPath); - const logService = createSpdLogService('cli', environmentService); + const logService = createSpdLogService('cli', getLogLevel(environmentService), environmentService.logsPath); process.once('exit', () => logService.dispose()); logService.info('main', argv); diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 0e21b9588b5..436f7a96967 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -364,7 +364,7 @@ abstract class BareHitTestRequest { this.mouseVerticalOffset = Math.max(0, ctx.getCurrentScrollTop() + pos.y - editorPos.y); this.mouseContentHorizontalOffset = ctx.getCurrentScrollLeft() + pos.x - editorPos.x - ctx.layoutInfo.contentLeft; - this.isInMarginArea = (pos.x - editorPos.x < ctx.layoutInfo.contentLeft); + this.isInMarginArea = (pos.x - editorPos.x < ctx.layoutInfo.contentLeft && pos.x - editorPos.x >= ctx.layoutInfo.glyphMarginLeft); this.isInContentArea = !this.isInMarginArea; this.mouseColumn = Math.max(0, MouseTargetFactory._getMouseColumn(this.mouseContentHorizontalOffset, ctx.typicalHalfwidthCharacterWidth)); } @@ -587,6 +587,8 @@ export class MouseTargetFactory { offsetX: offset }; + offset -= ctx.layoutInfo.glyphMarginLeft; + if (offset <= ctx.layoutInfo.glyphMarginWidth) { // On the glyph margin return request.fulfill(MouseTargetType.GUTTER_GLYPH_MARGIN, pos, res.range, detail); diff --git a/src/vs/editor/browser/services/bulkEdit.ts b/src/vs/editor/browser/services/bulkEdit.ts index bfe4d9c4df3..cded7ca6be5 100644 --- a/src/vs/editor/browser/services/bulkEdit.ts +++ b/src/vs/editor/browser/services/bulkEdit.ts @@ -5,68 +5,48 @@ 'use strict'; import * as nls from 'vs/nls'; -import { flatten } from 'vs/base/common/arrays'; -import { IStringDictionary, forEach, values, groupBy, size } from 'vs/base/common/collections'; import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; -import { IFileService, IFileChange } from 'vs/platform/files/common/files'; +import { IFileService, FileChangeType } from 'vs/platform/files/common/files'; import { EditOperation } from 'vs/editor/common/core/editOperation'; -import { Range, IRange } from 'vs/editor/common/core/range'; -import { Selection, ISelection } from 'vs/editor/common/core/selection'; +import { Range } from 'vs/editor/common/core/range'; +import { Selection } from 'vs/editor/common/core/selection'; import { IIdentifiedSingleEditOperation, ITextModel, EndOfLineSequence } from 'vs/editor/common/model'; -import { IProgressRunner } from 'vs/platform/progress/common/progress'; +import { IProgressRunner, emptyProgressRunner, IProgress } from 'vs/platform/progress/common/progress'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { optional } from 'vs/platform/instantiation/common/instantiation'; +import { ResourceTextEdit, ResourceFileEdit, isResourceFileEdit, isResourceTextEdit } from 'vs/editor/common/modes'; +import { getPathLabel } from 'vs/base/common/labels'; -export interface IResourceEdit { - resource: URI; - range?: IRange; - newText: string; - newEol?: EndOfLineSequence; -} -interface IRecording { - stop(): void; - hasChanged(resource: URI): boolean; - allChanges(): IFileChange[]; -} +abstract class IRecording { -class ChangeRecorder { - - private _fileService: IFileService; - - constructor(fileService?: IFileService) { - this._fileService = fileService; - } - - public start(): IRecording { - - const changes: IStringDictionary = Object.create(null); + static start(fileService: IFileService): IRecording { + const _changes = new Set(); let stop: IDisposable; - if (this._fileService) { - stop = this._fileService.onFileChanges((event) => { - event.changes.forEach(change => { - const key = String(change.resource); - let array = changes[key]; - - if (!array) { - changes[key] = array = []; + if (fileService) { + // watch only when there is a fileservice available + stop = fileService.onFileChanges(event => { + for (const change of event.changes) { + if (change.type === FileChangeType.UPDATED) { + _changes.add(change.resource.toString()); } - - array.push(change); - }); + } }); } return { - stop: () => { return stop && stop.dispose(); }, - hasChanged: (resource: URI) => !!changes[resource.toString()], - allChanges: () => flatten(values(changes)) + stop() { return dispose(stop); }, + hasChanged(resource) { return _changes.has(resource.toString()); } }; } + + abstract stop(): void; + abstract hasChanged(resource: URI): boolean; } class EditTask implements IDisposable { @@ -84,26 +64,34 @@ class EditTask implements IDisposable { this._edits = []; } - public addEdit(edit: IResourceEdit): void { - - if (typeof edit.newEol === 'number') { - // honor eol-change - this._newEol = edit.newEol; - } - - if (edit.range || edit.newText) { - // create edit operation - let range: Range; - if (!edit.range) { - range = this._model.getFullModelRange(); - } else { - range = Range.lift(edit.range); - } - this._edits.push(EditOperation.replaceMove(range, edit.newText)); + dispose() { + if (this._model) { + this._modelReference.dispose(); + this._modelReference = null; } } - public apply(): void { + addEdit(resourceEdit: ResourceTextEdit): void { + + for (const edit of resourceEdit.edits) { + if (typeof edit.eol === 'number') { + // honor eol-change + this._newEol = edit.eol; + } + if (edit.range || edit.text) { + // create edit operation + let range: Range; + if (!edit.range) { + range = this._model.getFullModelRange(); + } else { + range = Range.lift(edit.range); + } + this._edits.push(EditOperation.replaceMove(range, edit.text)); + } + } + } + + apply(): void { if (this._edits.length > 0) { this._edits = this._edits.map((value, index) => ({ value, index })).sort((a, b) => { @@ -160,16 +148,10 @@ class EditTask implements IDisposable { return [this._endCursorSelection]; } - public getEndCursorSelection(): Selection { + getEndCursorSelection(): Selection { return this._endCursorSelection; } - dispose() { - if (this._model) { - this._modelReference.dispose(); - this._modelReference = null; - } - } } class SourceModelEditTask extends EditTask { @@ -189,34 +171,42 @@ class SourceModelEditTask extends EditTask { class BulkEditModel implements IDisposable { private _textModelResolverService: ITextModelService; - private _numberOfResourcesToModify: number = 0; - private _edits: IStringDictionary = Object.create(null); + private _edits = new Map(); private _tasks: EditTask[]; private _sourceModel: URI; private _sourceSelections: Selection[]; private _sourceModelTask: SourceModelEditTask; + private _progress: IProgress; - constructor(textModelResolverService: ITextModelService, sourceModel: URI, sourceSelections: Selection[], edits: IResourceEdit[], private progress: IProgressRunner = null) { + constructor( + textModelResolverService: ITextModelService, + editor: ICodeEditor, + edits: ResourceTextEdit[], + progress: IProgress + ) { this._textModelResolverService = textModelResolverService; - this._sourceModel = sourceModel; - this._sourceSelections = sourceSelections; - this._sourceModelTask = null; + this._sourceModel = editor ? editor.getModel().uri : undefined; + this._sourceSelections = editor ? editor.getSelections() : undefined; + this._sourceModelTask = undefined; + this._progress = progress; - for (let edit of edits) { - this._addEdit(edit); - } + edits.forEach(this.addEdit, this); } - private _addEdit(edit: IResourceEdit): void { - let array = this._edits[edit.resource.toString()]; + dispose(): void { + this._tasks = dispose(this._tasks); + } + + addEdit(edit: ResourceTextEdit): void { + let array = this._edits.get(edit.resource.toString()); if (!array) { - this._edits[edit.resource.toString()] = array = []; - this._numberOfResourcesToModify += 1; + array = []; + this._edits.set(edit.resource.toString(), array); } array.push(edit); } - public prepare(): TPromise { + async prepare(): TPromise { if (this._tasks) { throw new Error('illegal state - already prepared'); @@ -225,145 +215,80 @@ class BulkEditModel implements IDisposable { this._tasks = []; const promises: TPromise[] = []; - if (this.progress) { - this.progress.total(this._numberOfResourcesToModify * 2); - } - - forEach(this._edits, entry => { - const promise = this._textModelResolverService.createModelReference(URI.parse(entry.key)).then(ref => { + this._edits.forEach((value, key) => { + const promise = this._textModelResolverService.createModelReference(URI.parse(key)).then(ref => { const model = ref.object; if (!model || !model.textEditorModel) { - throw new Error(`Cannot load file ${entry.key}`); + throw new Error(`Cannot load file ${key}`); } - const textEditorModel = model.textEditorModel; let task: EditTask; - - if (this._sourceModel && textEditorModel.uri.toString() === this._sourceModel.toString()) { + if (this._sourceModel && model.textEditorModel.uri.toString() === this._sourceModel.toString()) { this._sourceModelTask = new SourceModelEditTask(ref, this._sourceSelections); task = this._sourceModelTask; } else { task = new EditTask(ref); } - entry.value.forEach(edit => task.addEdit(edit)); + value.forEach(edit => task.addEdit(edit)); this._tasks.push(task); - if (this.progress) { - this.progress.worked(1); - } + this._progress.report(undefined); }); promises.push(promise); }); + await TPromise.join(promises); - return TPromise.join(promises).then(_ => this); + return this; } - public apply(): Selection { - this._tasks.forEach(task => this.applyTask(task)); - let r: Selection = null; - if (this._sourceModelTask) { - r = this._sourceModelTask.getEndCursorSelection(); + apply(): Selection { + for (const task of this._tasks) { + task.apply(); + this._progress.report(undefined); } - return r; - } - - private applyTask(task: EditTask): void { - task.apply(); - if (this.progress) { - this.progress.worked(1); - } - } - - dispose(): void { - this._tasks = dispose(this._tasks); + return this._sourceModelTask + ? this._sourceModelTask.getEndCursorSelection() + : undefined; } } -export interface BulkEdit { - progress(progress: IProgressRunner): void; - add(edit: IResourceEdit[]): void; - finish(): TPromise; - ariaMessage(): string; -} +export type Edit = ResourceFileEdit | ResourceTextEdit; -export function bulkEdit(textModelResolverService: ITextModelService, editor: ICodeEditor, edits: IResourceEdit[], fileService?: IFileService, progress: IProgressRunner = null): TPromise { - let bulk = createBulkEdit(textModelResolverService, editor, fileService); - bulk.add(edits); - bulk.progress(progress); - return bulk.finish(); -} +export class BulkEdit { -export function createBulkEdit(textModelResolverService: ITextModelService, editor?: ICodeEditor, fileService?: IFileService): BulkEdit { - - let all: IResourceEdit[] = []; - let recording = new ChangeRecorder(fileService).start(); - let progressRunner: IProgressRunner; - - function progress(progress: IProgressRunner) { - progressRunner = progress; + static perform(edits: Edit[], textModelService: ITextModelService, fileService: IFileService, editor: ICodeEditor): TPromise { + const edit = new BulkEdit(editor, null, textModelService, fileService); + edit.add(edits); + return edit.perform(); } - function add(edits: IResourceEdit[]): void { - all.push(...edits); + private _edits: Edit[] = []; + private _editor: ICodeEditor; + private _progress: IProgressRunner; + + constructor( + editor: ICodeEditor, + progress: IProgressRunner, + @ITextModelService private _textModelService: ITextModelService, + @optional(IFileService) private _fileService: IFileService + ) { + this._editor = editor; + this._progress = progress || emptyProgressRunner; } - function getConcurrentEdits() { - let names: string[]; - for (let edit of all) { - if (recording.hasChanged(edit.resource)) { - if (!names) { - names = []; - } - names.push(edit.resource.fsPath); - } + add(edits: Edit[] | Edit): void { + if (Array.isArray(edits)) { + this._edits.push(...edits); + } else { + this._edits.push(edits); } - if (names) { - return nls.localize('conflict', "These files have changed in the meantime: {0}", names.join(', ')); - } - return undefined; } - function finish(): TPromise { - - if (all.length === 0) { - return TPromise.as(undefined); - } - - let concurrentEdits = getConcurrentEdits(); - if (concurrentEdits) { - return TPromise.wrapError(new Error(concurrentEdits)); - } - - let uri: URI; - let selections: Selection[]; - - if (editor && editor.getModel()) { - uri = editor.getModel().uri; - selections = editor.getSelections(); - } - - const model = new BulkEditModel(textModelResolverService, uri, selections, all, progressRunner); - - return model.prepare().then(_ => { - - let concurrentEdits = getConcurrentEdits(); - if (concurrentEdits) { - throw new Error(concurrentEdits); - } - - recording.stop(); - - const result = model.apply(); - model.dispose(); - return result; - }); - } - - function ariaMessage(): string { - let editCount = all.length; - let resourceCount = size(groupBy(all, edit => edit.resource.toString())); + ariaMessage(): string { + const editCount = this._edits.reduce((prev, cur) => isResourceFileEdit(cur) ? prev : prev + cur.edits.length, 0); + const resourceCount = this._edits.length; if (editCount === 0) { return nls.localize('summary.0', "Made no edits"); } else if (editCount > 1 && resourceCount > 1) { @@ -373,10 +298,84 @@ export function createBulkEdit(textModelResolverService: ITextModelService, edit } } - return { - progress, - add, - finish, - ariaMessage - }; + async perform(): TPromise { + + let seen = new Set(); + let total = 0; + + const groups: Edit[][] = []; + let group: Edit[]; + for (const edit of this._edits) { + if (!group + || (isResourceFileEdit(group[0]) && !isResourceFileEdit(edit)) + || (isResourceTextEdit(group[0]) && !isResourceTextEdit(edit)) + ) { + group = []; + groups.push(group); + } + group.push(edit); + + if (isResourceFileEdit(edit)) { + total += 1; + } else if (!seen.has(edit.resource.toString())) { + seen.add(edit.resource.toString()); + total += 2; + } + } + + // define total work and progress callback + // for child operations + this._progress.total(total); + let progress: IProgress = { report: _ => this._progress.worked(1) }; + + // do it. return the last selection computed + // by a text change (can be undefined then) + let res: Selection = undefined; + for (const group of groups) { + if (isResourceFileEdit(group[0])) { + await this._performFileEdits(group, progress); + } else { + res = await this._performTextEdits(group, progress) || res; + } + } + return res; + } + + private async _performFileEdits(edits: ResourceFileEdit[], progress: IProgress) { + for (const edit of edits) { + + progress.report(undefined); + + if (edit.newUri && edit.oldUri) { + await this._fileService.moveFile(edit.oldUri, edit.newUri, false); + } else if (!edit.newUri && edit.oldUri) { + await this._fileService.del(edit.oldUri, true); + } else if (edit.newUri && !edit.oldUri) { + await this._fileService.createFile(edit.newUri, undefined, { overwrite: false }); + } + } + } + + private async _performTextEdits(edits: ResourceTextEdit[], progress: IProgress): TPromise { + + const recording = IRecording.start(this._fileService); + const model = new BulkEditModel(this._textModelService, this._editor, edits, progress); + + await model.prepare(); + + const conflicts = edits + .filter(edit => recording.hasChanged(edit.resource)) + .map(edit => getPathLabel(edit.resource)); + + recording.stop(); + + if (conflicts.length > 0) { + model.dispose(); + throw new Error(nls.localize('conflict', "These files have changed in the meantime: {0}", conflicts.join(', '))); + } + + const selection = await model.apply(); + model.dispose(); + return selection; + } } diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts index 73ae56f5e38..ed1121cfcdd 100644 --- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts +++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts @@ -99,7 +99,13 @@ export class EditorScrollbar extends ViewPart { const layoutInfo = this._context.configuration.editor.layoutInfo; this.scrollbarDomNode.setLeft(layoutInfo.contentLeft); - this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth); + + const side = this._context.configuration.editor.viewInfo.minimap.side; + if (side === 'right') { + this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth); + } else { + this.scrollbarDomNode.setWidth(layoutInfo.contentWidth); + } this.scrollbarDomNode.setHeight(layoutInfo.contentHeight); } diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 5f83e8df989..7a9761d20d8 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -228,9 +228,12 @@ export class ViewLine implements IVisibleLine { isRegularASCII = strings.isBasicASCII(lineData.content); } - if (isRegularASCII && lineData.content.length < 1000) { + if (isRegularASCII && lineData.content.length < 1000 && renderLineInput.lineTokens.getCount() < 100) { // Browser rounding errors have been observed in Chrome and IE, so using the fast // view line only for short lines. Please test before removing the length check... + // --- + // Another rounding error has been observed on Linux in VSCode, where width + // rounding errors add up to an observable large number... renderedViewLine = new FastRenderedViewLine( this._renderedViewLine ? this._renderedViewLine.domNode : null, renderLineInput, @@ -278,8 +281,27 @@ export class ViewLine implements IVisibleLine { } public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] { + startColumn = startColumn | 0; // @perf + endColumn = endColumn | 0; // @perf + startColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, startColumn)); endColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, endColumn)); + + const stopRenderingLineAfter = this._renderedViewLine.input.stopRenderingLineAfter | 0; // @perf + + if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter && endColumn > stopRenderingLineAfter) { + // This range is obviously not visible + return null; + } + + if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter) { + startColumn = stopRenderingLineAfter; + } + + if (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter) { + endColumn = stopRenderingLineAfter; + } + return this._renderedViewLine.getVisibleRangesForRange(startColumn, endColumn, context); } @@ -325,23 +347,6 @@ class FastRenderedViewLine implements IRenderedViewLine { } public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] { - startColumn = startColumn | 0; // @perf - endColumn = endColumn | 0; // @perf - const stopRenderingLineAfter = this.input.stopRenderingLineAfter | 0; // @perf - - if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter && endColumn > stopRenderingLineAfter) { - // This range is obviously not visible - return null; - } - - if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter) { - startColumn = stopRenderingLineAfter; - } - - if (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter) { - endColumn = stopRenderingLineAfter; - } - const startPosition = this._getCharPosition(startColumn); const endPosition = this._getCharPosition(endColumn); return [new HorizontalRange(startPosition, endPosition - startPosition)]; @@ -432,23 +437,6 @@ class RenderedViewLine implements IRenderedViewLine { * Visible ranges for a model range */ public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] { - startColumn = startColumn | 0; // @perf - endColumn = endColumn | 0; // @perf - const stopRenderingLineAfter = this.input.stopRenderingLineAfter | 0; // @perf - - if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter && endColumn > stopRenderingLineAfter) { - // This range is obviously not visible - return null; - } - - if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter) { - startColumn = stopRenderingLineAfter; - } - - if (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter) { - endColumn = stopRenderingLineAfter; - } - if (this._pixelOffsetCache !== null) { // the text is LTR let startOffset = this._readPixelOffset(startColumn, context); diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 62c2629841d..b1da0a53ed6 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -82,6 +82,10 @@ class MinimapOptions { public readonly lineHeight: number; + /** + * container dom node left position (in CSS px) + */ + public readonly minimapLeft: number; /** * container dom node width (in CSS px) */ @@ -121,6 +125,7 @@ class MinimapOptions { this.pixelRatio = pixelRatio; this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth; this.lineHeight = configuration.editor.lineHeight; + this.minimapLeft = layoutInfo.minimapLeft; this.minimapWidth = layoutInfo.minimapWidth; this.minimapHeight = layoutInfo.height; @@ -138,6 +143,7 @@ class MinimapOptions { && this.pixelRatio === other.pixelRatio && this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth && this.lineHeight === other.lineHeight + && this.minimapLeft === other.minimapLeft && this.minimapWidth === other.minimapWidth && this.minimapHeight === other.minimapHeight && this.canvasInnerWidth === other.canvasInnerWidth @@ -456,7 +462,6 @@ export class Minimap extends ViewPart { this._domNode.setPosition('absolute'); this._domNode.setAttribute('role', 'presentation'); this._domNode.setAttribute('aria-hidden', 'true'); - this._domNode.setRight(this._context.configuration.editor.layoutInfo.verticalScrollbarWidth); this._shadow = createFastDomNode(document.createElement('div')); this._shadow.setClassName('minimap-shadow-hidden'); @@ -563,6 +568,7 @@ export class Minimap extends ViewPart { } private _applyLayout(): void { + this._domNode.setLeft(this._options.minimapLeft); this._domNode.setWidth(this._options.minimapWidth); this._domNode.setHeight(this._options.minimapHeight); this._shadow.setHeight(this._options.minimapHeight); diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts index 92838c8a6d7..8c93fd9ef2b 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts @@ -34,7 +34,6 @@ class ViewCursorRenderData { export class ViewCursor { private readonly _context: ViewContext; - private readonly _isSecondary: boolean; private readonly _domNode: FastDomNode; private _cursorStyle: TextEditorCursorStyle; @@ -49,9 +48,8 @@ export class ViewCursor { private _lastRenderedContent: string; private _renderData: ViewCursorRenderData; - constructor(context: ViewContext, isSecondary: boolean) { + constructor(context: ViewContext) { this._context = context; - this._isSecondary = isSecondary; this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; this._lineHeight = this._context.configuration.editor.lineHeight; @@ -62,11 +60,7 @@ export class ViewCursor { // Create the dom node this._domNode = createFastDomNode(document.createElement('div')); - if (this._isSecondary) { - this._domNode.setClassName('cursor secondary'); - } else { - this._domNode.setClassName('cursor'); - } + this._domNode.setClassName('cursor'); this._domNode.setHeight(this._lineHeight); this._domNode.setTop(0); this._domNode.setLeft(0); diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.css b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.css index 4fc3fbb24c6..a0ecc219714 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.css +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.css @@ -12,9 +12,6 @@ cursor: text; overflow: hidden; } -.monaco-editor .cursors-layer > .cursor.secondary { - opacity: 0.6; -} /* -- block-outline-style -- */ .monaco-editor .cursors-layer.cursor-block-outline-style > .cursor { diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts index c54b332a631..98ec0b5a063 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursors.ts @@ -49,7 +49,7 @@ export class ViewCursors extends ViewPart { this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle; this._selectionIsEmpty = true; - this._primaryCursor = new ViewCursor(this._context, false); + this._primaryCursor = new ViewCursor(this._context); this._secondaryCursors = []; this._renderData = []; @@ -109,7 +109,7 @@ export class ViewCursors extends ViewPart { // Create new cursors let addCnt = secondaryPositions.length - this._secondaryCursors.length; for (let i = 0; i < addCnt; i++) { - let newCursor = new ViewCursor(this._context, true); + let newCursor = new ViewCursor(this._context); this._domNode.domNode.insertBefore(newCursor.getDomNode().domNode, this._primaryCursor.getDomNode().domNode.nextSibling); this._secondaryCursors.push(newCursor); } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index da33dd2058d..12d923aa696 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -264,6 +264,12 @@ const editorConfiguration: IConfigurationNode = { 'default': EDITOR_DEFAULTS.viewInfo.minimap.enabled, 'description': nls.localize('minimap.enabled', "Controls if the minimap is shown") }, + 'editor.minimap.side': { + 'type': 'string', + 'enum': ['left', 'right'], + 'default': EDITOR_DEFAULTS.viewInfo.minimap.side, + 'description': nls.localize('minimap.side', "Controls the side where to render the minimap. Possible values are \'right\' and \'left\'") + }, 'editor.minimap.showSlider': { 'type': 'string', 'enum': ['always', 'mouseover'], @@ -352,8 +358,8 @@ const editorConfiguration: IConfigurationNode = { 'type': 'string', 'enum': ['ctrlCmd', 'alt'], 'enumDescriptions': [ - nls.localize('multiCursorModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on OSX."), - nls.localize('multiCursorModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on OSX.") + nls.localize('multiCursorModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on macOS."), + nls.localize('multiCursorModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on macOS.") ], 'default': 'alt', 'description': nls.localize({ @@ -362,7 +368,7 @@ const editorConfiguration: IConfigurationNode = { '- `ctrlCmd` refers to a value the setting can take and should not be localized.', '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.' ] - }, "The modifier to be used to add multiple cursors with the mouse. `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on OSX. The Go To Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier.") + }, "The modifier to be used to add multiple cursors with the mouse. `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on macOS. The Go To Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier.") }, 'editor.quickSuggestions': { 'anyOf': [ @@ -462,6 +468,17 @@ const editorConfiguration: IConfigurationNode = { 'default': EDITOR_DEFAULTS.contribInfo.wordBasedSuggestions, 'description': nls.localize('wordBasedSuggestions', "Controls whether completions should be computed based on words in the document.") }, + 'editor.selectSuggestions': { + 'type': 'string', + 'enum': ['never', 'byRecency', 'byPrefix'], + 'enumDescriptions': [ + nls.localize('selectSuggestions.never', "Do not remember suggestions and always select the first."), + nls.localize('selectSuggestions.byRecency', "Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log`"), + nls.localize('selectSuggestions.byPrefix', "Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`"), + ], + 'default': 'byRecency', + 'description': nls.localize('selectSuggestions', "Controls if accepting suggestions changes how future suggestions are pre-selected.") + }, 'editor.suggestFontSize': { 'type': 'integer', 'default': 0, diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index c230f0088e2..9b76f7ea2dc 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -102,6 +102,11 @@ export interface IEditorMinimapOptions { * Defaults to false. */ enabled?: boolean; + /** + * Control the side of the minimap in editor. + * Defaults to 'right'. + */ + side?: 'right' | 'left'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. @@ -452,6 +457,10 @@ export interface IEditorOptions { * Enable word based suggestions. Defaults to 'true' */ wordBasedSuggestions?: boolean; + /** + * The history mode for suggestions. + */ + selectSuggestions?: string; /** * The font size for the suggest widget. * Defaults to the editor font size. @@ -740,6 +749,7 @@ export interface InternalEditorScrollbarOptions { export interface InternalEditorMinimapOptions { readonly enabled: boolean; + readonly side: 'right' | 'left'; readonly showSlider: 'always' | 'mouseover'; readonly renderCharacters: boolean; readonly maxColumn: number; @@ -821,6 +831,7 @@ export interface EditorContribOptions { readonly acceptSuggestionOnCommitCharacter: boolean; readonly snippetSuggestions: 'top' | 'bottom' | 'inline' | 'none'; readonly wordBasedSuggestions: boolean; + readonly selectSuggestions: 'never' | 'byRecency' | 'byPrefix'; readonly suggestFontSize: number; readonly suggestLineHeight: number; readonly selectionHighlight: boolean; @@ -1019,6 +1030,7 @@ export class InternalEditorOptions { && a.contentWidth === b.contentWidth && a.contentHeight === b.contentHeight && a.renderMinimap === b.renderMinimap + && a.minimapLeft === b.minimapLeft && a.minimapWidth === b.minimapWidth && a.viewportColumn === b.viewportColumn && a.verticalScrollbarWidth === b.verticalScrollbarWidth @@ -1101,6 +1113,7 @@ export class InternalEditorOptions { private static _equalsMinimapOptions(a: InternalEditorMinimapOptions, b: InternalEditorMinimapOptions): boolean { return ( a.enabled === b.enabled + && a.side === b.side && a.showSlider === b.showSlider && a.renderCharacters === b.renderCharacters && a.maxColumn === b.maxColumn @@ -1168,6 +1181,7 @@ export class InternalEditorOptions { && a.acceptSuggestionOnCommitCharacter === b.acceptSuggestionOnCommitCharacter && a.snippetSuggestions === b.snippetSuggestions && a.wordBasedSuggestions === b.wordBasedSuggestions + && a.selectSuggestions === b.selectSuggestions && a.suggestFontSize === b.suggestFontSize && a.suggestLineHeight === b.suggestLineHeight && a.selectionHighlight === b.selectionHighlight @@ -1288,6 +1302,10 @@ export interface EditorLayoutInfo { */ readonly contentHeight: number; + /** + * The position for the minimap + */ + readonly minimapLeft: number; /** * The width of the minimap */ @@ -1553,6 +1571,7 @@ export class EditorOptionsValidator { } return { enabled: _boolean(opts.enabled, defaults.enabled), + side: _stringSet<'right' | 'left'>(opts.side, defaults.side, ['right', 'left']), showSlider: _stringSet<'always' | 'mouseover'>(opts.showSlider, defaults.showSlider, ['always', 'mouseover']), renderCharacters: _boolean(opts.renderCharacters, defaults.renderCharacters), maxColumn: _clampedInt(opts.maxColumn, defaults.maxColumn, 1, 10000), @@ -1693,6 +1712,7 @@ export class EditorOptionsValidator { acceptSuggestionOnCommitCharacter: _boolean(opts.acceptSuggestionOnCommitCharacter, defaults.acceptSuggestionOnCommitCharacter), snippetSuggestions: _stringSet<'top' | 'bottom' | 'inline' | 'none'>(opts.snippetSuggestions, defaults.snippetSuggestions, ['top', 'bottom', 'inline', 'none']), wordBasedSuggestions: _boolean(opts.wordBasedSuggestions, defaults.wordBasedSuggestions), + selectSuggestions: _stringSet<'never' | 'byRecency' | 'byPrefix'>(opts.selectSuggestions, defaults.selectSuggestions, ['never', 'byRecency', 'byPrefix']), suggestFontSize: _clampedInt(opts.suggestFontSize, defaults.suggestFontSize, 0, 1000), suggestLineHeight: _clampedInt(opts.suggestLineHeight, defaults.suggestLineHeight, 0, 1000), selectionHighlight: _boolean(opts.selectionHighlight, defaults.selectionHighlight), @@ -1769,6 +1789,7 @@ export class InternalEditorOptionsFactory { scrollbar: opts.viewInfo.scrollbar, minimap: { enabled: (accessibilityIsOn ? false : opts.viewInfo.minimap.enabled), // DISABLED WHEN SCREEN READER IS ATTACHED + side: opts.viewInfo.minimap.side, renderCharacters: opts.viewInfo.minimap.renderCharacters, showSlider: opts.viewInfo.minimap.showSlider, maxColumn: opts.viewInfo.minimap.maxColumn @@ -1792,6 +1813,7 @@ export class InternalEditorOptionsFactory { acceptSuggestionOnCommitCharacter: opts.contribInfo.acceptSuggestionOnCommitCharacter, snippetSuggestions: opts.contribInfo.snippetSuggestions, wordBasedSuggestions: opts.contribInfo.wordBasedSuggestions, + selectSuggestions: opts.contribInfo.selectSuggestions, suggestFontSize: opts.contribInfo.suggestFontSize, suggestLineHeight: opts.contribInfo.suggestLineHeight, selectionHighlight: (accessibilityIsOn ? false : opts.contribInfo.selectionHighlight), // DISABLED WHEN SCREEN READER IS ATTACHED @@ -1850,6 +1872,7 @@ export class InternalEditorOptionsFactory { scrollbarArrowSize: opts.viewInfo.scrollbar.arrowSize, verticalScrollbarHasArrows: opts.viewInfo.scrollbar.verticalHasArrows, minimap: opts.viewInfo.minimap.enabled, + minimapSide: opts.viewInfo.minimap.side, minimapRenderCharacters: opts.viewInfo.minimap.renderCharacters, minimapMaxColumn: opts.viewInfo.minimap.maxColumn, pixelRatio: env.pixelRatio @@ -1982,6 +2005,7 @@ export interface IEditorLayoutProviderOpts { horizontalScrollbarHeight: number; minimap: boolean; + minimapSide: string; minimapRenderCharacters: boolean; minimapMaxColumn: number; pixelRatio: number; @@ -2007,6 +2031,7 @@ export class EditorLayoutProvider { const scrollbarArrowSize = _opts.scrollbarArrowSize | 0; const horizontalScrollbarHeight = _opts.horizontalScrollbarHeight | 0; const minimap = _opts.minimap; + const minimapSide = _opts.minimapSide; const minimapRenderCharacters = _opts.minimapRenderCharacters; const minimapMaxColumn = _opts.minimapMaxColumn | 0; const pixelRatio = _opts.pixelRatio; @@ -2022,17 +2047,19 @@ export class EditorLayoutProvider { glyphMarginWidth = lineHeight; } - const glyphMarginLeft = 0; - const lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; - const decorationsLeft = lineNumbersLeft + lineNumbersWidth; - const contentLeft = decorationsLeft + lineDecorationsWidth; + let glyphMarginLeft = 0; + let lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; + let decorationsLeft = lineNumbersLeft + lineNumbersWidth; + let contentLeft = decorationsLeft + lineDecorationsWidth; const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth; let renderMinimap: RenderMinimap; + let minimapLeft: number; let minimapWidth: number; let contentWidth: number; if (!minimap) { + minimapLeft = 0; minimapWidth = 0; renderMinimap = RenderMinimap.None; contentWidth = remainingWidth; @@ -2064,6 +2091,16 @@ export class EditorLayoutProvider { minimapWidth = Math.floor(minimapMaxColumn * minimapCharWidth); } contentWidth = remainingWidth - minimapWidth; + + if (minimapSide === 'left') { + minimapLeft = 0; + glyphMarginLeft += minimapWidth; + lineNumbersLeft += minimapWidth; + decorationsLeft += minimapWidth; + contentLeft += minimapWidth; + } else { + minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth; + } } const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth) / typicalHalfwidthCharacterWidth)); @@ -2091,6 +2128,7 @@ export class EditorLayoutProvider { contentHeight: outerHeight, renderMinimap: renderMinimap, + minimapLeft: minimapLeft, minimapWidth: minimapWidth, viewportColumn: viewportColumn, @@ -2206,6 +2244,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { }, minimap: { enabled: true, + side: 'right', showSlider: 'mouseover', renderCharacters: true, maxColumn: 120 @@ -2229,6 +2268,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { acceptSuggestionOnCommitCharacter: true, snippetSuggestions: 'inline', wordBasedSuggestions: true, + selectSuggestions: 'byRecency', suggestFontSize: 0, suggestLineHeight: 0, selectionHighlight: true, diff --git a/src/vs/editor/common/config/fontInfo.ts b/src/vs/editor/common/config/fontInfo.ts index af6a2d82873..24b105bbd4e 100644 --- a/src/vs/editor/common/config/fontInfo.ts +++ b/src/vs/editor/common/config/fontInfo.ts @@ -14,6 +14,16 @@ import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; */ const GOLDEN_LINE_HEIGHT_RATIO = platform.isMacintosh ? 1.5 : 1.35; +/** + * Font settings maximum and minimum limits + */ +const MINIMUM_FONT_SIZE = 8; +const MAXIMUM_FONT_SIZE = 100; +const MINIMUM_LINE_HEIGHT = 8; +const MAXIMUM_LINE_HEIGHT = 150; +const MINIMUM_LETTER_SPACING = -5; +const MAXIMUM_LETTER_SPACING = 20; + function safeParseFloat(n: number | string, defaultValue: number): number { if (typeof n === 'number') { return n; @@ -70,24 +80,25 @@ export class BareFontInfo { let fontFamily = _string(opts.fontFamily, EDITOR_FONT_DEFAULTS.fontFamily); let fontWeight = _string(opts.fontWeight, EDITOR_FONT_DEFAULTS.fontWeight); + let fontSize = safeParseFloat(opts.fontSize, EDITOR_FONT_DEFAULTS.fontSize); - fontSize = clamp(fontSize, 0, 100); + fontSize = clamp(fontSize, 0, MAXIMUM_FONT_SIZE); if (fontSize === 0) { fontSize = EDITOR_FONT_DEFAULTS.fontSize; - } else if (fontSize < 8) { - fontSize = 8; + } else if (fontSize < MINIMUM_FONT_SIZE) { + fontSize = MINIMUM_FONT_SIZE; } let lineHeight = safeParseInt(opts.lineHeight, 0); - lineHeight = clamp(lineHeight, 0, 150); + lineHeight = clamp(lineHeight, 0, MAXIMUM_LINE_HEIGHT); if (lineHeight === 0) { lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize); - } else if (lineHeight < 8) { - lineHeight = 8; + } else if (lineHeight < MINIMUM_LINE_HEIGHT) { + lineHeight = MINIMUM_LINE_HEIGHT; } let letterSpacing = safeParseFloat(opts.letterSpacing, 0); - letterSpacing = clamp(letterSpacing, -20, 20); + letterSpacing = clamp(letterSpacing, MINIMUM_LETTER_SPACING, MAXIMUM_LETTER_SPACING); let editorZoomLevelMultiplier = 1 + (EditorZoom.getZoomLevel() * 0.1); fontSize *= editorZoomLevelMultiplier; diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 88d2f566d95..bf3193748a5 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -92,6 +92,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { private readonly _configuration: editorCommon.IConfiguration; private readonly _model: ITextModel; + private _knownModelVersionId: number; private readonly _viewModel: IViewModel; public context: CursorContext; private _cursors: CursorCollection; @@ -105,6 +106,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { super(); this._configuration = configuration; this._model = model; + this._knownModelVersionId = this._model.getVersionId(); this._viewModel = viewModel; this.context = new CursorContext(this._configuration, this._model, this._viewModel); this._cursors = new CursorCollection(this.context); @@ -115,6 +117,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { this._prevEditOperationType = EditOperationType.Other; this._register(this._model.onDidChangeRawContent((e) => { + this._knownModelVersionId = e.versionId; if (this._isHandling) { return; } @@ -128,6 +131,16 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { return; } + if (this._knownModelVersionId !== this._model.getVersionId()) { + // There are model change events that I didn't yet receive. + // + // This can happen when editing the model, and the view model receives the change events first, + // and the view model emits line mapping changed events, all before the cursor gets a chance to + // recover from markers. + // + // The model change listener above will be called soon and we'll ensure a valid cursor state there. + return; + } // Ensure valid state this.setStates('viewModel', CursorChangeReason.NotSet, this.getAll()); })); @@ -136,13 +149,13 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { this.context = new CursorContext(this._configuration, this._model, this._viewModel); this._cursors.updateContext(this.context); }; - this._register(model.onDidChangeLanguage((e) => { + this._register(this._model.onDidChangeLanguage((e) => { updateCursorContext(); })); - this._register(model.onDidChangeLanguageConfiguration(() => { + this._register(this._model.onDidChangeLanguageConfiguration(() => { updateCursorContext(); })); - this._register(model.onDidChangeOptions(() => { + this._register(this._model.onDidChangeOptions(() => { updateCursorContext(); })); this._register(this._configuration.onDidChange((e) => { diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 9f25ed1118f..31f7b8be668 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -12,8 +12,9 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range, IRange } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { ModelRawContentChangedEvent, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelOptionsChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelContentChange, ModelRawChange } from 'vs/editor/common/model/textModelEvents'; +import { ModelRawContentChangedEvent, IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelOptionsChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelContentChange } from 'vs/editor/common/model/textModelEvents'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; /** * Vertical Lane in the overview ruler of the editor. @@ -499,6 +500,14 @@ export interface ITextModel { */ getValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string; + /** + * Get the text stored in this model. + * @param preserverBOM Preserve a BOM character if it was detected when the model was constructed. + * @return The text snapshot (it is safe to consume it asynchronously). + * @internal + */ + createSnapshot(preserveBOM?: boolean): ITextSnapshot; + /** * Get the length of the text stored in this model. */ @@ -1078,7 +1087,9 @@ export interface ITextBuffer { getRangeAt(offset: number, length: number): Range; getValueInRange(range: Range, eol: EndOfLinePreference): string; + createSnapshot(preserveBOM: boolean): ITextSnapshot; getValueLengthInRange(range: Range, eol: EndOfLinePreference): number; + getLength(): number; getLineCount(): number; getLinesContent(): string[]; getLineContent(lineNumber: number): string; @@ -1087,7 +1098,7 @@ export interface ITextBuffer { getLineFirstNonWhitespaceColumn(lineNumber: number): number; getLineLastNonWhitespaceColumn(lineNumber: number): number; - setEOL(newEOL: string): void; + setEOL(newEOL: '\r\n' | '\n'): void; applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult; } @@ -1098,7 +1109,6 @@ export class ApplyEditsResult { constructor( public readonly reverseEdits: IIdentifiedSingleEditOperation[], - public readonly rawChanges: ModelRawChange[], public readonly changes: IInternalModelContentChange[], public readonly trimAutoWhitespaceLineNumbers: number[] ) { } @@ -1110,7 +1120,6 @@ export class ApplyEditsResult { */ export interface IInternalModelContentChange extends IModelContentChange { range: Range; - lines: string[]; rangeOffset: number; forceMoveMarkers: boolean; } diff --git a/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts b/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts new file mode 100644 index 00000000000..53063409aea --- /dev/null +++ b/src/vs/editor/common/model/chunksTextBuffer/bufferPiece.ts @@ -0,0 +1,323 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { CharCode } from 'vs/base/common/charCode'; + +export class LeafOffsetLenEdit { + constructor( + public readonly start: number, + public readonly length: number, + public readonly text: string + ) { } +} + +export class BufferPiece { + private readonly _str: string; + public get text(): string { return this._str; } + + private readonly _lineStarts: Uint32Array; + + constructor(str: string, lineStarts: Uint32Array = null) { + this._str = str; + if (lineStarts === null) { + this._lineStarts = createLineStartsFast(str); + } else { + this._lineStarts = lineStarts; + } + } + + public length(): number { + return this._str.length; + } + + public newLineCount(): number { + return this._lineStarts.length; + } + + public lineStartFor(relativeLineIndex: number): number { + return this._lineStarts[relativeLineIndex]; + } + + public charCodeAt(index: number): number { + return this._str.charCodeAt(index); + } + + public substr(from: number, length: number): string { + return this._str.substr(from, length); + } + + public findLineStartBeforeOffset(offset: number): number { + if (this._lineStarts.length === 0 || offset < this._lineStarts[0]) { + return -1; + } + + let low = 0, high = this._lineStarts.length - 1; + + while (low < high) { + let mid = low + Math.ceil((high - low) / 2); + let lineStart = this._lineStarts[mid]; + + if (offset === lineStart) { + return mid; + } else if (offset < lineStart) { + high = mid - 1; + } else { + low = mid; + } + } + + return low; + } + + public findLineFirstNonWhitespaceIndex(searchStartOffset: number): number { + for (let i = searchStartOffset, len = this._str.length; i < len; i++) { + const chCode = this._str.charCodeAt(i); + if (chCode === CharCode.CarriageReturn || chCode === CharCode.LineFeed) { + // Reached EOL + return -2; + } + if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { + return i; + } + } + return -1; + } + + public findLineLastNonWhitespaceIndex(searchStartOffset: number): number { + for (let i = searchStartOffset - 1; i >= 0; i--) { + const chCode = this._str.charCodeAt(i); + if (chCode === CharCode.CarriageReturn || chCode === CharCode.LineFeed) { + // Reached EOL + return -2; + } + if (chCode !== CharCode.Space && chCode !== CharCode.Tab) { + return i; + } + } + return -1; + } + + public static normalizeEOL(target: BufferPiece, eol: '\r\n' | '\n'): BufferPiece { + return new BufferPiece(target._str.replace(/\r\n|\r|\n/g, eol)); + } + + public static deleteLastChar(target: BufferPiece): BufferPiece { + const targetCharsLength = target.length(); + const targetLineStartsLength = target.newLineCount(); + const targetLineStarts = target._lineStarts; + + let newLineStartsLength; + if (targetLineStartsLength > 0 && targetLineStarts[targetLineStartsLength - 1] === targetCharsLength) { + newLineStartsLength = targetLineStartsLength - 1; + } else { + newLineStartsLength = targetLineStartsLength; + } + + let newLineStarts = new Uint32Array(newLineStartsLength); + newLineStarts.set(targetLineStarts); + + return new BufferPiece( + target._str.substr(0, targetCharsLength - 1), + newLineStarts + ); + } + + public static insertFirstChar(target: BufferPiece, character: number): BufferPiece { + const targetLineStartsLength = target.newLineCount(); + const targetLineStarts = target._lineStarts; + const insertLineStart = ((character === CharCode.CarriageReturn && (targetLineStartsLength === 0 || targetLineStarts[0] !== 1 || target.charCodeAt(0) !== CharCode.LineFeed)) || (character === CharCode.LineFeed)); + + const newLineStartsLength = (insertLineStart ? targetLineStartsLength + 1 : targetLineStartsLength); + let newLineStarts = new Uint32Array(newLineStartsLength); + + if (insertLineStart) { + newLineStarts[0] = 1; + for (let i = 0; i < targetLineStartsLength; i++) { + newLineStarts[i + 1] = targetLineStarts[i] + 1; + } + } else { + for (let i = 0; i < targetLineStartsLength; i++) { + newLineStarts[i] = targetLineStarts[i] + 1; + } + } + + return new BufferPiece( + String.fromCharCode(character) + target._str, + newLineStarts + ); + } + + public static join(first: BufferPiece, second: BufferPiece): BufferPiece { + const firstCharsLength = first._str.length; + + const firstLineStartsLength = first._lineStarts.length; + const secondLineStartsLength = second._lineStarts.length; + + const firstLineStarts = first._lineStarts; + const secondLineStarts = second._lineStarts; + + const newLineStartsLength = firstLineStartsLength + secondLineStartsLength; + let newLineStarts = new Uint32Array(newLineStartsLength); + newLineStarts.set(firstLineStarts, 0); + for (let i = 0; i < secondLineStartsLength; i++) { + newLineStarts[i + firstLineStartsLength] = secondLineStarts[i] + firstCharsLength; + } + + return new BufferPiece(first._str + second._str, newLineStarts); + } + + public static replaceOffsetLen(target: BufferPiece, edits: LeafOffsetLenEdit[], idealLeafLength: number, maxLeafLength: number, result: BufferPiece[]): void { + const editsSize = edits.length; + const originalCharsLength = target.length(); + if (editsSize === 1 && edits[0].text.length === 0 && edits[0].start === 0 && edits[0].length === originalCharsLength) { + // special case => deleting everything + return; + } + + let pieces: string[] = new Array(2 * editsSize + 1); + let originalFromIndex = 0; + let piecesTextLength = 0; + for (let i = 0; i < editsSize; i++) { + const edit = edits[i]; + + const originalText = target._str.substr(originalFromIndex, edit.start - originalFromIndex); + pieces[2 * i] = originalText; + piecesTextLength += originalText.length; + + originalFromIndex = edit.start + edit.length; + pieces[2 * i + 1] = edit.text; + piecesTextLength += edit.text.length; + } + + // maintain the chars that survive to the right of the last edit + let text = target._str.substr(originalFromIndex, originalCharsLength - originalFromIndex); + pieces[2 * editsSize] = text; + piecesTextLength += text.length; + + let targetDataLength = piecesTextLength > maxLeafLength ? idealLeafLength : piecesTextLength; + let targetDataOffset = 0; + + let data: string = ''; + + for (let pieceIndex = 0, pieceCount = pieces.length; pieceIndex < pieceCount; pieceIndex++) { + const pieceText = pieces[pieceIndex]; + const pieceLength = pieceText.length; + if (pieceLength === 0) { + continue; + } + + let pieceOffset = 0; + while (pieceOffset < pieceLength) { + if (targetDataOffset >= targetDataLength) { + result.push(new BufferPiece(data)); + targetDataLength = piecesTextLength > maxLeafLength ? idealLeafLength : piecesTextLength; + targetDataOffset = 0; + data = ''; + } + + let writingCnt = min(pieceLength - pieceOffset, targetDataLength - targetDataOffset); + data += pieceText.substr(pieceOffset, writingCnt); + pieceOffset += writingCnt; + targetDataOffset += writingCnt; + piecesTextLength -= writingCnt; + + // check that the buffer piece does not end in a \r or high surrogate + if (targetDataOffset === targetDataLength && piecesTextLength > 0) { + const lastChar = data.charCodeAt(targetDataLength - 1); + if (lastChar === CharCode.CarriageReturn || (0xD800 <= lastChar && lastChar <= 0xDBFF)) { + // move lastChar over to next buffer piece + targetDataLength -= 1; + pieceOffset -= 1; + targetDataOffset -= 1; + piecesTextLength += 1; + data = data.substr(0, data.length - 1); + } + } + } + } + + result.push(new BufferPiece(data)); + } +} + +function min(a: number, b: number): number { + return (a < b ? a : b); +} + +export function createUint32Array(arr: number[]): Uint32Array { + let r = new Uint32Array(arr.length); + r.set(arr, 0); + return r; +} + +export class LineStarts { + constructor( + public readonly lineStarts: Uint32Array, + public readonly cr: number, + public readonly lf: number, + public readonly crlf: number, + public readonly isBasicASCII: boolean + ) { } +} + +export function createLineStartsFast(str: string): Uint32Array { + let r: number[] = [], rLength = 0; + for (let i = 0, len = str.length; i < len; i++) { + const chr = str.charCodeAt(i); + + if (chr === CharCode.CarriageReturn) { + if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { + // \r\n... case + r[rLength++] = i + 2; + i++; // skip \n + } else { + // \r... case + r[rLength++] = i + 1; + } + } else if (chr === CharCode.LineFeed) { + r[rLength++] = i + 1; + } + } + return createUint32Array(r); +} + +export function createLineStarts(r: number[], str: string): LineStarts { + r.length = 0; + + let rLength = 0; + let cr = 0, lf = 0, crlf = 0; + let isBasicASCII = true; + for (let i = 0, len = str.length; i < len; i++) { + const chr = str.charCodeAt(i); + + if (chr === CharCode.CarriageReturn) { + if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { + // \r\n... case + crlf++; + r[rLength++] = i + 2; + i++; // skip \n + } else { + cr++; + // \r... case + r[rLength++] = i + 1; + } + } else if (chr === CharCode.LineFeed) { + lf++; + r[rLength++] = i + 1; + } else { + if (isBasicASCII) { + if (chr !== CharCode.Tab && (chr < 32 || chr > 126)) { + isBasicASCII = false; + } + } + } + } + + const result = new LineStarts(createUint32Array(r), cr, lf, crlf, isBasicASCII); + r.length = 0; + + return result; +} diff --git a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts new file mode 100644 index 00000000000..046f3387ea5 --- /dev/null +++ b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBuffer.ts @@ -0,0 +1,1526 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { CharCode } from 'vs/base/common/charCode'; +import { ITextBuffer, EndOfLinePreference, IIdentifiedSingleEditOperation, ApplyEditsResult, ISingleEditOperationIdentifier, IInternalModelContentChange } from 'vs/editor/common/model'; +import { BufferPiece, LeafOffsetLenEdit } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; +import { Position } from 'vs/editor/common/core/position'; +import { Range } from 'vs/editor/common/core/range'; +import * as strings from 'vs/base/common/strings'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; + +export interface IValidatedEditOperation { + sortIndex: number; + identifier: ISingleEditOperationIdentifier; + range: Range; + rangeOffset: number; + rangeLength: number; + lines: string[]; + forceMoveMarkers: boolean; + isAutoWhitespaceEdit: boolean; +} + +export class ChunksTextBuffer implements ITextBuffer { + + private _BOM: string; + private _actual: Buffer; + private _mightContainRTL: boolean; + private _mightContainNonBasicASCII: boolean; + + constructor(pieces: BufferPiece[], _averageChunkSize: number, BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, isBasicASCII: boolean) { + this._BOM = BOM; + const averageChunkSize = Math.floor(Math.min(65536.0, Math.max(128.0, _averageChunkSize))); + const delta = Math.floor(averageChunkSize / 3); + const min = averageChunkSize - delta; + const max = 2 * min; + this._actual = new Buffer(pieces, min, max, eol); + this._mightContainRTL = containsRTL; + this._mightContainNonBasicASCII = !isBasicASCII; + } + + equals(other: ITextBuffer): boolean { + if (!(other instanceof ChunksTextBuffer)) { + return false; + } + return this._actual.equals(other._actual); + } + mightContainRTL(): boolean { + return this._mightContainRTL; + } + mightContainNonBasicASCII(): boolean { + return this._mightContainNonBasicASCII; + } + getBOM(): string { + return this._BOM; + } + getEOL(): string { + return this._actual.getEOL(); + } + getOffsetAt(lineNumber: number, column: number): number { + return this._actual.convertPositionToOffset(lineNumber, column); + } + getPositionAt(offset: number): Position { + return this._actual.convertOffsetToPosition(offset); + } + getRangeAt(offset: number, length: number): Range { + return this._actual.convertOffsetLenToRange(offset, length); + } + getValueInRange(range: Range, eol: EndOfLinePreference): string { + if (range.isEmpty()) { + return ''; + } + + const text = this._actual.getValueInRange(range); + switch (eol) { + case EndOfLinePreference.TextDefined: + return text; + case EndOfLinePreference.LF: + if (this.getEOL() === '\n') { + return text; + } else { + return text.replace(/\r\n/g, '\n'); + } + case EndOfLinePreference.CRLF: + if (this.getEOL() === '\r\n') { + return text; + } else { + return text.replace(/\n/g, '\r\n'); + } + } + return null; + } + + public createSnapshot(preserveBOM: boolean): ITextSnapshot { + return this._actual.createSnapshot(preserveBOM ? this._BOM : ''); + } + + getValueLengthInRange(range: Range, eol: EndOfLinePreference): number { + if (range.isEmpty()) { + return 0; + } + const eolCount = range.endLineNumber - range.startLineNumber; + const result = this._actual.getValueLengthInRange(range); + switch (eol) { + case EndOfLinePreference.TextDefined: + return result; + case EndOfLinePreference.LF: + if (this.getEOL() === '\n') { + return result; + } else { + return result - eolCount; // \r\n => \n + } + case EndOfLinePreference.CRLF: + if (this.getEOL() === '\r\n') { + return result; + } else { + return result + eolCount; // \n => \r\n + } + } + return 0; + } + + public getLength(): number { + return this._actual.getLength(); + } + + getLineCount(): number { + return this._actual.getLineCount(); + } + + getLinesContent(): string[] { + return this._actual.getLinesContent(); + } + + getLineContent(lineNumber: number): string { + return this._actual.getLineContent(lineNumber); + } + + getLineCharCode(lineNumber: number, index: number): number { + return this._actual.getLineCharCode(lineNumber, index); + } + + getLineLength(lineNumber: number): number { + return this._actual.getLineLength(lineNumber); + } + + getLineFirstNonWhitespaceColumn(lineNumber: number): number { + const result = this._actual.getLineFirstNonWhitespaceIndex(lineNumber); + if (result === -1) { + return 0; + } + return result + 1; + } + getLineLastNonWhitespaceColumn(lineNumber: number): number { + const result = this._actual.getLineLastNonWhitespaceIndex(lineNumber); + if (result === -1) { + return 0; + } + return result + 1; + } + setEOL(newEOL: '\r\n' | '\n'): void { + if (this.getEOL() === newEOL) { + // nothing to do... + return; + } + this._actual.setEOL(newEOL); + } + + private static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { + let r = Range.compareRangesUsingEnds(a.range, b.range); + if (r === 0) { + return a.sortIndex - b.sortIndex; + } + return r; + } + + private static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { + let r = Range.compareRangesUsingEnds(a.range, b.range); + if (r === 0) { + return b.sortIndex - a.sortIndex; + } + return -r; + } + + applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { + if (rawOperations.length === 0) { + return new ApplyEditsResult([], [], []); + } + + let mightContainRTL = this._mightContainRTL; + let mightContainNonBasicASCII = this._mightContainNonBasicASCII; + let canReduceOperations = true; + + let operations: IValidatedEditOperation[] = []; + for (let i = 0; i < rawOperations.length; i++) { + let op = rawOperations[i]; + if (canReduceOperations && op._isTracked) { + canReduceOperations = false; + } + let validatedRange = op.range; + if (!mightContainRTL && op.text) { + // check if the new inserted text contains RTL + mightContainRTL = strings.containsRTL(op.text); + } + if (!mightContainNonBasicASCII && op.text) { + mightContainNonBasicASCII = !strings.isBasicASCII(op.text); + } + operations[i] = { + sortIndex: i, + identifier: op.identifier || null, + range: validatedRange, + rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), + rangeLength: this.getValueLengthInRange(validatedRange, EndOfLinePreference.TextDefined), + lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, + forceMoveMarkers: op.forceMoveMarkers || false, + isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false + }; + } + + // Sort operations ascending + operations.sort(ChunksTextBuffer._sortOpsAscending); + + for (let i = 0, count = operations.length - 1; i < count; i++) { + let rangeEnd = operations[i].range.getEndPosition(); + let nextRangeStart = operations[i + 1].range.getStartPosition(); + + if (nextRangeStart.isBefore(rangeEnd)) { + // overlapping ranges + throw new Error('Overlapping ranges are not allowed!'); + } + } + + if (canReduceOperations) { + operations = this._reduceOperations(operations); + } + + // Delta encode operations + let reverseRanges = ChunksTextBuffer._getInverseEditRanges(operations); + let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = []; + + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + let reverseRange = reverseRanges[i]; + + if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) { + // Record already the future line numbers that might be auto whitespace removal candidates on next edit + for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { + let currentLineContent = ''; + if (lineNumber === reverseRange.startLineNumber) { + currentLineContent = this.getLineContent(op.range.startLineNumber); + if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { + continue; + } + } + newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); + } + } + } + + let reverseOperations: IIdentifiedSingleEditOperation[] = []; + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + let reverseRange = reverseRanges[i]; + + reverseOperations[i] = { + identifier: op.identifier, + range: reverseRange, + text: this.getValueInRange(op.range, EndOfLinePreference.TextDefined), + forceMoveMarkers: op.forceMoveMarkers + }; + } + + this._mightContainRTL = mightContainRTL; + this._mightContainNonBasicASCII = mightContainNonBasicASCII; + + const contentChanges = this._doApplyEdits(operations); + + let trimAutoWhitespaceLineNumbers: number[] = null; + if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { + // sort line numbers auto whitespace removal candidates for next edit descending + newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber); + + trimAutoWhitespaceLineNumbers = []; + for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) { + let lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber; + if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) { + // Do not have the same line number twice + continue; + } + + let prevContent = newTrimAutoWhitespaceCandidates[i].oldContent; + let lineContent = this.getLineContent(lineNumber); + + if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) { + continue; + } + + trimAutoWhitespaceLineNumbers.push(lineNumber); + } + } + + return new ApplyEditsResult( + reverseOperations, + contentChanges, + trimAutoWhitespaceLineNumbers + ); + } + + /** + * Transform operations such that they represent the same logic edit, + * but that they also do not cause OOM crashes. + */ + private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] { + if (operations.length < 1000) { + // We know from empirical testing that a thousand edits work fine regardless of their shape. + return operations; + } + + // At one point, due to how events are emitted and how each operation is handled, + // some operations can trigger a high ammount of temporary string allocations, + // that will immediately get edited again. + // e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line + // Therefore, the strategy is to collapse all the operations into a huge single edit operation + return [this._toSingleEditOperation(operations)]; + } + + _toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation { + let forceMoveMarkers = false, + firstEditRange = operations[0].range, + lastEditRange = operations[operations.length - 1].range, + entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn), + lastEndLineNumber = firstEditRange.startLineNumber, + lastEndColumn = firstEditRange.startColumn, + result: string[] = []; + + for (let i = 0, len = operations.length; i < len; i++) { + let operation = operations[i], + range = operation.range; + + forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers; + + // (1) -- Push old text + for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) { + if (lineNumber === lastEndLineNumber) { + result.push(this.getLineContent(lineNumber).substring(lastEndColumn - 1)); + } else { + result.push('\n'); + result.push(this.getLineContent(lineNumber)); + } + } + + if (range.startLineNumber === lastEndLineNumber) { + result.push(this.getLineContent(range.startLineNumber).substring(lastEndColumn - 1, range.startColumn - 1)); + } else { + result.push('\n'); + result.push(this.getLineContent(range.startLineNumber).substring(0, range.startColumn - 1)); + } + + // (2) -- Push new text + if (operation.lines) { + for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) { + if (j !== 0) { + result.push('\n'); + } + result.push(operation.lines[j]); + } + } + + lastEndLineNumber = operation.range.endLineNumber; + lastEndColumn = operation.range.endColumn; + } + + return { + sortIndex: 0, + identifier: operations[0].identifier, + range: entireEditRange, + rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), + rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined), + lines: result.join('').split('\n'), + forceMoveMarkers: forceMoveMarkers, + isAutoWhitespaceEdit: false + }; + } + + private _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] { + + // Sort operations descending + operations.sort(ChunksTextBuffer._sortOpsDescending); + + let contentChanges: IInternalModelContentChange[] = []; + let edits: OffsetLenEdit[] = []; + + for (let i = 0, len = operations.length; i < len; i++) { + const op = operations[i]; + + const text = (op.lines ? op.lines.join(this.getEOL()) : ''); + edits[i] = new OffsetLenEdit(op.sortIndex, op.rangeOffset, op.rangeLength, text); + + const startLineNumber = op.range.startLineNumber; + const startColumn = op.range.startColumn; + const endLineNumber = op.range.endLineNumber; + const endColumn = op.range.endColumn; + + if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) { + // no-op + continue; + } + + contentChanges.push({ + range: op.range, + rangeLength: op.rangeLength, + text: text, + rangeOffset: op.rangeOffset, + forceMoveMarkers: op.forceMoveMarkers + }); + } + + this._actual.replaceOffsetLen(edits); + + return contentChanges; + } + + /** + * Assumes `operations` are validated and sorted ascending + */ + public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] { + let result: Range[] = []; + + let prevOpEndLineNumber: number; + let prevOpEndColumn: number; + let prevOp: IValidatedEditOperation = null; + for (let i = 0, len = operations.length; i < len; i++) { + let op = operations[i]; + + let startLineNumber: number; + let startColumn: number; + + if (prevOp) { + if (prevOp.range.endLineNumber === op.range.startLineNumber) { + startLineNumber = prevOpEndLineNumber; + startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn); + } else { + startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber); + startColumn = op.range.startColumn; + } + } else { + startLineNumber = op.range.startLineNumber; + startColumn = op.range.startColumn; + } + + let resultRange: Range; + + if (op.lines && op.lines.length > 0) { + // the operation inserts something + let lineCount = op.lines.length; + let firstLine = op.lines[0]; + let lastLine = op.lines[lineCount - 1]; + + if (lineCount === 1) { + // single line insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length); + } else { + // multi line insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1); + } + } else { + // There is nothing to insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn); + } + + prevOpEndLineNumber = resultRange.endLineNumber; + prevOpEndColumn = resultRange.endColumn; + + result.push(resultRange); + prevOp = op; + } + + return result; + } +} + + +class BufferNodes { + + public length: Uint32Array; + public newLineCount: Uint32Array; + + constructor(count: number) { + this.length = new Uint32Array(count); + this.newLineCount = new Uint32Array(count); + } + +} + +class BufferCursor { + constructor( + public offset: number, + public leafIndex: number, + public leafStartOffset: number, + public leafStartNewLineCount: number + ) { } + + public set(offset: number, leafIndex: number, leafStartOffset: number, leafStartNewLineCount: number) { + this.offset = offset; + this.leafIndex = leafIndex; + this.leafStartOffset = leafStartOffset; + this.leafStartNewLineCount = leafStartNewLineCount; + } +} + +class OffsetLenEdit { + constructor( + public readonly initialIndex: number, + public readonly offset: number, + public length: number, + public text: string + ) { } +} + +class InternalOffsetLenEdit { + constructor( + public readonly startLeafIndex: number, + public readonly startInnerOffset: number, + public readonly endLeafIndex: number, + public readonly endInnerOffset: number, + public text: string + ) { } +} + +class LeafReplacement { + constructor( + public readonly startLeafIndex: number, + public readonly endLeafIndex: number, + public readonly replacements: BufferPiece[] + ) { } +} + +const BUFFER_CURSOR_POOL_SIZE = 10; +const BufferCursorPool = new class { + private _pool: BufferCursor[]; + private _len: number; + + constructor() { + this._pool = []; + for (let i = 0; i < BUFFER_CURSOR_POOL_SIZE; i++) { + this._pool[i] = new BufferCursor(0, 0, 0, 0); + } + this._len = this._pool.length; + } + + public put(cursor: BufferCursor): void { + if (this._len > this._pool.length) { + // oh, well + return; + } + this._pool[this._len++] = cursor; + } + + public take(): BufferCursor { + if (this._len === 0) { + // oh, well + console.log(`insufficient BufferCursor pool`); + return new BufferCursor(0, 0, 0, 0); + } + const result = this._pool[this._len - 1]; + this._pool[this._len--] = null; + return result; + } +}; + +class BufferSnapshot implements ITextSnapshot { + + private readonly _pieces: BufferPiece[]; + private readonly _piecesLength: number; + private readonly _BOM: string; + private _piecesIndex: number; + + constructor(pieces: BufferPiece[], BOM: string) { + this._pieces = pieces; + this._piecesLength = this._pieces.length; + this._BOM = BOM; + this._piecesIndex = 0; + } + + public read(): string { + if (this._piecesIndex >= this._piecesLength) { + return null; + } + + let result: string = null; + if (this._piecesIndex === 0) { + result = this._BOM + this._pieces[this._piecesIndex].text; + } else { + result = this._pieces[this._piecesIndex].text; + } + + this._piecesIndex++; + return result; + } +} + +class Buffer { + + private _minLeafLength: number; + private _maxLeafLength: number; + private _idealLeafLength: number; + + private _eol: '\r\n' | '\n'; + private _eolLength: number; + + private _leafs: BufferPiece[]; + private _nodes: BufferNodes; + private _nodesCount: number; + private _leafsStart: number; + private _leafsEnd: number; + + constructor(pieces: BufferPiece[], minLeafLength: number, maxLeafLength: number, eol: '\r\n' | '\n') { + if (!(2 * minLeafLength >= maxLeafLength)) { + throw new Error(`assertion violation`); + } + + this._minLeafLength = minLeafLength; + this._maxLeafLength = maxLeafLength; + this._idealLeafLength = (minLeafLength + maxLeafLength) >>> 1; + + this._eol = eol; + this._eolLength = this._eol.length; + + this._leafs = pieces; + this._nodes = null; + this._nodesCount = 0; + this._leafsStart = 0; + this._leafsEnd = 0; + + this._rebuildNodes(); + } + + equals(other: Buffer): boolean { + return Buffer.equals(this, other); + } + + private static equals(a: Buffer, b: Buffer): boolean { + const aLength = a.getLength(); + const bLength = b.getLength(); + if (aLength !== bLength) { + return false; + } + if (a.getLineCount() !== b.getLineCount()) { + return false; + } + + let remaining = aLength; + let aLeafIndex = -1, aLeaf = null, aLeafLength = 0, aLeafRemaining = 0; + let bLeafIndex = -1, bLeaf = null, bLeafLength = 0, bLeafRemaining = 0; + + while (remaining > 0) { + if (aLeafRemaining === 0) { + aLeafIndex++; + aLeaf = a._leafs[aLeafIndex]; + aLeafLength = aLeaf.length(); + aLeafRemaining = aLeafLength; + } + + if (bLeafRemaining === 0) { + bLeafIndex++; + bLeaf = b._leafs[bLeafIndex]; + bLeafLength = bLeaf.length(); + bLeafRemaining = bLeafLength; + } + + let consuming = Math.min(aLeafRemaining, bLeafRemaining); + + let aStr = aLeaf.substr(aLeafLength - aLeafRemaining, consuming); + let bStr = bLeaf.substr(bLeafLength - bLeafRemaining, consuming); + + if (aStr !== bStr) { + return false; + } + + remaining -= consuming; + aLeafRemaining -= consuming; + bLeafRemaining -= consuming; + } + + return true; + } + + public getEOL(): string { + return this._eol; + } + + private _rebuildNodes() { + const leafsCount = this._leafs.length; + + this._nodesCount = (1 << log2(leafsCount)); + this._leafsStart = this._nodesCount; + this._leafsEnd = this._leafsStart + leafsCount; + + this._nodes = new BufferNodes(this._nodesCount); + for (let i = this._nodesCount - 1; i >= 1; i--) { + this._updateSingleNode(i); + } + } + + private _updateSingleNode(nodeIndex: number): void { + const left = LEFT_CHILD(nodeIndex); + const right = RIGHT_CHILD(nodeIndex); + + let length = 0; + let newLineCount = 0; + + if (this.IS_NODE(left)) { + length += this._nodes.length[left]; + newLineCount += this._nodes.newLineCount[left]; + } else if (this.IS_LEAF(left)) { + const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; + length += leaf.length(); + newLineCount += leaf.newLineCount(); + } + + if (this.IS_NODE(right)) { + length += this._nodes.length[right]; + newLineCount += this._nodes.newLineCount[right]; + } else if (this.IS_LEAF(right)) { + const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(right)]; + length += leaf.length(); + newLineCount += leaf.newLineCount(); + } + + this._nodes.length[nodeIndex] = length; + this._nodes.newLineCount[nodeIndex] = newLineCount; + } + + private _findOffset(offset: number, result: BufferCursor): boolean { + if (offset > this._nodes.length[1]) { + return false; + } + + let it = 1; + let searchOffset = offset; + let leafStartOffset = 0; + let leafStartNewLineCount = 0; + while (!this.IS_LEAF(it)) { + const left = LEFT_CHILD(it); + const right = RIGHT_CHILD(it); + + let leftNewLineCount = 0; + let leftLength = 0; + if (this.IS_NODE(left)) { + leftNewLineCount = this._nodes.newLineCount[left]; + leftLength = this._nodes.length[left]; + } else if (this.IS_LEAF(left)) { + const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; + leftNewLineCount = leaf.newLineCount(); + leftLength = leaf.length(); + } + + let rightLength = 0; + if (this.IS_NODE(right)) { + rightLength += this._nodes.length[right]; + } else if (this.IS_LEAF(right)) { + rightLength += this._leafs[this.NODE_TO_LEAF_INDEX(right)].length(); + } + + if (searchOffset < leftLength || rightLength === 0) { + // go left + it = left; + } else { + // go right + searchOffset -= leftLength; + leafStartOffset += leftLength; + leafStartNewLineCount += leftNewLineCount; + it = right; + } + } + it = this.NODE_TO_LEAF_INDEX(it); + + result.set(offset, it, leafStartOffset, leafStartNewLineCount); + return true; + } + + private _findOffsetCloseAfter(offset: number, start: BufferCursor, result: BufferCursor): boolean { + if (offset > this._nodes.length[1]) { + return false; + } + + let innerOffset = offset - start.leafStartOffset; + const leafsCount = this._leafs.length; + + let leafIndex = start.leafIndex; + let leafStartOffset = start.leafStartOffset; + let leafStartNewLineCount = start.leafStartNewLineCount; + + while (true) { + const leaf = this._leafs[leafIndex]; + + if (innerOffset < leaf.length() || (innerOffset === leaf.length() && leafIndex + 1 === leafsCount)) { + result.set(offset, leafIndex, leafStartOffset, leafStartNewLineCount); + return true; + } + + leafIndex++; + + if (leafIndex >= leafsCount) { + result.set(offset, leafIndex, leafStartOffset, leafStartNewLineCount); + return true; + } + + leafStartOffset += leaf.length(); + leafStartNewLineCount += leaf.newLineCount(); + innerOffset -= leaf.length(); + } + } + + private _findLineStart(lineNumber: number, result: BufferCursor): boolean { + let lineIndex = lineNumber - 1; + if (lineIndex < 0 || lineIndex > this._nodes.newLineCount[1]) { + result.set(0, 0, 0, 0); + return false; + } + + let it = 1; + let leafStartOffset = 0; + let leafStartNewLineCount = 0; + while (!this.IS_LEAF(it)) { + const left = LEFT_CHILD(it); + const right = RIGHT_CHILD(it); + + let leftNewLineCount = 0; + let leftLength = 0; + if (this.IS_NODE(left)) { + leftNewLineCount = this._nodes.newLineCount[left]; + leftLength = this._nodes.length[left]; + } else if (this.IS_LEAF(left)) { + const leaf = this._leafs[this.NODE_TO_LEAF_INDEX(left)]; + leftNewLineCount = leaf.newLineCount(); + leftLength = leaf.length(); + } + + if (lineIndex <= leftNewLineCount) { + // go left + it = left; + continue; + } + + // go right + lineIndex -= leftNewLineCount; + leafStartOffset += leftLength; + leafStartNewLineCount += leftNewLineCount; + it = right; + } + it = this.NODE_TO_LEAF_INDEX(it); + + const innerLineStartOffset = (lineIndex === 0 ? 0 : this._leafs[it].lineStartFor(lineIndex - 1)); + + result.set(leafStartOffset + innerLineStartOffset, it, leafStartOffset, leafStartNewLineCount); + return true; + } + + private _findLineEnd(start: BufferCursor, lineNumber: number, result: BufferCursor): void { + let innerLineIndex = lineNumber - 1 - start.leafStartNewLineCount; + const leafsCount = this._leafs.length; + + let leafIndex = start.leafIndex; + let leafStartOffset = start.leafStartOffset; + let leafStartNewLineCount = start.leafStartNewLineCount; + while (true) { + const leaf = this._leafs[leafIndex]; + + if (innerLineIndex < leaf.newLineCount()) { + const lineEndOffset = this._leafs[leafIndex].lineStartFor(innerLineIndex); + result.set(leafStartOffset + lineEndOffset, leafIndex, leafStartOffset, leafStartNewLineCount); + return; + } + + leafIndex++; + + if (leafIndex >= leafsCount) { + result.set(leafStartOffset + leaf.length(), leafIndex - 1, leafStartOffset, leafStartNewLineCount); + return; + } + + leafStartOffset += leaf.length(); + leafStartNewLineCount += leaf.newLineCount(); + innerLineIndex = 0; + } + } + + private _findLine(lineNumber: number, start: BufferCursor, end: BufferCursor): boolean { + if (!this._findLineStart(lineNumber, start)) { + return false; + } + + this._findLineEnd(start, lineNumber, end); + return true; + } + + public getLength(): number { + return this._nodes.length[1]; + } + + public getLineCount(): number { + return this._nodes.newLineCount[1] + 1; + } + + public getLineContent(lineNumber: number): string { + const start = BufferCursorPool.take(); + const end = BufferCursorPool.take(); + + if (!this._findLine(lineNumber, start, end)) { + BufferCursorPool.put(start); + BufferCursorPool.put(end); + throw new Error(`Line not found`); + } + + let result: string; + if (lineNumber === this.getLineCount()) { + // last line is not trailed by an eol + result = this.extractString(start, end.offset - start.offset); + } else { + result = this.extractString(start, end.offset - start.offset - this._eolLength); + } + + BufferCursorPool.put(start); + BufferCursorPool.put(end); + return result; + } + + public getLineCharCode(lineNumber: number, index: number): number { + const start = BufferCursorPool.take(); + + if (!this._findLineStart(lineNumber, start)) { + BufferCursorPool.put(start); + throw new Error(`Line not found`); + } + + const tmp = BufferCursorPool.take(); + this._findOffsetCloseAfter(start.offset + index, start, tmp); + const result = this._leafs[tmp.leafIndex].charCodeAt(tmp.offset - tmp.leafStartNewLineCount); + BufferCursorPool.put(tmp); + + BufferCursorPool.put(start); + return result; + } + + public getLineLength(lineNumber: number): number { + const start = BufferCursorPool.take(); + const end = BufferCursorPool.take(); + + if (!this._findLine(lineNumber, start, end)) { + BufferCursorPool.put(start); + BufferCursorPool.put(end); + throw new Error(`Line not found`); + } + + let result: number; + if (lineNumber === this.getLineCount()) { + // last line is not trailed by an eol + result = end.offset - start.offset; + } else { + result = end.offset - start.offset - this._eolLength; + } + + BufferCursorPool.put(start); + BufferCursorPool.put(end); + return result; + } + + public getLineFirstNonWhitespaceIndex(lineNumber: number): number { + const start = BufferCursorPool.take(); + + if (!this._findLineStart(lineNumber, start)) { + BufferCursorPool.put(start); + throw new Error(`Line not found`); + } + + let leafIndex = start.leafIndex; + let searchStartOffset = start.offset - start.leafStartOffset; + BufferCursorPool.put(start); + + const leafsCount = this._leafs.length; + let totalDelta = 0; + while (true) { + const leaf = this._leafs[leafIndex]; + + const leafResult = leaf.findLineFirstNonWhitespaceIndex(searchStartOffset); + if (leafResult === -2) { + // reached EOL + return -1; + } + if (leafResult !== -1) { + return (leafResult - searchStartOffset) + totalDelta; + } + + leafIndex++; + + if (leafIndex >= leafsCount) { + return -1; + } + + totalDelta += (leaf.length() - searchStartOffset); + searchStartOffset = 0; + } + } + + public getLineLastNonWhitespaceIndex(lineNumber: number): number { + const start = BufferCursorPool.take(); + const end = BufferCursorPool.take(); + + if (!this._findLineStart(lineNumber, start)) { + BufferCursorPool.put(start); + BufferCursorPool.put(end); + throw new Error(`Line not found`); + } + + this._findLineEnd(start, lineNumber, end); + + const startOffset = start.offset; + const endOffset = end.offset; + let leafIndex = end.leafIndex; + let searchStartOffset = end.offset - end.leafStartOffset - this._eolLength; + + BufferCursorPool.put(start); + BufferCursorPool.put(end); + + let totalDelta = 0; + while (true) { + const leaf = this._leafs[leafIndex]; + + const leafResult = leaf.findLineLastNonWhitespaceIndex(searchStartOffset); + if (leafResult === -2) { + // reached EOL + return -1; + } + if (leafResult !== -1) { + const delta = (searchStartOffset - 1 - leafResult); + const absoluteOffset = (endOffset - this._eolLength) - delta - totalDelta; + return absoluteOffset - startOffset; + } + + leafIndex--; + + if (leafIndex < 0) { + return -1; + } + + totalDelta += searchStartOffset; + searchStartOffset = leaf.length(); + } + } + + public getLinesContent(): string[] { + let result: string[] = new Array(this.getLineCount()); + let resultIndex = 0; + + let currentLine = ''; + for (let leafIndex = 0, leafsCount = this._leafs.length; leafIndex < leafsCount; leafIndex++) { + const leaf = this._leafs[leafIndex]; + const leafNewLineCount = leaf.newLineCount(); + + if (leafNewLineCount === 0) { + // special case => push entire leaf text + currentLine += leaf.text; + continue; + } + + let leafSubstrOffset = 0; + for (let newLineIndex = 0; newLineIndex < leafNewLineCount; newLineIndex++) { + const newLineStart = leaf.lineStartFor(newLineIndex); + currentLine += leaf.substr(leafSubstrOffset, newLineStart - leafSubstrOffset - this._eolLength); + result[resultIndex++] = currentLine; + + currentLine = ''; + leafSubstrOffset = newLineStart; + } + currentLine += leaf.substr(leafSubstrOffset, leaf.length()); + } + result[resultIndex++] = currentLine; + + return result; + } + + public extractString(start: BufferCursor, len: number): string { + if (!(start.offset + len <= this._nodes.length[1])) { + throw new Error(`assertion violation`); + } + + let innerLeafOffset = start.offset - start.leafStartOffset; + let leafIndex = start.leafIndex; + let res = ''; + while (len > 0) { + const leaf = this._leafs[leafIndex]; + const cnt = Math.min(len, leaf.length() - innerLeafOffset); + res += leaf.substr(innerLeafOffset, cnt); + + len -= cnt; + innerLeafOffset = 0; + + if (len === 0) { + break; + } + + leafIndex++; + } + return res; + } + + private _getOffsetAt(lineNumber: number, column: number, result: BufferCursor): boolean { + const lineStart = BufferCursorPool.take(); + + if (!this._findLineStart(lineNumber, lineStart)) { + BufferCursorPool.put(lineStart); + return false; + } + + const startOffset = lineStart.offset + column - 1; + if (!this._findOffsetCloseAfter(startOffset, lineStart, result)) { + BufferCursorPool.put(lineStart); + return false; + } + + BufferCursorPool.put(lineStart); + return true; + } + + public convertPositionToOffset(lineNumber: number, column: number): number { + const r = BufferCursorPool.take(); + + if (!this._findLineStart(lineNumber, r)) { + BufferCursorPool.put(r); + throw new Error(`Position not found`); + } + + const result = r.offset + column - 1; + + BufferCursorPool.put(r); + return result; + } + + /** + * returns `lineNumber` + */ + private _findLineStartBeforeOffsetInLeaf(offset: number, leafIndex: number, leafStartOffset: number, leafStartNewLineCount: number, result: BufferCursor): number { + const leaf = this._leafs[leafIndex]; + const lineStartIndex = leaf.findLineStartBeforeOffset(offset - leafStartOffset); + const lineStartOffset = leafStartOffset + leaf.lineStartFor(lineStartIndex); + + result.set(lineStartOffset, leafIndex, leafStartOffset, leafStartNewLineCount); + return leafStartNewLineCount + lineStartIndex + 2; + } + + /** + * returns `lineNumber`. + */ + private _findLineStartBeforeOffset(offset: number, location: BufferCursor, result: BufferCursor): number { + + let leafIndex = location.leafIndex; + let leafStartOffset = location.leafStartOffset; + let leafStartNewLineCount = location.leafStartNewLineCount; + while (true) { + const leaf = this._leafs[leafIndex]; + + if (leaf.newLineCount() >= 1 && leaf.lineStartFor(0) + leafStartOffset <= offset) { + // must be in this leaf + return this._findLineStartBeforeOffsetInLeaf(offset, leafIndex, leafStartOffset, leafStartNewLineCount, result); + } + + // continue looking in previous leaf + leafIndex--; + + if (leafIndex < 0) { + result.set(0, 0, 0, 0); + return 1; + } + + leafStartOffset -= this._leafs[leafIndex].length(); + leafStartNewLineCount -= this._leafs[leafIndex].newLineCount(); + } + } + + public convertOffsetToPosition(offset: number): Position { + const r = BufferCursorPool.take(); + const lineStart = BufferCursorPool.take(); + + if (!this._findOffset(offset, r)) { + BufferCursorPool.put(r); + BufferCursorPool.put(lineStart); + throw new Error(`Offset not found`); + } + + const lineNumber = this._findLineStartBeforeOffset(offset, r, lineStart); + const column = offset - lineStart.offset + 1; + + BufferCursorPool.put(r); + BufferCursorPool.put(lineStart); + + return new Position(lineNumber, column); + } + + public convertOffsetLenToRange(offset: number, len: number): Range { + const r = BufferCursorPool.take(); + const lineStart = BufferCursorPool.take(); + + if (!this._findOffset(offset, r)) { + BufferCursorPool.put(r); + BufferCursorPool.put(lineStart); + throw new Error(`Offset not found`); + } + const startLineNumber = this._findLineStartBeforeOffset(offset, r, lineStart); + const startColumn = offset - lineStart.offset + 1; + + if (!this._findOffset(offset + len, r)) { + BufferCursorPool.put(r); + BufferCursorPool.put(lineStart); + throw new Error(`Offset not found`); + } + const endLineNumber = this._findLineStartBeforeOffset(offset + len, r, lineStart); + const endColumn = offset + len - lineStart.offset + 1; + + BufferCursorPool.put(r); + BufferCursorPool.put(lineStart); + + return new Range(startLineNumber, startColumn, endLineNumber, endColumn); + } + + public getValueInRange(range: Range): string { + const start = BufferCursorPool.take(); + + if (!this._getOffsetAt(range.startLineNumber, range.startColumn, start)) { + BufferCursorPool.put(start); + throw new Error(`Line not found`); + } + + const endOffset = this.convertPositionToOffset(range.endLineNumber, range.endColumn); + const result = this.extractString(start, endOffset - start.offset); + + BufferCursorPool.put(start); + return result; + } + + public createSnapshot(BOM: string): ITextSnapshot { + return new BufferSnapshot(this._leafs, BOM); + } + + public getValueLengthInRange(range: Range): number { + const startOffset = this.convertPositionToOffset(range.startLineNumber, range.startColumn); + const endOffset = this.convertPositionToOffset(range.endLineNumber, range.endColumn); + return endOffset - startOffset; + } + + //#region Editing + + private _mergeAdjacentEdits(edits: OffsetLenEdit[]): OffsetLenEdit[] { + // Check if we must merge adjacent edits + let merged: OffsetLenEdit[] = [], mergedLength = 0; + let prev = edits[0]; + for (let i = 1, len = edits.length; i < len; i++) { + const curr = edits[i]; + if (prev.offset + prev.length === curr.offset) { + // merge into `prev` + prev.length = prev.length + curr.length; + prev.text = prev.text + curr.text; + } else { + merged[mergedLength++] = prev; + prev = curr; + } + } + merged[mergedLength++] = prev; + + return merged; + } + + private _resolveEdits(edits: OffsetLenEdit[]): InternalOffsetLenEdit[] { + edits = this._mergeAdjacentEdits(edits); + + let result: InternalOffsetLenEdit[] = []; + let tmp = new BufferCursor(0, 0, 0, 0); + let tmp2 = new BufferCursor(0, 0, 0, 0); + for (let i = 0, len = edits.length; i < len; i++) { + const edit = edits[i]; + + let text = edit.text; + + this._findOffset(edit.offset, tmp); + let startLeafIndex = tmp.leafIndex; + let startInnerOffset = tmp.offset - tmp.leafStartOffset; + if (startInnerOffset > 0) { + const startLeaf = this._leafs[startLeafIndex]; + const charBefore = startLeaf.charCodeAt(startInnerOffset - 1); + if (charBefore === CharCode.CarriageReturn) { + // include the replacement of \r in the edit + text = '\r' + text; + + this._findOffsetCloseAfter(edit.offset - 1, tmp, tmp2); + startLeafIndex = tmp2.leafIndex; + startInnerOffset = tmp2.offset - tmp2.leafStartOffset; + // this._findOffset(edit.offset - 1, tmp); + // startLeafIndex = tmp.leafIndex; + // startInnerOffset = tmp.offset - tmp.leafStartOffset; + } + } + + this._findOffset(edit.offset + edit.length, tmp); + let endLeafIndex = tmp.leafIndex; + let endInnerOffset = tmp.offset - tmp.leafStartOffset; + const endLeaf = this._leafs[endLeafIndex]; + if (endInnerOffset < endLeaf.length()) { + const charAfter = endLeaf.charCodeAt(endInnerOffset); + if (charAfter === CharCode.LineFeed) { + // include the replacement of \n in the edit + text = text + '\n'; + + this._findOffsetCloseAfter(edit.offset + edit.length + 1, tmp, tmp2); + endLeafIndex = tmp2.leafIndex; + endInnerOffset = tmp2.offset - tmp2.leafStartOffset; + // this._findOffset(edit.offset + edit.length + 1, tmp); + // endLeafIndex = tmp.leafIndex; + // endInnerOffset = tmp.offset - tmp.leafStartOffset; + } + } + + result[i] = new InternalOffsetLenEdit( + startLeafIndex, startInnerOffset, + endLeafIndex, endInnerOffset, + text + ); + } + + return result; + } + + private _pushLeafReplacement(startLeafIndex: number, endLeafIndex: number, replacements: LeafReplacement[]): LeafReplacement { + const res = new LeafReplacement(startLeafIndex, endLeafIndex, []); + replacements.push(res); + return res; + } + + private _flushLeafEdits(accumulatedLeafIndex: number, accumulatedLeafEdits: LeafOffsetLenEdit[], replacements: LeafReplacement[]): void { + if (accumulatedLeafEdits.length > 0) { + const rep = this._pushLeafReplacement(accumulatedLeafIndex, accumulatedLeafIndex, replacements); + BufferPiece.replaceOffsetLen(this._leafs[accumulatedLeafIndex], accumulatedLeafEdits, this._idealLeafLength, this._maxLeafLength, rep.replacements); + } + accumulatedLeafEdits.length = 0; + } + + private _pushLeafEdits(start: number, length: number, text: string, accumulatedLeafEdits: LeafOffsetLenEdit[]): void { + if (length !== 0 || text.length !== 0) { + accumulatedLeafEdits.push(new LeafOffsetLenEdit(start, length, text)); + } + } + + private _appendLeaf(leaf: BufferPiece, leafs: BufferPiece[], prevLeaf: BufferPiece): BufferPiece { + if (prevLeaf === null) { + leafs.push(leaf); + prevLeaf = leaf; + return prevLeaf; + } + + let prevLeafLength = prevLeaf.length(); + let currLeafLength = leaf.length(); + + if ((prevLeafLength < this._minLeafLength || currLeafLength < this._minLeafLength) && prevLeafLength + currLeafLength <= this._maxLeafLength) { + const joinedLeaf = BufferPiece.join(prevLeaf, leaf); + leafs[leafs.length - 1] = joinedLeaf; + prevLeaf = joinedLeaf; + return prevLeaf; + } + + const lastChar = prevLeaf.charCodeAt(prevLeafLength - 1); + const firstChar = leaf.charCodeAt(0); + + if ( + (lastChar >= 0xd800 && lastChar <= 0xdbff) || (lastChar === CharCode.CarriageReturn && firstChar === CharCode.LineFeed) + ) { + const modifiedPrevLeaf = BufferPiece.deleteLastChar(prevLeaf); + leafs[leafs.length - 1] = modifiedPrevLeaf; + + const modifiedLeaf = BufferPiece.insertFirstChar(leaf, lastChar); + leaf = modifiedLeaf; + } + + leafs.push(leaf); + prevLeaf = leaf; + return prevLeaf; + } + + private static _compareEdits(a: OffsetLenEdit, b: OffsetLenEdit): number { + if (a.offset === b.offset) { + if (a.length === b.length) { + return (a.initialIndex - b.initialIndex); + } + return (a.length - b.length); + } + return a.offset - b.offset; + } + + public replaceOffsetLen(_edits: OffsetLenEdit[]): void { + _edits.sort(Buffer._compareEdits); + + const initialLeafLength = this._leafs.length; + const edits = this._resolveEdits(_edits); + + let accumulatedLeafIndex = 0; + let accumulatedLeafEdits: LeafOffsetLenEdit[] = []; + let replacements: LeafReplacement[] = []; + + for (let i = 0, len = edits.length; i < len; i++) { + const edit = edits[i]; + + const startLeafIndex = edit.startLeafIndex; + const endLeafIndex = edit.endLeafIndex; + + if (startLeafIndex !== accumulatedLeafIndex) { + this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); + accumulatedLeafIndex = startLeafIndex; + } + + const leafEditStart = edit.startInnerOffset; + const leafEditEnd = (startLeafIndex === endLeafIndex ? edit.endInnerOffset : this._leafs[startLeafIndex].length()); + this._pushLeafEdits(leafEditStart, leafEditEnd - leafEditStart, edit.text, accumulatedLeafEdits); + + if (startLeafIndex < endLeafIndex) { + this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); + accumulatedLeafIndex = endLeafIndex; + + // delete leafs in the middle + if (startLeafIndex + 1 < endLeafIndex) { + this._pushLeafReplacement(startLeafIndex + 1, endLeafIndex - 1, replacements); + } + + // delete on last leaf + const leafEditStart = 0; + const leafEditEnd = edit.endInnerOffset; + this._pushLeafEdits(leafEditStart, leafEditEnd - leafEditStart, '', accumulatedLeafEdits); + } + } + this._flushLeafEdits(accumulatedLeafIndex, accumulatedLeafEdits, replacements); + + let leafs: BufferPiece[] = []; + let leafIndex = 0; + let prevLeaf: BufferPiece = null; + + for (let i = 0, len = replacements.length; i < len; i++) { + const replaceStartLeafIndex = replacements[i].startLeafIndex; + const replaceEndLeafIndex = replacements[i].endLeafIndex; + const innerLeafs = replacements[i].replacements; + + // add leafs to the left of this replace op. + while (leafIndex < replaceStartLeafIndex) { + prevLeaf = this._appendLeaf(this._leafs[leafIndex], leafs, prevLeaf); + leafIndex++; + } + + // delete leafs that get replaced. + while (leafIndex <= replaceEndLeafIndex) { + leafIndex++; + } + + // add new leafs. + for (let j = 0, lenJ = innerLeafs.length; j < lenJ; j++) { + prevLeaf = this._appendLeaf(innerLeafs[j], leafs, prevLeaf); + } + } + + // add remaining leafs to the right of the last replacement. + while (leafIndex < initialLeafLength) { + prevLeaf = this._appendLeaf(this._leafs[leafIndex], leafs, prevLeaf); + leafIndex++; + } + + if (leafs.length === 0) { + // don't leave behind an empty leafs array + leafs.push(new BufferPiece('')); + } + + this._leafs = leafs; + this._rebuildNodes(); + } + + public setEOL(newEOL: '\r\n' | '\n'): void { + let leafs: BufferPiece[] = []; + for (let i = 0, len = this._leafs.length; i < len; i++) { + leafs[i] = BufferPiece.normalizeEOL(this._leafs[i], newEOL); + } + this._leafs = leafs; + this._rebuildNodes(); + this._eol = newEOL; + this._eolLength = this._eol.length; + } + + //#endregion + + private IS_NODE(i: number): boolean { + return (i < this._nodesCount); + } + private IS_LEAF(i: number): boolean { + return (i >= this._leafsStart && i < this._leafsEnd); + } + private NODE_TO_LEAF_INDEX(i: number): number { + return (i - this._leafsStart); + } + // private LEAF_TO_NODE_INDEX(i: number): number { + // return (i + this._leafsStart); + // } +} + +function log2(n: number): number { + let v = 1; + for (let pow = 1; ; pow++) { + v = v << 1; + if (v >= n) { + return pow; + } + } + // return -1; +} + +function LEFT_CHILD(i: number): number { + return (i << 1); +} + +function RIGHT_CHILD(i: number): number { + return (i << 1) + 1; +} diff --git a/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts new file mode 100644 index 00000000000..12eaf167b28 --- /dev/null +++ b/src/vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder.ts @@ -0,0 +1,186 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as strings from 'vs/base/common/strings'; +import { ITextBufferBuilder, ITextBufferFactory, ITextBuffer, DefaultEndOfLine } from 'vs/editor/common/model'; +import { BufferPiece, createLineStarts } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; +import { ChunksTextBuffer } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBuffer'; +import { CharCode } from 'vs/base/common/charCode'; + +export class TextBufferFactory implements ITextBufferFactory { + + constructor( + private readonly _pieces: BufferPiece[], + private readonly _averageChunkSize: number, + private readonly _BOM: string, + private readonly _cr: number, + private readonly _lf: number, + private readonly _crlf: number, + private readonly _containsRTL: boolean, + private readonly _isBasicASCII: boolean, + ) { + } + + /** + * if text source is empty or with precisely one line, returns null. No end of line is detected. + * if text source contains more lines ending with '\r\n', returns '\r\n'. + * Otherwise returns '\n'. More lines end with '\n'. + */ + private _getEOL(defaultEOL: DefaultEndOfLine): '\r\n' | '\n' { + const totalEOLCount = this._cr + this._lf + this._crlf; + const totalCRCount = this._cr + this._crlf; + if (totalEOLCount === 0) { + // This is an empty file or a file with precisely one line + return (defaultEOL === DefaultEndOfLine.LF ? '\n' : '\r\n'); + } + if (totalCRCount > totalEOLCount / 2) { + // More than half of the file contains \r\n ending lines + return '\r\n'; + } + // At least one line more ends in \n + return '\n'; + } + + public create(defaultEOL: DefaultEndOfLine): ITextBuffer { + const eol = this._getEOL(defaultEOL); + let pieces = this._pieces; + + if ( + (eol === '\r\n' && (this._cr > 0 || this._lf > 0)) + || (eol === '\n' && (this._cr > 0 || this._crlf > 0)) + ) { + // Normalize pieces + for (let i = 0, len = pieces.length; i < len; i++) { + pieces[i] = BufferPiece.normalizeEOL(pieces[i], eol); + } + } + return new ChunksTextBuffer(pieces, this._averageChunkSize, this._BOM, eol, this._containsRTL, this._isBasicASCII); + } + + public getFirstLineText(lengthLimit: number): string { + const firstPiece = this._pieces[0]; + if (firstPiece.newLineCount() === 0) { + return firstPiece.substr(0, lengthLimit); + } + + const firstEOLOffset = firstPiece.lineStartFor(0); + return firstPiece.substr(0, Math.min(lengthLimit, firstEOLOffset)); + } +} + +export class ChunksTextBufferBuilder implements ITextBufferBuilder { + + private _rawPieces: BufferPiece[]; + private _hasPreviousChar: boolean; + private _previousChar: number; + private _averageChunkSize: number; + private _tmpLineStarts: number[]; + + private BOM: string; + private cr: number; + private lf: number; + private crlf: number; + private containsRTL: boolean; + private isBasicASCII: boolean; + + constructor() { + this._rawPieces = []; + this._hasPreviousChar = false; + this._previousChar = 0; + this._averageChunkSize = 0; + this._tmpLineStarts = []; + + this.BOM = ''; + this.cr = 0; + this.lf = 0; + this.crlf = 0; + this.containsRTL = false; + this.isBasicASCII = true; + } + + public acceptChunk(chunk: string): void { + if (chunk.length === 0) { + return; + } + + if (this._rawPieces.length === 0) { + if (strings.startsWithUTF8BOM(chunk)) { + this.BOM = strings.UTF8_BOM_CHARACTER; + chunk = chunk.substr(1); + } + } + + this._averageChunkSize = (this._averageChunkSize * this._rawPieces.length + chunk.length) / (this._rawPieces.length + 1); + + const lastChar = chunk.charCodeAt(chunk.length - 1); + if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) { + // last character is \r or a high surrogate => keep it back + this._acceptChunk1(chunk.substr(0, chunk.length - 1), false); + this._hasPreviousChar = true; + this._previousChar = lastChar; + } else { + this._acceptChunk1(chunk, false); + this._hasPreviousChar = false; + this._previousChar = lastChar; + } + } + + private _acceptChunk1(chunk: string, allowEmptyStrings: boolean): void { + if (!allowEmptyStrings && chunk.length === 0) { + // Nothing to do + return; + } + + if (this._hasPreviousChar) { + this._acceptChunk2(chunk + String.fromCharCode(this._previousChar)); + } else { + this._acceptChunk2(chunk); + } + } + + private _acceptChunk2(chunk: string): void { + const lineStarts = createLineStarts(this._tmpLineStarts, chunk); + + this._rawPieces.push(new BufferPiece(chunk, lineStarts.lineStarts)); + this.cr += lineStarts.cr; + this.lf += lineStarts.lf; + this.crlf += lineStarts.crlf; + + if (this.isBasicASCII) { + this.isBasicASCII = lineStarts.isBasicASCII; + } + if (!this.isBasicASCII && !this.containsRTL) { + // No need to check if is basic ASCII + this.containsRTL = strings.containsRTL(chunk); + } + } + + public finish(): TextBufferFactory { + this._finish(); + return new TextBufferFactory(this._rawPieces, this._averageChunkSize, this.BOM, this.cr, this.lf, this.crlf, this.containsRTL, this.isBasicASCII); + } + + private _finish(): void { + if (this._rawPieces.length === 0) { + // no chunks => forcefully go through accept chunk + this._acceptChunk1('', true); + return; + } + + if (this._hasPreviousChar) { + this._hasPreviousChar = false; + + // recreate last chunk + const lastPiece = this._rawPieces[this._rawPieces.length - 1]; + const tmp = new BufferPiece(String.fromCharCode(this._previousChar)); + const newLastPiece = BufferPiece.join(lastPiece, tmp); + this._rawPieces[this._rawPieces.length - 1] = newLastPiece; + if (this._previousChar === CharCode.CarriageReturn) { + this.cr++; + } + } + } +} diff --git a/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts b/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts index 09cafe2246c..0d03ecd90a0 100644 --- a/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts +++ b/src/vs/editor/common/model/linesTextBuffer/linesTextBuffer.ts @@ -9,8 +9,8 @@ import { Position } from 'vs/editor/common/core/position'; import * as strings from 'vs/base/common/strings'; import * as arrays from 'vs/base/common/arrays'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { ModelRawChange, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents'; import { ISingleEditOperationIdentifier, IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange } from 'vs/editor/common/model'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; export interface IValidatedEditOperation { sortIndex: number; @@ -49,6 +49,45 @@ export interface ITextSource { readonly isBasicASCII: boolean; } +class LinesTextBufferSnapshot implements ITextSnapshot { + + private readonly _lines: string[]; + private readonly _linesLength: number; + private readonly _eol: string; + private readonly _bom: string; + private _lineIndex: number; + + constructor(lines: string[], eol: string, bom: string) { + this._lines = lines; + this._linesLength = this._lines.length; + this._eol = eol; + this._bom = bom; + this._lineIndex = 0; + } + + public read(): string { + if (this._lineIndex >= this._linesLength) { + return null; + } + + let result: string = null; + + if (this._lineIndex === 0) { + result = this._bom + this._lines[this._lineIndex]; + } else { + result = this._lines[this._lineIndex]; + } + + this._lineIndex++; + + if (this._lineIndex < this._linesLength) { + result += this._eol; + } + + return result; + } +} + export class LinesTextBuffer implements ITextBuffer { private _lines: string[]; @@ -177,6 +216,10 @@ export class LinesTextBuffer implements ITextBuffer { return resultLines.join(lineEnding); } + public createSnapshot(preserveBOM: boolean): ITextSnapshot { + return new LinesTextBufferSnapshot(this._lines.slice(0), this._EOL, preserveBOM ? this._BOM : ''); + } + public getValueLengthInRange(range: Range, eol: EndOfLinePreference): number { if (range.isEmpty()) { return 0; @@ -199,6 +242,10 @@ export class LinesTextBuffer implements ITextBuffer { return this._lines.slice(0); } + public getLength(): number { + return this._lineStarts.getTotalValue(); + } + public getLineContent(lineNumber: number): string { return this._lines[lineNumber - 1]; } @@ -229,7 +276,7 @@ export class LinesTextBuffer implements ITextBuffer { //#region Editing - public setEOL(newEOL: string): void { + public setEOL(newEOL: '\r\n' | '\n'): void { this._EOL = newEOL; this._constructLineStarts(); } @@ -252,7 +299,7 @@ export class LinesTextBuffer implements ITextBuffer { public applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { if (rawOperations.length === 0) { - return new ApplyEditsResult([], [], [], []); + return new ApplyEditsResult([], [], []); } let mightContainRTL = this._mightContainRTL; @@ -341,7 +388,7 @@ export class LinesTextBuffer implements ITextBuffer { this._mightContainRTL = mightContainRTL; this._mightContainNonBasicASCII = mightContainNonBasicASCII; - const [rawContentChanges, contentChanges] = this._doApplyEdits(operations); + const contentChanges = this._doApplyEdits(operations); let trimAutoWhitespaceLineNumbers: number[] = null; if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { @@ -369,7 +416,6 @@ export class LinesTextBuffer implements ITextBuffer { return new ApplyEditsResult( reverseOperations, - rawContentChanges, contentChanges, trimAutoWhitespaceLineNumbers ); @@ -451,18 +497,16 @@ export class LinesTextBuffer implements ITextBuffer { }; } - private _setLineContent(lineNumber: number, content: string, rawContentChanges: ModelRawChange[]): void { + private _setLineContent(lineNumber: number, content: string): void { this._lines[lineNumber - 1] = content; this._lineStarts.changeValue(lineNumber - 1, content.length + this._EOL.length); - rawContentChanges.push(new ModelRawLineChanged(lineNumber, content)); } - private _doApplyEdits(operations: IValidatedEditOperation[]): [ModelRawChange[], IInternalModelContentChange[]] { + private _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] { // Sort operations descending operations.sort(LinesTextBuffer._sortOpsDescending); - let rawContentChanges: ModelRawChange[] = []; let contentChanges: IInternalModelContentChange[] = []; for (let i = 0, len = operations.length; i < len; i++) { @@ -497,7 +541,7 @@ export class LinesTextBuffer implements ITextBuffer { ); } - this._setLineContent(editLineNumber, editText, rawContentChanges); + this._setLineContent(editLineNumber, editText); } if (editingLinesCnt < deletingLinesCnt) { @@ -507,12 +551,10 @@ export class LinesTextBuffer implements ITextBuffer { const endLineRemains = this._lines[endLineNumber - 1].substring(endColumn - 1); // Reconstruct first line - this._setLineContent(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1] + endLineRemains, rawContentChanges); + this._setLineContent(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1] + endLineRemains); this._lines.splice(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); this._lineStarts.removeValues(spliceStartLineNumber, endLineNumber - spliceStartLineNumber); - - rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber)); } if (editingLinesCnt < insertingLinesCnt) { @@ -527,7 +569,7 @@ export class LinesTextBuffer implements ITextBuffer { // Split last line const leftoverLine = this._lines[spliceLineNumber - 1].substring(spliceColumn - 1); - this._setLineContent(spliceLineNumber, this._lines[spliceLineNumber - 1].substring(0, spliceColumn - 1), rawContentChanges); + this._setLineContent(spliceLineNumber, this._lines[spliceLineNumber - 1].substring(0, spliceColumn - 1)); // Lines in the middle let newLines: string[] = new Array(insertingLinesCnt - editingLinesCnt); @@ -540,8 +582,6 @@ export class LinesTextBuffer implements ITextBuffer { newLinesLengths[newLines.length - 1] += leftoverLine.length; this._lines = arrays.arrayInsert(this._lines, startLineNumber + editingLinesCnt, newLines); this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths); - - rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines)); } const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn); @@ -550,13 +590,12 @@ export class LinesTextBuffer implements ITextBuffer { range: contentChangeRange, rangeLength: op.rangeLength, text: text, - lines: op.lines, rangeOffset: op.rangeOffset, forceMoveMarkers: op.forceMoveMarkers }); } - return [rawContentChanges, contentChanges]; + return contentChanges; } /** diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts new file mode 100644 index 00000000000..d5497dd4c34 --- /dev/null +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -0,0 +1,1291 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { Position } from 'vs/editor/common/core/position'; +import { CharCode } from 'vs/base/common/charCode'; +import { Range } from 'vs/editor/common/core/range'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; +import { leftest, righttest, updateTreeMetadata, rbDelete, fixInsert, NodeColor, SENTINEL, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase'; + +// const lfRegex = new RegExp(/\r\n|\r|\n/g); + +export function createUintArray(arr: number[]): Uint32Array | Uint16Array { + let r; + if (arr[arr.length - 1] < 65536) { + r = new Uint16Array(arr.length); + } else { + r = new Uint32Array(arr.length); + } + r.set(arr, 0); + return r; +} + +export class LineStarts { + constructor( + public readonly lineStarts: Uint32Array | Uint16Array | number[], + public readonly cr: number, + public readonly lf: number, + public readonly crlf: number, + public readonly isBasicASCII: boolean + ) { } +} + +export function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | number[] { + let r: number[] = [0], rLength = 1; + + for (let i = 0, len = str.length; i < len; i++) { + const chr = str.charCodeAt(i); + + if (chr === CharCode.CarriageReturn) { + if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { + // \r\n... case + r[rLength++] = i + 2; + i++; // skip \n + } else { + // \r... case + r[rLength++] = i + 1; + } + } else if (chr === CharCode.LineFeed) { + r[rLength++] = i + 1; + } + } + if (readonly) { + return createUintArray(r); + } else { + return r; + } +} + +export function createLineStarts(r: number[], str: string): LineStarts { + r.length = 0; + r[0] = 0; + let rLength = 1; + let cr = 0, lf = 0, crlf = 0; + let isBasicASCII = true; + for (let i = 0, len = str.length; i < len; i++) { + const chr = str.charCodeAt(i); + + if (chr === CharCode.CarriageReturn) { + if (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) { + // \r\n... case + crlf++; + r[rLength++] = i + 2; + i++; // skip \n + } else { + cr++; + // \r... case + r[rLength++] = i + 1; + } + } else if (chr === CharCode.LineFeed) { + lf++; + r[rLength++] = i + 1; + } else { + if (isBasicASCII) { + if (chr !== CharCode.Tab && (chr < 32 || chr > 126)) { + isBasicASCII = false; + } + } + } + } + const result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII); + r.length = 0; + + return result; +} + +export interface NodePosition { + /** + * Piece Index + */ + node: TreeNode; + /** + * remainer in current piece. + */ + remainder: number; + /** + * node start offset in document. + */ + nodeStartOffset: number; +} + +export interface BufferCursor { + /** + * Line number in current buffer + */ + line: number; + /** + * Column number in current buffer + */ + column: number; +} + +export class Piece { + bufferIndex: number; + start: BufferCursor; + end: BufferCursor; + length: number; + lineFeedCnt: number; + + constructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) { + this.bufferIndex = bufferIndex; + this.start = start; + this.end = end; + this.lineFeedCnt = lineFeedCnt; + this.length = length; + } +} + +export class StringBuffer { + buffer: string; + lineStarts: Uint32Array | Uint16Array | number[]; + + constructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) { + this.buffer = buffer; + this.lineStarts = lineStarts; + } +} + +/** + * Readonly snapshot for piece tree. + * In a real multiple thread environment, to make snapshot reading always work correctly, we need to + * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel. + * 2. TreeNode/Buffers normalization should not happen during snapshot reading. + */ +class PieceTreeSnapshot implements ITextSnapshot { + private _nodes: TreeNode[]; // pieces/tree nodes in order + private _index: number; + private _tree: PieceTreeBase; + private _BOM: string; + + constructor(tree: PieceTreeBase, BOM: string) { + this._nodes = []; + this._tree = tree; + this._BOM = BOM; + this._index = 0; + if (tree.root !== SENTINEL) { + tree.iterate(tree.root, node => { + if (node !== SENTINEL) { + this._nodes.push(node); + } + return true; + }); + } + } + + read(): string { + if (this._nodes.length === 0) { + if (this._index === 0) { + this._index++; + return this._BOM; + } else { + return null; + } + } + + if (this._index > this._nodes.length - 1) { + return null; + } + + if (this._index === 0) { + return this._BOM + this._tree.getNodeContent(this._nodes[this._index++]); + } + return this._tree.getNodeContent(this._nodes[this._index++]); + } +} + +export class PieceTreeBase { + root: TreeNode; + protected _buffers: StringBuffer[]; // 0 is change buffer, others are readonly original buffer. + protected _lineCnt: number; + protected _length: number; + private _lastChangeBufferPos: BufferCursor; + + constructor(chunks: StringBuffer[]) { + this.create(chunks); + } + + create(chunks: StringBuffer[]) { + this._buffers = [ + new StringBuffer('', [0]) + ]; + this._lastChangeBufferPos = { line: 0, column: 0 }; + this.root = SENTINEL; + this._lineCnt = 1; + this._length = 0; + + let lastNode: TreeNode = null; + for (let i = 0, len = chunks.length; i < len; i++) { + if (chunks[i].buffer.length > 0) { + if (!chunks[i].lineStarts) { + chunks[i].lineStarts = createLineStartsFast(chunks[i].buffer); + } + + let piece = new Piece( + i + 1, + { line: 0, column: 0 }, + { line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] }, + chunks[i].lineStarts.length - 1, + chunks[i].buffer.length + ); + this._buffers.push(chunks[i]); + lastNode = this.rbInsertRight(lastNode, piece); + } + } + + this.computeBufferMetadata(); + + } + + normalizeEOL(eol: '\r\n' | '\n') { + let averageBufferSize = 65536; + let min = averageBufferSize - Math.floor(averageBufferSize / 3); + let max = min * 2; + + let tempChunk = ''; + let tempChunkLen = 0; + let chunks: StringBuffer[] = []; + + this.iterate(this.root, node => { + let str = this.getNodeContent(node); + let len = str.length; + if (tempChunkLen <= min || tempChunkLen + len < max) { + tempChunk += str; + tempChunkLen += len; + return true; + } + + // flush anyways + let text = tempChunk.replace(/\r\n|\r|\n/g, eol); + chunks.push(new StringBuffer(text, createLineStartsFast(text))); + tempChunk = str; + tempChunkLen = len; + return true; + }); + + if (tempChunkLen > 0) { + let text = tempChunk.replace(/\r\n|\r|\n/g, eol); + chunks.push(new StringBuffer(text, createLineStartsFast(text))); + } + + this.create(chunks); + } + + // #region Buffer API + public createSnapshot(BOM: string): ITextSnapshot { + return new PieceTreeSnapshot(this, BOM); + } + + public equal(other: PieceTreeBase): boolean { + if (this.getLength() !== other.getLength()) { + return false; + } + if (this.getLineCount() !== other.getLineCount()) { + return false; + } + + let offset = 0; + let ret = this.iterate(this.root, node => { + if (node === SENTINEL) { + return true; + } + let str = this.getNodeContent(node); + let len = str.length; + let startPosition = other.nodeAt(offset); + let endPosition = other.nodeAt(offset + len); + let val = other.getValueInRange2(startPosition, endPosition); + + return str === val; + }); + + return ret; + } + + public getOffsetAt(lineNumber: number, column: number): number { + let leftLen = 0; // inorder + + let x = this.root; + + while (x !== SENTINEL) { + if (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) { + x = x.left; + } else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) { + leftLen += x.size_left; + // lineNumber >= 2 + let accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2); + return leftLen += accumualtedValInCurrentIndex + column - 1; + } else { + lineNumber -= x.lf_left + x.piece.lineFeedCnt; + leftLen += x.size_left + x.piece.length; + x = x.right; + } + } + + return leftLen; + } + + public getPositionAt(offset: number): Position { + offset = Math.floor(offset); + offset = Math.max(0, offset); + + let x = this.root; + let lfCnt = 0; + let originalOffset = offset; + + while (x !== SENTINEL) { + if (x.size_left !== 0 && x.size_left >= offset) { + x = x.left; + } else if (x.size_left + x.piece.length >= offset) { + let out = this.getIndexOf(x, offset - x.size_left); + + lfCnt += x.lf_left + out.index; + + if (out.index === 0) { + let lineStartOffset = this.getOffsetAt(lfCnt + 1, 1); + let column = originalOffset - lineStartOffset; + return new Position(lfCnt + 1, column + 1); + } + + return new Position(lfCnt + 1, out.remainder + 1); + } else { + offset -= x.size_left + x.piece.length; + lfCnt += x.lf_left + x.piece.lineFeedCnt; + + if (x.right === SENTINEL) { + // last node + let lineStartOffset = this.getOffsetAt(lfCnt + 1, 1); + let column = originalOffset - offset - lineStartOffset; + return new Position(lfCnt + 1, column + 1); + } else { + x = x.right; + } + } + } + + return new Position(1, 1); + } + + public getValueInRange(range: Range): string { + if (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) { + return ''; + } + + let startPosition = this.nodeAt2(new Position(range.startLineNumber, range.startColumn)); + let endPosition = this.nodeAt2(new Position(range.endLineNumber, range.endColumn)); + + return this.getValueInRange2(startPosition, endPosition); + } + + public getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string { + if (startPosition.node === endPosition.node) { + let node = startPosition.node; + let buffer = this._buffers[node.piece.bufferIndex].buffer; + let startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start); + return buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder); + } + + let x = startPosition.node; + let buffer = this._buffers[x.piece.bufferIndex].buffer; + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + let ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length); + + x = x.next(); + while (x !== SENTINEL) { + let buffer = this._buffers[x.piece.bufferIndex].buffer; + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + + if (x === endPosition.node) { + ret += buffer.substring(startOffset, startOffset + endPosition.remainder); + break; + } else { + ret += buffer.substr(startOffset, x.piece.length); + } + + x = x.next(); + } + + return ret; + } + + public getLinesContent(): string[] { + return this.getContentOfSubTree(this.root).split(/\r\n|\r|\n/); + } + + public getLength(): number { + return this._length; + } + + public getLineCount(): number { + return this._lineCnt; + } + + public getLineContent(lineNumber): string { + return this.getLineRawContent(lineNumber).replace(/(\r\n|\r|\n)$/, ''); + } + + public getLineCharCode(lineNumber: number, index: number): number { + let nodePos = this.nodeAt2(new Position(lineNumber, index + 1)); + let buffer = this._buffers[nodePos.node.piece.bufferIndex]; + let startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start); + let targetOffset = startOffset + index; + + return buffer.buffer.charCodeAt(targetOffset); + } + + // #endregion + + // #region Piece Table + insert(offset: number, value: string): void { + if (this.root !== SENTINEL) { + let { node, remainder, nodeStartOffset } = this.nodeAt(offset); + let piece = node.piece; + let bufferIndex = piece.bufferIndex; + let insertPosInBuffer = this.positionInBuffer(node, remainder); + if (node.piece.bufferIndex === 0 && + piece.end.line === this._lastChangeBufferPos.line && + piece.end.column === this._lastChangeBufferPos.column && + (nodeStartOffset + piece.length === offset) + ) { + // changed buffer + this.appendToNode(node, value); + this.computeBufferMetadata(); + return; + } + + if (nodeStartOffset === offset) { + this.insertContentToNodeLeft(value, node); + } else if (nodeStartOffset + node.piece.length > offset) { + // we are inserting into the middle of a node. + let nodesToDel = []; + let newRightPiece = new Piece( + piece.bufferIndex, + insertPosInBuffer, + piece.end, + this.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end), + this.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer) + ); + + if (this.endWithCR(value)) { + let headOfRight = this.nodeCharCodeAt(node, remainder); + + if (headOfRight === 10 /** \n */) { + let newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 }; + newRightPiece.start = newStart; + newRightPiece.length -= 1; + newRightPiece.lineFeedCnt = this.getLineFeedCnt(newRightPiece.bufferIndex, newRightPiece.start, newRightPiece.end); // @todo, we can optimize + value += '\n'; + } + } + + // reuse node for content before insertion point. + if (this.startWithLF(value)) { + let tailOfLeft = this.nodeCharCodeAt(node, remainder - 1); + if (tailOfLeft === 13 /** \r */) { + let previousPos = this.positionInBuffer(node, remainder - 1); + this.deleteNodeTail(node, previousPos); + value = '\r' + value; + + if (node.piece.length === 0) { + nodesToDel.push(node); + } + } else { + this.deleteNodeTail(node, insertPosInBuffer); + } + } else { + this.deleteNodeTail(node, insertPosInBuffer); + } + + let newPiece = this.createNewPiece(value); + if (newRightPiece.length > 0) { + this.rbInsertRight(node, newRightPiece); + } + this.rbInsertRight(node, newPiece); + this.deleteNodes(nodesToDel); + } else { + this.insertContentToNodeRight(value, node); + } + } else { + // insert new node + let piece = this.createNewPiece(value); + this.rbInsertLeft(null, piece); + } + + // todo, this is too brutal. Total line feed count should be updated the same way as lf_left. + this.computeBufferMetadata(); + } + + delete(offset: number, cnt: number): void { + if (cnt <= 0 || this.root === SENTINEL) { + return; + } + + let startPosition = this.nodeAt(offset); + let endPosition = this.nodeAt(offset + cnt); + let startNode = startPosition.node; + let endNode = endPosition.node; + + if (startNode === endNode) { + let startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder); + let endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder); + + if (startPosition.nodeStartOffset === offset) { + if (cnt === startNode.piece.length) { // delete node + let next = startNode.next(); + rbDelete(this, startNode); + this.validateCRLFWithPrevNode(next); + this.computeBufferMetadata(); + return; + } + this.deleteNodeHead(startNode, endSplitPosInBuffer); + this.validateCRLFWithPrevNode(startNode); + this.computeBufferMetadata(); + return; + } + + if (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) { + this.deleteNodeTail(startNode, startSplitPosInBuffer); + this.validateCRLFWithNextNode(startNode); + this.computeBufferMetadata(); + return; + } + + // delete content in the middle, this node will be splitted to nodes + this.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer); + this.computeBufferMetadata(); + return; + } + + let nodesToDel = []; + + let startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder); + this.deleteNodeTail(startNode, startSplitPosInBuffer); + if (startNode.piece.length === 0) { + nodesToDel.push(startNode); + } + + // update last touched node + let endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder); + this.deleteNodeHead(endNode, endSplitPosInBuffer); + if (endNode.piece.length === 0) { + nodesToDel.push(endNode); + } + + // delete nodes in between + let secondNode = startNode.next(); + for (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) { + nodesToDel.push(node); + } + + let prev = startNode.piece.length === 0 ? startNode.prev() : startNode; + this.deleteNodes(nodesToDel); + this.validateCRLFWithNextNode(prev); + this.computeBufferMetadata(); + } + + insertContentToNodeLeft(value: string, node: TreeNode) { + // we are inserting content to the beginning of node + let nodesToDel = []; + if (this.endWithCR(value) && this.startWithLF(node)) { + // move `\n` to new node. + + let piece = node.piece; + let newStart: BufferCursor = { line: piece.start.line + 1, column: 0 }; + piece.start = newStart; + piece.lineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, piece.end); // @todo, we can optimize + piece.length -= 1; + + value += '\n'; + updateTreeMetadata(this, node, -1, -1); + + if (node.piece.length === 0) { + nodesToDel.push(node); + } + } + + let newPiece = this.createNewPiece(value); + let newNode = this.rbInsertLeft(node, newPiece); + this.validateCRLFWithPrevNode(newNode); + this.deleteNodes(nodesToDel); + } + + insertContentToNodeRight(value: string, node: TreeNode) { + // we are inserting to the right of this node. + if (this.adjustCarriageReturnFromNext(value, node)) { + // move \n to the new node. + value += '\n'; + } + + let newPiece = this.createNewPiece(value); + let newNode = this.rbInsertRight(node, newPiece); + this.validateCRLFWithPrevNode(newNode); + } + + positionInBuffer(node: TreeNode, remainder: number): BufferCursor { + let piece = node.piece; + let bufferIndex = node.piece.bufferIndex; + let lineStarts = this._buffers[bufferIndex].lineStarts; + + let startOffset = lineStarts[piece.start.line] + piece.start.column; + + let offset = startOffset + remainder; + + // binary search offset between startOffset and endOffset + let low = piece.start.line; + let high = piece.end.line; + + let mid: number; + let midStop: number; + let midStart: number; + + while (low <= high) { + mid = low + ((high - low) / 2) | 0; + midStart = lineStarts[mid]; + + if (mid === high) { + break; + } + + midStop = lineStarts[mid + 1]; + + if (offset < midStart) { + high = mid - 1; + } else if (offset >= midStop) { + low = mid + 1; + } else { + break; + } + } + + return { + line: mid, + column: offset - midStart + }; + } + + getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number { + // we don't need to worry about start: abc\r|\n, or abc|\r, or abc|\n, or abc|\r\n doesn't change the fact that, there is one line break after start. + // now let's take care of end: abc\r|\n, if end is in between \r and \n, we need to add line feed count by 1 + if (end.column === 0) { + return end.line - start.line; + } + + let lineStarts = this._buffers[bufferIndex].lineStarts; + if (end.line === lineStarts.length - 1) { // it means, there is no \n after end, otherwise, there will be one more lineStart. + return end.line - start.line; + } + + let nextLineStartOffset = lineStarts[end.line + 1]; + let endOffset = lineStarts[end.line] + end.column; + if (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \n + return end.line - start.line; + } + // endOffset + 1 === nextLineStartOffset + // character at endOffset is \n, so we check the character before first + // if character at endOffset is \r, end.column is 0 and we can't get here. + let previousCharOffset = endOffset - 1; // end.column > 0 so it's okay. + let buffer = this._buffers[bufferIndex].buffer; + + if (buffer.charCodeAt(previousCharOffset) === 13) { + return end.line - start.line + 1; + } else { + return end.line - start.line; + } + } + + offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number { + let lineStarts = this._buffers[bufferIndex].lineStarts; + return lineStarts[cursor.line] + cursor.column; + } + + deleteNodes(nodes: TreeNode[]): void { + for (let i = 0; i < nodes.length; i++) { + rbDelete(this, nodes[i]); + } + } + + createNewPiece(text: string): Piece { + let startOffset = this._buffers[0].buffer.length; + const lineStarts = createLineStartsFast(text, false); + + let start = this._lastChangeBufferPos; + if (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset + && startOffset !== 0 + && this.startWithLF(text) + && this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one + ) { + this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 }; + start = this._lastChangeBufferPos; + + for (let i = 0; i < lineStarts.length; i++) { + lineStarts[i] += startOffset + 1; + } + + this._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1)); + this._buffers[0].buffer += '_' + text; + startOffset += 1; + } else { + if (startOffset !== 0) { + for (let i = 0; i < lineStarts.length; i++) { + lineStarts[i] += startOffset; + } + } + this._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1)); + this._buffers[0].buffer += text; + } + + const endOffset = this._buffers[0].buffer.length; + let endIndex = this._buffers[0].lineStarts.length - 1; + let endColumn = endOffset - this._buffers[0].lineStarts[endIndex]; + let endPos = { line: endIndex, column: endColumn }; + let newPiece = new Piece( + 0, + start, + endPos, + this.getLineFeedCnt(0, start, endPos), // @todo, optimize + endOffset - startOffset + ); + this._lastChangeBufferPos = endPos; + return newPiece; + } + + getLinesRawContent(): string { + return this.getContentOfSubTree(this.root); + } + + getLineRawContent(lineNumber: number): string { + let x = this.root; + + let ret = ''; + while (x !== SENTINEL) { + if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) { + x = x.left; + } else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) { + let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2); + let accumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1); + let buffer = this._buffers[x.piece.bufferIndex].buffer; + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + return buffer.substring(startOffset + prevAccumualtedValue, startOffset + accumualtedValue); + } else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) { + let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2); + let buffer = this._buffers[x.piece.bufferIndex].buffer; + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + + ret = buffer.substring(startOffset + prevAccumualtedValue, startOffset + x.piece.length); + break; + } else { + lineNumber -= x.lf_left + x.piece.lineFeedCnt; + x = x.right; + } + } + + // search in order, to find the node contains end column + x = x.next(); + while (x !== SENTINEL) { + let buffer = this._buffers[x.piece.bufferIndex].buffer; + + if (x.piece.lineFeedCnt > 0) { + let accumualtedValue = this.getAccumulatedValue(x, 0); + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + + ret += buffer.substring(startOffset, startOffset + accumualtedValue); + return ret; + } else { + let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start); + ret += buffer.substr(startOffset, x.piece.length); + } + + x = x.next(); + } + + return ret; + } + + computeBufferMetadata() { + let x = this.root; + + let lfCnt = 1; + let len = 0; + + while (x !== SENTINEL) { + lfCnt += x.lf_left + x.piece.lineFeedCnt; + len += x.size_left + x.piece.length; + x = x.right; + } + + this._lineCnt = lfCnt; + this._length = len; + } + + // #region node operations + getIndexOf(node: TreeNode, accumulatedValue: number): { index: number, remainder: number } { + let piece = node.piece; + let pos = this.positionInBuffer(node, accumulatedValue); + let lineCnt = pos.line - piece.start.line; + + if (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) { + // we are checking the end of this node, so a CRLF check is necessary. + let realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos); + if (realLineCnt !== lineCnt) { + // aha yes, CRLF + return { index: realLineCnt, remainder: 0 }; + } + } + + return { index: lineCnt, remainder: pos.column }; + } + + getAccumulatedValue(node: TreeNode, index: number) { + if (index < 0) { + return 0; + } + let piece = node.piece; + let lineStarts = this._buffers[piece.bufferIndex].lineStarts; + let expectedLineStartIndex = piece.start.line + index + 1; + if (expectedLineStartIndex > piece.end.line) { + return lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column; + } else { + return lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column; + } + } + + deleteNodeTail(node: TreeNode, pos: BufferCursor) { + let piece = node.piece; + let originalLFCnt = piece.lineFeedCnt; + let originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end); + piece.end = pos; + let newEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end); + piece.lineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, piece.end); + let lf_delta = piece.lineFeedCnt - originalLFCnt; + let size_delta = newEndOffset - originalEndOffset; + piece.length += size_delta; + updateTreeMetadata(this, node, size_delta, lf_delta); + } + + deleteNodeHead(node: TreeNode, pos: BufferCursor) { + let piece = node.piece; + let originalLFCnt = piece.lineFeedCnt; + let originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start); + + piece.start = pos; + piece.lineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, piece.end); // @todo, maybe we can optimize this case as we just change start. + let newStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start); + let lf_delta = piece.lineFeedCnt - originalLFCnt; + let size_delta = originalStartOffset - newStartOffset; + piece.length += size_delta; + updateTreeMetadata(this, node, size_delta, lf_delta); + } + + shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) { + let piece = node.piece; + let originalStartPos = piece.start; + let originalEndPos = piece.end; + + // old piece, originalStartPos, start + let oldLength = piece.length; + let oldLFCnt = piece.lineFeedCnt; + piece.end = start; + piece.lineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, piece.end); + let newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos); + let newLFCnt = piece.lineFeedCnt; + piece.length = newLength; + updateTreeMetadata(this, node, newLength - oldLength, newLFCnt - oldLFCnt); + + // new right piece, end, originalEndPos + let newPiece = new Piece( + piece.bufferIndex, + end, + originalEndPos, + this.getLineFeedCnt(piece.bufferIndex, end, originalEndPos), + this.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end) + ); + + let newNode = this.rbInsertRight(node, newPiece); + this.validateCRLFWithPrevNode(newNode); + } + + appendToNode(node: TreeNode, value: string): void { + if (this.adjustCarriageReturnFromNext(value, node)) { + value += '\n'; + } + + let hitCRLF = this.startWithLF(value) && this.endWithCR(node); + const startOffset = this._buffers[0].buffer.length; + this._buffers[0].buffer += value; + const lineStarts = createLineStartsFast(value, false); + for (let i = 0; i < lineStarts.length; i++) { + lineStarts[i] += startOffset; + } + if (hitCRLF) { + let prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2]; + (this._buffers[0].lineStarts).pop(); + // _lastChangeBufferPos is already wrong + this._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset }; + } + + this._buffers[0].lineStarts = (this._buffers[0].lineStarts).concat(lineStarts.slice(1)); + let endIndex = this._buffers[0].lineStarts.length - 1; + let endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex]; + let endPos = { line: endIndex, column: endColumn }; + node.piece.end = endPos; + node.piece.length += value.length; + let oldLineFeedCnt = node.piece.lineFeedCnt; + let newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, endPos); + node.piece.lineFeedCnt = newLineFeedCnt; + let lf_delta = newLineFeedCnt - oldLineFeedCnt; + this._lastChangeBufferPos = endPos; + updateTreeMetadata(this, node, value.length, lf_delta); + } + + nodeAt(offset: number): NodePosition { + let x = this.root; + let nodeStartOffset = 0; + + while (x !== SENTINEL) { + if (x.size_left > offset) { + x = x.left; + } else if (x.size_left + x.piece.length >= offset) { + nodeStartOffset += x.size_left; + return { + node: x, + remainder: offset - x.size_left, + nodeStartOffset + }; + } else { + offset -= x.size_left + x.piece.length; + nodeStartOffset += x.size_left + x.piece.length; + x = x.right; + } + } + + return null; + } + + nodeAt2(position: Position): NodePosition { + let x = this.root; + let lineNumber = position.lineNumber; + let column = position.column; + let nodeStartOffset = 0; + + while (x !== SENTINEL) { + if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) { + x = x.left; + } else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) { + let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2); + let accumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1); + nodeStartOffset += x.size_left; + + return { + node: x, + remainder: Math.min(prevAccumualtedValue + column - 1, accumualtedValue), + nodeStartOffset + }; + } else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) { + let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2); + if (prevAccumualtedValue + column - 1 <= x.piece.length) { + return { + node: x, + remainder: prevAccumualtedValue + column - 1, + nodeStartOffset + }; + } else { + column -= x.piece.length - prevAccumualtedValue; + break; + } + } else { + lineNumber -= x.lf_left + x.piece.lineFeedCnt; + nodeStartOffset += x.size_left + x.piece.length; + x = x.right; + } + } + + // search in order, to find the node contains position.column + x = x.next(); + while (x !== SENTINEL) { + + if (x.piece.lineFeedCnt > 0) { + let accumualtedValue = this.getAccumulatedValue(x, 0); + let nodeStartOffset = this.offsetOfNode(x); + return { + node: x, + remainder: Math.min(column - 1, accumualtedValue), + nodeStartOffset + }; + } else { + if (x.piece.length >= column - 1) { + let nodeStartOffset = this.offsetOfNode(x); + return { + node: x, + remainder: column - 1, + nodeStartOffset + }; + } else { + column -= x.piece.length; + } + } + + x = x.next(); + } + + return null; + } + + nodeCharCodeAt(node: TreeNode, offset: number): number { + if (node.piece.lineFeedCnt < 1) { + return -1; + } + let buffer = this._buffers[node.piece.bufferIndex]; + let newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset; + return buffer.buffer.charCodeAt(newOffset); + } + + offsetOfNode(node: TreeNode): number { + if (!node) { + return 0; + } + let pos = node.size_left; + while (node !== this.root) { + if (node.parent.right === node) { + pos += node.parent.size_left + node.parent.piece.length; + } + + node = node.parent; + } + + return pos; + } + + // #endregion + + // #region CRLF + startWithLF(val: string | TreeNode): boolean { + if (typeof val === 'string') { + return val.charCodeAt(0) === 10; + } + + if (val === SENTINEL || val.piece.lineFeedCnt === 0) { + return false; + } + + let piece = val.piece; + let lineStarts = this._buffers[piece.bufferIndex].lineStarts; + let line = piece.start.line; + let startOffset = lineStarts[line] + piece.start.column; + if (line === lineStarts.length - 1) { + // last line, so there is no line feed at the end of this line + return false; + } + let nextLineOffset = lineStarts[line + 1]; + if (nextLineOffset > startOffset + 1) { + return false; + } + return this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10; + } + + endWithCR(val: string | TreeNode): boolean { + if (typeof val === 'string') { + return val.charCodeAt(val.length - 1) === 13; + } + + if (val === SENTINEL || val.piece.lineFeedCnt === 0) { + return false; + } + + return this.nodeCharCodeAt(val, val.piece.length - 1) === 13; + } + + validateCRLFWithPrevNode(nextNode: TreeNode) { + if (this.startWithLF(nextNode)) { + let node = nextNode.prev(); + if (this.endWithCR(node)) { + this.fixCRLF(node, nextNode); + } + } + } + + validateCRLFWithNextNode(node: TreeNode) { + if (this.endWithCR(node)) { + let nextNode = node.next(); + if (this.startWithLF(nextNode)) { + this.fixCRLF(node, nextNode); + } + } + } + + fixCRLF(prev: TreeNode, next: TreeNode) { + let nodesToDel = []; + // update node + let lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts; + if (prev.piece.end.column === 0) { + // it means, last line ends with \r, not \r\n + let newEnd: BufferCursor = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 }; + prev.piece.end = newEnd; + } else { + // \r\n + let newEnd: BufferCursor = { line: prev.piece.end.line, column: prev.piece.end.column - 1 }; + prev.piece.end = newEnd; + } + + prev.piece.length -= 1; + prev.piece.lineFeedCnt -= 1; + + updateTreeMetadata(this, prev, - 1, -1); + if (prev.piece.length === 0) { + nodesToDel.push(prev); + } + + // update nextNode + let newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 }; + next.piece.start = newStart; + next.piece.length -= 1; + next.piece.lineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, next.piece.start, next.piece.end); // @todo, we can optimize + // } + + updateTreeMetadata(this, next, - 1, -1); + if (next.piece.length === 0) { + nodesToDel.push(next); + } + + // create new piece which contains \r\n + let piece = this.createNewPiece('\r\n'); + this.rbInsertRight(prev, piece); + // delete empty nodes + + for (let i = 0; i < nodesToDel.length; i++) { + rbDelete(this, nodesToDel[i]); + } + } + + adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean { + if (this.endWithCR(value)) { + let nextNode = node.next(); + if (this.startWithLF(nextNode)) { + // move `\n` forward + value += '\n'; + + if (nextNode.piece.length === 1) { + rbDelete(this, nextNode); + } else { + + let piece = nextNode.piece; + let newStart: BufferCursor = { line: piece.start.line + 1, column: 0 }; + piece.start = newStart; + piece.length -= 1; + piece.lineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, piece.end); // @todo, we can optimize + updateTreeMetadata(this, nextNode, -1, -1); + } + return true; + } + } + + return false; + } + + // #endregion + + // #endregion + + // #region Tree operations + iterate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean { + if (node === SENTINEL) { + return callback(SENTINEL); + } + + let leftRet = this.iterate(node.left, callback); + if (!leftRet) { + return leftRet; + } + + return callback(node) && this.iterate(node.right, callback); + } + + getNodeContent(node: TreeNode) { + if (node === SENTINEL) { + return ''; + } + let buffer = this._buffers[node.piece.bufferIndex]; + let currentContent; + let piece = node.piece; + let startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start); + let endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end); + currentContent = buffer.buffer.substring(startOffset, endOffset); + return currentContent; + } + + /** + * node node + * / \ / \ + * a b <---- a b + * / + * z + */ + rbInsertRight(node: TreeNode, p: Piece): TreeNode { + let z = new TreeNode(p, NodeColor.Red); + z.left = SENTINEL; + z.right = SENTINEL; + z.parent = SENTINEL; + z.size_left = 0; + z.lf_left = 0; + + let x = this.root; + if (x === SENTINEL) { + this.root = z; + z.color = NodeColor.Black; + } else if (node.right === SENTINEL) { + node.right = z; + z.parent = node; + } else { + let nextNode = leftest(node.right); + nextNode.left = z; + z.parent = nextNode; + } + + fixInsert(this, z); + return z; + } + + /** + * node node + * / \ / \ + * a b ----> a b + * \ + * z + */ + rbInsertLeft(node: TreeNode, p: Piece): TreeNode { + let z = new TreeNode(p, NodeColor.Red); + z.left = SENTINEL; + z.right = SENTINEL; + z.parent = SENTINEL; + z.size_left = 0; + z.lf_left = 0; + + let x = this.root; + if (x === SENTINEL) { + this.root = z; + z.color = NodeColor.Black; + } else if (node.left === SENTINEL) { + node.left = z; + z.parent = node; + } else { + let prevNode = righttest(node.left); // a + prevNode.right = z; + z.parent = prevNode; + } + + fixInsert(this, z); + return z; + } + + getContentOfSubTree(node: TreeNode): string { + let str = ''; + + this.iterate(node, node => { + str += this.getNodeContent(node); + return true; + }); + + return str; + } + // #endregion +} diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts new file mode 100644 index 00000000000..f8505567923 --- /dev/null +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -0,0 +1,504 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { Range } from 'vs/editor/common/core/range'; +import { Position } from 'vs/editor/common/core/position'; +import * as strings from 'vs/base/common/strings'; +import { IValidatedEditOperation } from 'vs/editor/common/model/linesTextBuffer/linesTextBuffer'; +import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; +import { IIdentifiedSingleEditOperation, EndOfLinePreference, ITextBuffer, ApplyEditsResult, IInternalModelContentChange } from 'vs/editor/common/model'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; + +export class PieceTreeTextBuffer implements ITextBuffer { + private _pieceTree: PieceTreeBase; + private _BOM: string; + private _EOL: string; + private _EOLLength: number; + private _mightContainRTL: boolean; + private _mightContainNonBasicASCII: boolean; + + constructor(chunks: StringBuffer[], BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, isBasicASCII: boolean) { + this._BOM = BOM; + this._EOL = eol; + this._EOLLength = this._EOL.length; + this._mightContainNonBasicASCII = !isBasicASCII; + this._mightContainRTL = containsRTL; + this._pieceTree = new PieceTreeBase(chunks); + } + + // #region TextBuffer + public equals(other: ITextBuffer): boolean { + if (!(other instanceof PieceTreeTextBuffer)) { + return false; + } + if (this._BOM !== other._BOM) { + return false; + } + if (this._EOL !== other._EOL) { + return false; + } + return this._pieceTree.equal(other._pieceTree); + } + public mightContainRTL(): boolean { + return this._mightContainRTL; + } + public mightContainNonBasicASCII(): boolean { + return this._mightContainNonBasicASCII; + } + public getBOM(): string { + return this._BOM; + } + public getEOL(): string { + return this._EOL; + } + + public createSnapshot(preserveBOM: boolean): ITextSnapshot { + return this._pieceTree.createSnapshot(preserveBOM ? this._BOM : ''); + } + + public getOffsetAt(lineNumber: number, column: number): number { + return this._pieceTree.getOffsetAt(lineNumber, column); + } + + public getPositionAt(offset: number): Position { + return this._pieceTree.getPositionAt(offset); + } + + public getRangeAt(start: number, length: number): Range { + let end = start + length; + const startPosition = this.getPositionAt(start); + const endPosition = this.getPositionAt(end); + return new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column); + } + + public getValueInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): string { + if (range.isEmpty()) { + return ''; + } + + const lineEnding = this._getEndOfLine(eol); + const text = this._pieceTree.getValueInRange(range); + return text.replace(/\r\n|\r|\n/g, lineEnding); + } + + public getValueLengthInRange(range: Range, eol: EndOfLinePreference = EndOfLinePreference.TextDefined): number { + if (range.isEmpty()) { + return 0; + } + + if (range.startLineNumber === range.endLineNumber) { + return (range.endColumn - range.startColumn); + } + + let startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn); + let endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn); + return endOffset - startOffset; + } + + public getLength(): number { + return this._pieceTree.getLength(); + } + + public getLineCount(): number { + return this._pieceTree.getLineCount(); + } + + public getLinesContent(): string[] { + return this._pieceTree.getLinesContent(); + } + + public getLineContent(lineNumber: number): string { + return this._pieceTree.getLineContent(lineNumber); + } + + public getLineCharCode(lineNumber: number, index: number): number { + return this._pieceTree.getLineCharCode(lineNumber, index); + } + + public getLineLength(lineNumber: number): number { + if (lineNumber === this.getLineCount()) { + let startOffset = this.getOffsetAt(lineNumber, 1); + return this.getLength() - startOffset; + } + return this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength; + } + + public getLineMinColumn(lineNumber: number): number { + return 1; + } + + public getLineMaxColumn(lineNumber: number): number { + return this.getLineLength(lineNumber) + 1; + } + + public getLineFirstNonWhitespaceColumn(lineNumber: number): number { + const result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber)); + if (result === -1) { + return 0; + } + return result + 1; + } + + public getLineLastNonWhitespaceColumn(lineNumber: number): number { + const result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber)); + if (result === -1) { + return 0; + } + return result + 2; + } + + private _getEndOfLine(eol: EndOfLinePreference): string { + switch (eol) { + case EndOfLinePreference.LF: + return '\n'; + case EndOfLinePreference.CRLF: + return '\r\n'; + case EndOfLinePreference.TextDefined: + return this.getEOL(); + } + throw new Error('Unknown EOL preference'); + } + + public setEOL(newEOL: '\r\n' | '\n'): void { + this._EOL = newEOL; + this._EOLLength = this._EOL.length; + this._pieceTree.normalizeEOL(newEOL); + } + + public applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { + let mightContainRTL = this._mightContainRTL; + let mightContainNonBasicASCII = this._mightContainNonBasicASCII; + let canReduceOperations = true; + + let operations: IValidatedEditOperation[] = []; + for (let i = 0; i < rawOperations.length; i++) { + let op = rawOperations[i]; + if (canReduceOperations && op._isTracked) { + canReduceOperations = false; + } + let validatedRange = op.range; + if (!mightContainRTL && op.text) { + // check if the new inserted text contains RTL + mightContainRTL = strings.containsRTL(op.text); + } + if (!mightContainNonBasicASCII && op.text) { + mightContainNonBasicASCII = !strings.isBasicASCII(op.text); + } + operations[i] = { + sortIndex: i, + identifier: op.identifier, + range: validatedRange, + rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), + rangeLength: this.getValueLengthInRange(validatedRange), + lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, + forceMoveMarkers: op.forceMoveMarkers, + isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false + }; + } + + // Sort operations ascending + operations.sort(PieceTreeTextBuffer._sortOpsAscending); + + for (let i = 0, count = operations.length - 1; i < count; i++) { + let rangeEnd = operations[i].range.getEndPosition(); + let nextRangeStart = operations[i + 1].range.getStartPosition(); + + if (nextRangeStart.isBefore(rangeEnd)) { + // overlapping ranges + throw new Error('Overlapping ranges are not allowed!'); + } + } + + if (canReduceOperations) { + operations = this._reduceOperations(operations); + } + + // Delta encode operations + let reverseRanges = PieceTreeTextBuffer._getInverseEditRanges(operations); + let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = []; + + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + let reverseRange = reverseRanges[i]; + + if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) { + // Record already the future line numbers that might be auto whitespace removal candidates on next edit + for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { + let currentLineContent = ''; + if (lineNumber === reverseRange.startLineNumber) { + currentLineContent = this.getLineContent(op.range.startLineNumber); + if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { + continue; + } + } + newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); + } + } + } + + let reverseOperations: IIdentifiedSingleEditOperation[] = []; + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + let reverseRange = reverseRanges[i]; + + reverseOperations[i] = { + identifier: op.identifier, + range: reverseRange, + text: this.getValueInRange(op.range), + forceMoveMarkers: op.forceMoveMarkers + }; + } + + this._mightContainRTL = mightContainRTL; + this._mightContainNonBasicASCII = mightContainNonBasicASCII; + + const contentChanges = this._doApplyEdits(operations); + + let trimAutoWhitespaceLineNumbers: number[] = null; + if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { + // sort line numbers auto whitespace removal candidates for next edit descending + newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber); + + trimAutoWhitespaceLineNumbers = []; + for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) { + let lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber; + if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) { + // Do not have the same line number twice + continue; + } + + let prevContent = newTrimAutoWhitespaceCandidates[i].oldContent; + let lineContent = this.getLineContent(lineNumber); + + if (lineContent.length === 0 || lineContent === prevContent || strings.firstNonWhitespaceIndex(lineContent) !== -1) { + continue; + } + + trimAutoWhitespaceLineNumbers.push(lineNumber); + } + } + + return new ApplyEditsResult( + reverseOperations, + contentChanges, + trimAutoWhitespaceLineNumbers + ); + } + + /** + * Transform operations such that they represent the same logic edit, + * but that they also do not cause OOM crashes. + */ + private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] { + if (operations.length < 1000) { + // We know from empirical testing that a thousand edits work fine regardless of their shape. + return operations; + } + + // At one point, due to how events are emitted and how each operation is handled, + // some operations can trigger a high ammount of temporary string allocations, + // that will immediately get edited again. + // e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line + // Therefore, the strategy is to collapse all the operations into a huge single edit operation + return [this._toSingleEditOperation(operations)]; + } + + _toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation { + let forceMoveMarkers = false, + firstEditRange = operations[0].range, + lastEditRange = operations[operations.length - 1].range, + entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn), + lastEndLineNumber = firstEditRange.startLineNumber, + lastEndColumn = firstEditRange.startColumn, + result: string[] = []; + + for (let i = 0, len = operations.length; i < len; i++) { + let operation = operations[i], + range = operation.range; + + forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers; + + // (1) -- Push old text + for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) { + if (lineNumber === lastEndLineNumber) { + result.push(this.getLineContent(lineNumber).substring(lastEndColumn - 1)); + } else { + result.push('\n'); + result.push(this.getLineContent(lineNumber)); + } + } + + if (range.startLineNumber === lastEndLineNumber) { + result.push(this.getLineContent(range.startLineNumber).substring(lastEndColumn - 1, range.startColumn - 1)); + } else { + result.push('\n'); + result.push(this.getLineContent(range.startLineNumber).substring(0, range.startColumn - 1)); + } + + // (2) -- Push new text + if (operation.lines) { + for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) { + if (j !== 0) { + result.push('\n'); + } + result.push(operation.lines[j]); + } + } + + lastEndLineNumber = operation.range.endLineNumber; + lastEndColumn = operation.range.endColumn; + } + + return { + sortIndex: 0, + identifier: operations[0].identifier, + range: entireEditRange, + rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), + rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined), + lines: result.join('').split('\n'), + forceMoveMarkers: forceMoveMarkers, + isAutoWhitespaceEdit: false + }; + } + + private _doApplyEdits(operations: IValidatedEditOperation[]): IInternalModelContentChange[] { + operations.sort(PieceTreeTextBuffer._sortOpsDescending); + + let contentChanges: IInternalModelContentChange[] = []; + + // operations are from bottom to top + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + + const startLineNumber = op.range.startLineNumber; + const startColumn = op.range.startColumn; + const endLineNumber = op.range.endLineNumber; + const endColumn = op.range.endColumn; + + if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) { + // no-op + continue; + } + + const deletingLinesCnt = endLineNumber - startLineNumber; + const insertingLinesCnt = (op.lines ? op.lines.length - 1 : 0); + const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); + + const text = (op.lines ? op.lines.join(this.getEOL()) : ''); + + if (text) { + // replacement + this._pieceTree.delete(op.rangeOffset, op.rangeLength); + this._pieceTree.insert(op.rangeOffset, text); + + } else { + // deletion + this._pieceTree.delete(op.rangeOffset, op.rangeLength); + } + + if (editingLinesCnt < insertingLinesCnt) { + let newLinesContent: string[] = []; + for (let j = editingLinesCnt + 1; j <= insertingLinesCnt; j++) { + newLinesContent.push(op.lines[j]); + } + + newLinesContent[newLinesContent.length - 1] = this.getLineContent(startLineNumber + insertingLinesCnt - 1); + } + + const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn); + contentChanges.push({ + range: contentChangeRange, + rangeLength: op.rangeLength, + text: text, + rangeOffset: op.rangeOffset, + forceMoveMarkers: op.forceMoveMarkers + }); + } + return contentChanges; + } + + // #endregion + + // #region helper + // testing purpose. + public getPieceTree(): PieceTreeBase { + return this._pieceTree; + } + /** + * Assumes `operations` are validated and sorted ascending + */ + public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] { + let result: Range[] = []; + + let prevOpEndLineNumber: number; + let prevOpEndColumn: number; + let prevOp: IValidatedEditOperation = null; + for (let i = 0, len = operations.length; i < len; i++) { + let op = operations[i]; + + let startLineNumber: number; + let startColumn: number; + + if (prevOp) { + if (prevOp.range.endLineNumber === op.range.startLineNumber) { + startLineNumber = prevOpEndLineNumber; + startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn); + } else { + startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber); + startColumn = op.range.startColumn; + } + } else { + startLineNumber = op.range.startLineNumber; + startColumn = op.range.startColumn; + } + + let resultRange: Range; + + if (op.lines && op.lines.length > 0) { + // the operation inserts something + let lineCount = op.lines.length; + let firstLine = op.lines[0]; + let lastLine = op.lines[lineCount - 1]; + + if (lineCount === 1) { + // single line insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length); + } else { + // multi line insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1); + } + } else { + // There is nothing to insert + resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn); + } + + prevOpEndLineNumber = resultRange.endLineNumber; + prevOpEndColumn = resultRange.endColumn; + + result.push(resultRange); + prevOp = op; + } + + return result; + } + + private static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { + let r = Range.compareRangesUsingEnds(a.range, b.range); + if (r === 0) { + return a.sortIndex - b.sortIndex; + } + return r; + } + + private static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number { + let r = Range.compareRangesUsingEnds(a.range, b.range); + if (r === 0) { + return b.sortIndex - a.sortIndex; + } + return -r; + } + // #endregion +} diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts new file mode 100644 index 00000000000..ab46a6892b3 --- /dev/null +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts @@ -0,0 +1,180 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as strings from 'vs/base/common/strings'; +import { ITextBufferBuilder, DefaultEndOfLine, ITextBufferFactory, ITextBuffer } from 'vs/editor/common/model'; +import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; +import { StringBuffer, createLineStarts, createLineStartsFast } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; +import { CharCode } from 'vs/base/common/charCode'; + +export class PieceTreeTextBufferFactory implements ITextBufferFactory { + + constructor( + private readonly _chunks: StringBuffer[], + private readonly _bom: string, + private readonly _cr: number, + private readonly _lf: number, + private readonly _crlf: number, + private readonly _containsRTL: boolean, + private readonly _isBasicASCII: boolean, + private readonly _normalizeEOL: boolean + ) { } + + private _getEOL(defaultEOL: DefaultEndOfLine): '\r\n' | '\n' { + const totalEOLCount = this._cr + this._lf + this._crlf; + const totalCRCount = this._cr + this._crlf; + if (totalEOLCount === 0) { + // This is an empty file or a file with precisely one line + return (defaultEOL === DefaultEndOfLine.LF ? '\n' : '\r\n'); + } + if (totalCRCount > totalEOLCount / 2) { + // More than half of the file contains \r\n ending lines + return '\r\n'; + } + // At least one line more ends in \n + return '\n'; + } + + public create(defaultEOL: DefaultEndOfLine): ITextBuffer { + const eol = this._getEOL(defaultEOL); + let chunks = this._chunks; + + if (this._normalizeEOL && + ((eol === '\r\n' && (this._cr > 0 || this._lf > 0)) + || (eol === '\n' && (this._cr > 0 || this._crlf > 0))) + ) { + // Normalize pieces + for (let i = 0, len = chunks.length; i < len; i++) { + let str = chunks[i].buffer.replace(/\r\n|\r|\n/g, eol); + let newLineStart = createLineStartsFast(str); + chunks[i] = new StringBuffer(str, newLineStart); + } + } + + return new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._isBasicASCII); + } + + public getFirstLineText(lengthLimit: number): string { + return this._chunks[0].buffer.substr(0, 100).split(/\r\n|\r|\n/)[0]; + } +} + +export class PieceTreeTextBufferBuilder implements ITextBufferBuilder { + private chunks: StringBuffer[]; + private BOM: string; + + private _hasPreviousChar: boolean; + private _previousChar: number; + private _tmpLineStarts: number[]; + + private cr: number; + private lf: number; + private crlf: number; + private containsRTL: boolean; + private isBasicASCII: boolean; + + constructor() { + this.chunks = []; + this.BOM = ''; + + this._hasPreviousChar = false; + this._previousChar = 0; + this._tmpLineStarts = []; + + this.cr = 0; + this.lf = 0; + this.crlf = 0; + this.containsRTL = false; + this.isBasicASCII = true; + } + + public acceptChunk(chunk: string): void { + if (chunk.length === 0) { + return; + } + + if (this.chunks.length === 0) { + if (strings.startsWithUTF8BOM(chunk)) { + this.BOM = strings.UTF8_BOM_CHARACTER; + chunk = chunk.substr(1); + } + } + + const lastChar = chunk.charCodeAt(chunk.length - 1); + if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) { + // last character is \r or a high surrogate => keep it back + this._acceptChunk1(chunk.substr(0, chunk.length - 1), false); + this._hasPreviousChar = true; + this._previousChar = lastChar; + } else { + this._acceptChunk1(chunk, false); + this._hasPreviousChar = false; + this._previousChar = lastChar; + } + } + + private _acceptChunk1(chunk: string, allowEmptyStrings: boolean): void { + if (!allowEmptyStrings && chunk.length === 0) { + // Nothing to do + return; + } + + if (this._hasPreviousChar) { + this._acceptChunk2(String.fromCharCode(this._previousChar) + chunk); + } else { + this._acceptChunk2(chunk); + } + } + + private _acceptChunk2(chunk: string): void { + const lineStarts = createLineStarts(this._tmpLineStarts, chunk); + + this.chunks.push(new StringBuffer(chunk, lineStarts.lineStarts)); + this.cr += lineStarts.cr; + this.lf += lineStarts.lf; + this.crlf += lineStarts.crlf; + + if (this.isBasicASCII) { + this.isBasicASCII = lineStarts.isBasicASCII; + } + if (!this.isBasicASCII && !this.containsRTL) { + // No need to check if is basic ASCII + this.containsRTL = strings.containsRTL(chunk); + } + } + + public finish(normalizeEOL: boolean = true): PieceTreeTextBufferFactory { + this._finish(); + return new PieceTreeTextBufferFactory( + this.chunks, + this.BOM, + this.cr, + this.lf, + this.crlf, + this.containsRTL, + this.isBasicASCII, + normalizeEOL + ); + } + + private _finish(): void { + if (this.chunks.length === 0) { + this._acceptChunk1('', true); + } + + if (this._hasPreviousChar) { + this._hasPreviousChar = false; + // recreate last chunk + let lastChunk = this.chunks[this.chunks.length - 1]; + lastChunk.buffer += String.fromCharCode(this._previousChar); + let newLineStarts = createLineStartsFast(lastChunk.buffer); + lastChunk.lineStarts = newLineStarts; + if (this._previousChar === CharCode.CarriageReturn) { + this.cr++; + } + } + } +} diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts new file mode 100644 index 00000000000..84417b947cd --- /dev/null +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts @@ -0,0 +1,427 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { Piece, PieceTreeBase } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; + +export class TreeNode { + parent: TreeNode; + left: TreeNode; + right: TreeNode; + color: NodeColor; + + // Piece + piece: Piece; + size_left: number; // size of the left subtree (not inorder) + lf_left: number; // line feeds cnt in the left subtree (not in order) + + constructor(piece: Piece, color: NodeColor) { + this.piece = piece; + this.color = color; + this.size_left = 0; + this.lf_left = 0; + this.parent = null; + this.left = null; + this.right = null; + } + + public next(): TreeNode { + if (this.right !== SENTINEL) { + return leftest(this.right); + } + + let node: TreeNode = this; + + while (node.parent !== SENTINEL) { + if (node.parent.left === node) { + break; + } + + node = node.parent; + } + + if (node.parent === SENTINEL) { + return SENTINEL; + } else { + return node.parent; + } + } + + public prev(): TreeNode { + if (this.left !== SENTINEL) { + return righttest(this.left); + } + + let node: TreeNode = this; + + while (node.parent !== SENTINEL) { + if (node.parent.right === node) { + break; + } + + node = node.parent; + } + + if (node.parent === SENTINEL) { + return SENTINEL; + } else { + return node.parent; + } + } + + public detach(): void { + this.parent = null; + this.left = null; + this.right = null; + } +} + +export const SENTINEL: TreeNode = new TreeNode(null, NodeColor.Black); +SENTINEL.parent = SENTINEL; +SENTINEL.left = SENTINEL; +SENTINEL.right = SENTINEL; +SENTINEL.color = NodeColor.Black; + +export const enum NodeColor { + Black = 0, + Red = 1, +} + +export function leftest(node: TreeNode): TreeNode { + while (node.left !== SENTINEL) { + node = node.left; + } + return node; +} + +export function righttest(node: TreeNode): TreeNode { + while (node.right !== SENTINEL) { + node = node.right; + } + return node; +} + +export function calculateSize(node: TreeNode): number { + if (node === SENTINEL) { + return 0; + } + + return node.size_left + node.piece.length + calculateSize(node.right); +} + +export function calculateLF(node: TreeNode): number { + if (node === SENTINEL) { + return 0; + } + + return node.lf_left + node.piece.lineFeedCnt + calculateLF(node.right); +} + +export function resetSentinel(): void { + SENTINEL.parent = SENTINEL; +} + +export function leftRotate(tree: PieceTreeBase, x: TreeNode) { + let y = x.right; + + // fix size_left + y.size_left += x.size_left + (x.piece ? x.piece.length : 0); + y.lf_left += x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0); + x.right = y.left; + + if (y.left !== SENTINEL) { + y.left.parent = x; + } + y.parent = x.parent; + if (x.parent === SENTINEL) { + tree.root = y; + } else if (x.parent.left === x) { + x.parent.left = y; + } else { + x.parent.right = y; + } + y.left = x; + x.parent = y; +} + +export function rightRotate(tree: PieceTreeBase, y: TreeNode) { + let x = y.left; + y.left = x.right; + if (x.right !== SENTINEL) { + x.right.parent = y; + } + x.parent = y.parent; + + // fix size_left + y.size_left -= x.size_left + (x.piece ? x.piece.length : 0); + y.lf_left -= x.lf_left + (x.piece ? x.piece.lineFeedCnt : 0); + + if (y.parent === SENTINEL) { + tree.root = x; + } else if (y === y.parent.right) { + y.parent.right = x; + } else { + y.parent.left = x; + } + + x.right = y; + y.parent = x; +} + +export function rbDelete(tree: PieceTreeBase, z: TreeNode) { + let x: TreeNode; + let y: TreeNode; + + if (z.left === SENTINEL) { + y = z; + x = y.right; + } else if (z.right === SENTINEL) { + y = z; + x = y.left; + } else { + y = leftest(z.right); + x = y.right; + } + + if (y === tree.root) { + tree.root = x; + + // if x is null, we are removing the only node + x.color = NodeColor.Black; + z.detach(); + resetSentinel(); + tree.root.parent = SENTINEL; + + return; + } + + let yWasRed = (y.color === NodeColor.Red); + + if (y === y.parent.left) { + y.parent.left = x; + } else { + y.parent.right = x; + } + + if (y === z) { + x.parent = y.parent; + recomputeTreeMetadata(tree, x); + } else { + if (y.parent === z) { + x.parent = y; + } else { + x.parent = y.parent; + } + + // as we make changes to x's hierarchy, update size_left of subtree first + recomputeTreeMetadata(tree, x); + + y.left = z.left; + y.right = z.right; + y.parent = z.parent; + y.color = z.color; + + if (z === tree.root) { + tree.root = y; + } else { + if (z === z.parent.left) { + z.parent.left = y; + } else { + z.parent.right = y; + } + } + + if (y.left !== SENTINEL) { + y.left.parent = y; + } + if (y.right !== SENTINEL) { + y.right.parent = y; + } + // update metadata + // we replace z with y, so in this sub tree, the length change is z.item.length + y.size_left = z.size_left; + y.lf_left = z.lf_left; + recomputeTreeMetadata(tree, y); + } + + z.detach(); + + if (x.parent.left === x) { + let newSizeLeft = calculateSize(x); + let newLFLeft = calculateLF(x); + if (newSizeLeft !== x.parent.size_left || newLFLeft !== x.parent.lf_left) { + let delta = newSizeLeft - x.parent.size_left; + let lf_delta = newLFLeft - x.parent.lf_left; + x.parent.size_left = newSizeLeft; + x.parent.lf_left = newLFLeft; + updateTreeMetadata(tree, x.parent, delta, lf_delta); + } + } + + recomputeTreeMetadata(tree, x.parent); + + if (yWasRed) { + resetSentinel(); + return; + } + + // RB-DELETE-FIXUP + let w: TreeNode; + while (x !== tree.root && x.color === NodeColor.Black) { + if (x === x.parent.left) { + w = x.parent.right; + + if (w.color === NodeColor.Red) { + w.color = NodeColor.Black; + x.parent.color = NodeColor.Red; + leftRotate(tree, x.parent); + w = x.parent.right; + } + + if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { + w.color = NodeColor.Red; + x = x.parent; + } else { + if (w.right.color === NodeColor.Black) { + w.left.color = NodeColor.Black; + w.color = NodeColor.Red; + rightRotate(tree, w); + w = x.parent.right; + } + + w.color = x.parent.color; + x.parent.color = NodeColor.Black; + w.right.color = NodeColor.Black; + leftRotate(tree, x.parent); + x = tree.root; + } + } else { + w = x.parent.left; + + if (w.color === NodeColor.Red) { + w.color = NodeColor.Black; + x.parent.color = NodeColor.Red; + rightRotate(tree, x.parent); + w = x.parent.left; + } + + if (w.left.color === NodeColor.Black && w.right.color === NodeColor.Black) { + w.color = NodeColor.Red; + x = x.parent; + + } else { + if (w.left.color === NodeColor.Black) { + w.right.color = NodeColor.Black; + w.color = NodeColor.Red; + leftRotate(tree, w); + w = x.parent.left; + } + + w.color = x.parent.color; + x.parent.color = NodeColor.Black; + w.left.color = NodeColor.Black; + rightRotate(tree, x.parent); + x = tree.root; + } + } + } + x.color = NodeColor.Black; + resetSentinel(); +} + +export function fixInsert(tree: PieceTreeBase, x: TreeNode) { + recomputeTreeMetadata(tree, x); + + while (x !== tree.root && x.parent.color === NodeColor.Red) { + if (x.parent === x.parent.parent.left) { + const y = x.parent.parent.right; + + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; + } else { + if (x === x.parent.right) { + x = x.parent; + leftRotate(tree, x); + } + + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + rightRotate(tree, x.parent.parent); + } + } else { + const y = x.parent.parent.left; + + if (y.color === NodeColor.Red) { + x.parent.color = NodeColor.Black; + y.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + x = x.parent.parent; + } else { + if (x === x.parent.left) { + x = x.parent; + rightRotate(tree, x); + } + x.parent.color = NodeColor.Black; + x.parent.parent.color = NodeColor.Red; + leftRotate(tree, x.parent.parent); + } + } + } + + tree.root.color = NodeColor.Black; +} + +export function updateTreeMetadata(tree: PieceTreeBase, x: TreeNode, delta: number, lineFeedCntDelta: number): void { + // node length change or line feed count change + while (x !== tree.root && x !== SENTINEL) { + if (x.parent.left === x) { + x.parent.size_left += delta; + x.parent.lf_left += lineFeedCntDelta; + } + + x = x.parent; + } +} + +export function recomputeTreeMetadata(tree: PieceTreeBase, x: TreeNode) { + let delta = 0; + let lf_delta = 0; + if (x === tree.root) { + return; + } + + if (delta === 0) { + // go upwards till the node whose left subtree is changed. + while (x !== tree.root && x === x.parent.right) { + x = x.parent; + } + + if (x === tree.root) { + // well, it means we add a node to the end (inorder) + return; + } + + // x is the node whose right subtree is changed. + x = x.parent; + + delta = calculateSize(x.left) - x.size_left; + lf_delta = calculateLF(x.left) - x.lf_left; + x.size_left += delta; + x.lf_left += lf_delta; + } + + // go upwards till root. O(logN) + while (x !== tree.root && (delta !== 0 || lf_delta !== 0)) { + if (x.parent.left === x) { + x.parent.size_left += delta; + x.parent.lf_left += lf_delta; + } + + x = x.parent; + } +} diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index dff56a1a7a8..d64c382f47e 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -11,7 +11,7 @@ import { LanguageIdentifier, TokenizationRegistry, LanguageId } from 'vs/editor/ import { EditStack } from 'vs/editor/common/model/editStack'; import { Range, IRange } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { ModelRawContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelOptionsChangedEvent, IModelContentChangedEvent, InternalModelContentChangeEvent, ModelRawFlush, ModelRawEOLChanged } from 'vs/editor/common/model/textModelEvents'; +import { ModelRawContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelOptionsChangedEvent, IModelContentChangedEvent, InternalModelContentChangeEvent, ModelRawFlush, ModelRawEOLChanged, ModelRawChange, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import * as strings from 'vs/base/common/strings'; @@ -32,11 +32,22 @@ import { guessIndentation } from 'vs/editor/common/model/indentationGuesser'; import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { TextModelSearch, SearchParams } from 'vs/editor/common/model/textModelSearch'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IStringStream } from 'vs/platform/files/common/files'; +import { IStringStream, ITextSnapshot } from 'vs/platform/files/common/files'; import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; +import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; +import { ChunksTextBufferBuilder } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder'; // Here is the master switch for the text buffer implementation: +const USE_PIECE_TREE_IMPLEMENTATION = true; +const USE_CHUNKS_TEXT_BUFFER = false; + function createTextBufferBuilder() { + if (USE_PIECE_TREE_IMPLEMENTATION) { + return new PieceTreeTextBufferBuilder(); + } + if (USE_CHUNKS_TEXT_BUFFER) { + return new ChunksTextBufferBuilder(); + } return new LinesTextBufferBuilder(); } @@ -46,12 +57,16 @@ export function createTextBufferFactory(text: string): model.ITextBufferFactory return builder.finish(); } -export function createTextBufferFactoryFromStream(stream: IStringStream): TPromise { +export function createTextBufferFactoryFromStream(stream: IStringStream, filter?: (chunk: string) => string): TPromise { return new TPromise((c, e, p) => { let done = false; let builder = createTextBufferBuilder(); stream.on('data', (chunk) => { + if (filter) { + chunk = filter(chunk); + } + builder.acceptChunk(chunk); }); @@ -71,6 +86,17 @@ export function createTextBufferFactoryFromStream(stream: IStringStream): TPromi }); } +export function createTextBufferFactoryFromSnapshot(snapshot: ITextSnapshot): model.ITextBufferFactory { + let builder = createTextBufferBuilder(); + + let chunk: string; + while (typeof (chunk = snapshot.read()) === 'string') { + builder.acceptChunk(chunk); + } + + return builder.finish(); +} + export function createTextBuffer(value: string | model.ITextBufferFactory, defaultEOL: model.DefaultEndOfLine): model.ITextBuffer { const factory = (typeof value === 'string' ? createTextBufferFactory(value) : value); return factory.create(defaultEOL); @@ -96,6 +122,48 @@ function singleLetter(result: number): string { const LIMIT_FIND_COUNT = 999; export const LONG_LINE_BOUNDARY = 10000; +class TextModelSnapshot implements ITextSnapshot { + + private readonly _source: ITextSnapshot; + private _eos: boolean; + + constructor(source: ITextSnapshot) { + this._source = source; + this._eos = false; + } + + public read(): string { + if (this._eos) { + return null; + } + + let result: string[] = [], resultCnt = 0, resultLength = 0; + + do { + let tmp = this._source.read(); + + if (tmp === null) { + // end-of-stream + this._eos = true; + if (resultCnt === 0) { + return null; + } else { + return result.join(''); + } + } + + if (tmp.length > 0) { + result[resultCnt++] = tmp; + resultLength += tmp.length; + } + + if (resultLength >= 64 * 1024) { + return result.join(''); + } + } while (true); + } +} + export class TextModel extends Disposable implements model.ITextModel { private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB @@ -488,6 +556,10 @@ export class TextModel extends Disposable implements model.ITextModel { public isDominatedByLongLines(): boolean { this._assertNotDisposed(); + if (this.isTooLargeForTokenization()) { + // Cannot word wrap huge files anyways, so it doesn't really matter + return false; + } let smallLineCharCount = 0; let longLineCharCount = 0; @@ -630,8 +702,9 @@ export class TextModel extends Disposable implements model.ITextModel { return this._buffer.getOffsetAt(position.lineNumber, position.column); } - public getPositionAt(offset: number): Position { + public getPositionAt(rawOffset: number): Position { this._assertNotDisposed(); + let offset = (Math.min(this._buffer.getLength(), Math.max(0, rawOffset))); return this._buffer.getPositionAt(offset); } @@ -660,6 +733,10 @@ export class TextModel extends Disposable implements model.ITextModel { return fullModelValue; } + public createSnapshot(preserveBOM: boolean = false): ITextSnapshot { + return new TextModelSnapshot(this._buffer.createSnapshot(preserveBOM)); + } + public getValueLength(eol?: model.EndOfLinePreference, preserveBOM: boolean = false): number { this._assertNotDisposed(); const fullModelRange = this.getFullModelRange(); @@ -890,7 +967,8 @@ export class TextModel extends Disposable implements model.ITextModel { public modifyPosition(rawPosition: IPosition, offset: number): Position { this._assertNotDisposed(); - return this.getPositionAt(this.getOffsetAt(rawPosition) + offset); + let candidate = this.getOffsetAt(rawPosition) + offset; + return this.getPositionAt(Math.min(this._buffer.getLength(), Math.max(0, candidate))); } public getFullModelRange(): Range { @@ -1033,21 +1111,94 @@ export class TextModel extends Disposable implements model.ITextModel { } } + private static _eolCount(text: string): [number, number] { + let eolCount = 0; + let firstLineLength = 0; + for (let i = 0, len = text.length; i < len; i++) { + const chr = text.charCodeAt(i); + + if (chr === CharCode.CarriageReturn) { + if (eolCount === 0) { + firstLineLength = i; + } + eolCount++; + if (i + 1 < len && text.charCodeAt(i + 1) === CharCode.LineFeed) { + // \r\n... case + i++; // skip \n + } else { + // \r... case + } + } else if (chr === CharCode.LineFeed) { + if (eolCount === 0) { + firstLineLength = i; + } + eolCount++; + } + } + if (eolCount === 0) { + firstLineLength = text.length; + } + return [eolCount, firstLineLength]; + } + private _applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IIdentifiedSingleEditOperation[] { for (let i = 0, len = rawOperations.length; i < len; i++) { rawOperations[i].range = this.validateRange(rawOperations[i].range); } + + const oldLineCount = this._buffer.getLineCount(); const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace); - const rawContentChanges = result.rawChanges; + const newLineCount = this._buffer.getLineCount(); + const contentChanges = result.changes; this._trimAutoWhitespaceLines = result.trimAutoWhitespaceLineNumbers; - if (rawContentChanges.length !== 0 || contentChanges.length !== 0) { + if (contentChanges.length !== 0) { + let rawContentChanges: ModelRawChange[] = []; + + let lineCount = oldLineCount; for (let i = 0, len = contentChanges.length; i < len; i++) { - const contentChange = contentChanges[i]; - this._tokens.applyEdits(contentChange.range, contentChange.lines); + const change = contentChanges[i]; + const [eolCount, firstLineLength] = TextModel._eolCount(change.text); + this._tokens.applyEdits(change.range, eolCount, firstLineLength); this._onDidChangeDecorations.fire(); - this._decorationsTree.acceptReplace(contentChange.rangeOffset, contentChange.rangeLength, contentChange.text.length, contentChange.forceMoveMarkers); + this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers); + + const startLineNumber = change.range.startLineNumber; + const endLineNumber = change.range.endLineNumber; + + const deletingLinesCnt = endLineNumber - startLineNumber; + const insertingLinesCnt = eolCount; + const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); + + const changeLineCountDelta = (insertingLinesCnt - deletingLinesCnt); + + for (let j = editingLinesCnt; j >= 0; j--) { + const editLineNumber = startLineNumber + j; + const currentEditLineNumber = newLineCount - lineCount - changeLineCountDelta + editLineNumber; + rawContentChanges.push(new ModelRawLineChanged(editLineNumber, this.getLineContent(currentEditLineNumber))); + } + + if (editingLinesCnt < deletingLinesCnt) { + // Must delete some lines + const spliceStartLineNumber = startLineNumber + editingLinesCnt; + rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber)); + } + + if (editingLinesCnt < insertingLinesCnt) { + // Must insert some lines + const spliceLineNumber = startLineNumber + editingLinesCnt; + const cnt = insertingLinesCnt - editingLinesCnt; + const fromLineNumber = newLineCount - lineCount - cnt + spliceLineNumber + 1; + let newLines: string[] = []; + for (let i = 0; i < cnt; i++) { + let lineNumber = fromLineNumber + i; + newLines[lineNumber - fromLineNumber] = this.getLineContent(lineNumber); + } + rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines)); + } + + lineCount += changeLineCountDelta; } this._increaseVersionId(); diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index aa969b5334a..2f1526e618e 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -136,6 +136,23 @@ export class TextModelSearch { } if (searchData.regex.multiline) { + if (searchData.regex.source === '\\n') { + // Fast path for searching for EOL + let result: FindMatch[] = [], resultLen = 0; + for (let lineNumber = 1, lineCount = model.getLineCount(); lineNumber < lineCount; lineNumber++) { + const range = new Range(lineNumber, model.getLineMaxColumn(lineNumber), lineNumber + 1, 1); + if (captureMatches) { + result[resultLen++] = new FindMatch(range, null); + } else { + result[resultLen++] = new FindMatch(range, ['\n']); + } + + if (resultLen >= limitResultCount) { + break; + } + } + return result; + } return this._doFindMatchesMultiline(model, searchRange, new Searcher(searchData.wordSeparators, searchData.regex), captureMatches, limitResultCount); } return this._doFindMatchesLineByLine(model, searchRange, searchData, captureMatches, limitResultCount); diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index e190d4337bb..bc0a715dda9 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -285,34 +285,18 @@ export class ModelLinesTokens { //#region Editing - // TODO: simplify - public applyEdits(range: Range, lines: string[]): void { + public applyEdits(range: Range, eolCount: number, firstLineLength: number): void { const deletingLinesCnt = range.endLineNumber - range.startLineNumber; - const insertingLinesCnt = (lines ? lines.length - 1 : 0); + const insertingLinesCnt = eolCount; const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); - // Iterating descending to overlap with previous op - // in case there are common lines being edited in both for (let j = editingLinesCnt; j >= 0; j--) { - const editLineNumber = range.startLineNumber + j; - this.invalidateLine(editLineNumber - 1); - } - - if (editingLinesCnt < deletingLinesCnt) { - // Must delete some lines - const spliceStartLineNumber = range.startLineNumber + editingLinesCnt; - this.invalidateLine(spliceStartLineNumber - 1); - } - - if (editingLinesCnt < insertingLinesCnt) { - // Must insert some lines - const spliceLineNumber = range.startLineNumber + editingLinesCnt; - this.invalidateLine(spliceLineNumber - 1); + this.invalidateLine(range.startLineNumber + j - 1); } this._acceptDeleteRange(range); - this._acceptInsertText(new Position(range.startLineNumber, range.startColumn), lines); + this._acceptInsertText(new Position(range.startLineNumber, range.startColumn), eolCount, firstLineLength); } private _acceptDeleteRange(range: Range): void { @@ -350,9 +334,9 @@ export class ModelLinesTokens { this._tokens.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber); } - private _acceptInsertText(position: Position, insertLines: string[]): void { + private _acceptInsertText(position: Position, eolCount: number, firstLineLength: number): void { - if (!insertLines || insertLines.length === 0) { + if (eolCount === 0 && firstLineLength === 0) { // Nothing to insert return; } @@ -362,18 +346,18 @@ export class ModelLinesTokens { return; } - if (insertLines.length === 1) { + if (eolCount === 0) { // Inserting text on one line - this._tokens[lineIndex].insert(position.column - 1, insertLines[0].length); + this._tokens[lineIndex].insert(position.column - 1, firstLineLength); return; } const line = this._tokens[lineIndex]; line.deleteEnding(position.column - 1); - line.insert(position.column - 1, insertLines[0].length); + line.insert(position.column - 1, firstLineLength); - let insert: ModelLineTokens[] = new Array(insertLines.length - 1); - for (let i = insertLines.length - 2; i >= 0; i--) { + let insert: ModelLineTokens[] = new Array(eolCount); + for (let i = eolCount - 1; i >= 0; i--) { insert[i] = new ModelLineTokens(null); } this._tokens = arrays.arrayInsert(this._tokens, position.lineNumber, insert); diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index fdd0cec375e..c7fd1b7b243 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -17,6 +17,7 @@ import { TokenizationRegistryImpl } from 'vs/editor/common/modes/tokenizationReg import { Color } from 'vs/base/common/color'; import { IMarkerData } from 'vs/platform/markers/common/markers'; import * as model from 'vs/editor/common/model'; +import { isObject } from 'vs/base/common/types'; /** * Open ended enum at runtime @@ -343,6 +344,14 @@ export interface CodeAction { command?: Command; edit?: WorkspaceEdit; diagnostics?: IMarkerData[]; + kind?: string; +} + +/** + * @internal + */ +export interface CodeActionContext { + only?: string; } /** @@ -354,7 +363,7 @@ export interface CodeActionProvider { /** * Provide commands for the given document and range. */ - provideCodeActions(model: model.ITextModel, range: Range, token: CancellationToken): CodeAction[] | Thenable; + provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): CodeAction[] | Thenable; } /** @@ -817,19 +826,41 @@ export interface DocumentColorProvider { provideColorPresentations(model: model.ITextModel, colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable; } -export interface IResourceEdit { +/** + * @internal + */ +export function isResourceFileEdit(thing: any): thing is ResourceFileEdit { + return isObject(thing) && (Boolean((thing).newUri) || Boolean((thing).oldUri)); +} + +/** + * @internal + */ +export function isResourceTextEdit(thing: any): thing is ResourceTextEdit { + return isObject(thing) && (thing).resource && Array.isArray((thing).edits); +} + +export interface ResourceFileEdit { + oldUri: URI; + newUri: URI; +} + +export interface ResourceTextEdit { resource: URI; - range: IRange; - newText: string; + modelVersionId?: number; + edits: TextEdit[]; } + export interface WorkspaceEdit { - edits: IResourceEdit[]; - rejectReason?: string; + edits: Array; + rejectReason?: string; // TODO@joh, move to rename } + export interface RenameInitialValue { range: IRange; text?: string; } + export interface RenameProvider { provideRenameEdits(model: model.ITextModel, position: Position, newName: string, token: CancellationToken): WorkspaceEdit | Thenable; resolveInitialRenameValue?(model: model.ITextModel, position: Position, token: CancellationToken): RenameInitialValue | Thenable; diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 9855eda6939..24009cea46a 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -403,6 +403,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { insertPrefixSumValues[i] = outputLineCount; } + // TODO@Alex: use arrays.arrayInsert this.lines = this.lines.slice(0, fromLineNumber - 1).concat(insertLines).concat(this.lines.slice(fromLineNumber - 1)); this.prefixSumComputer.insertValues(fromLineNumber - 1, insertPrefixSumValues); diff --git a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts index 45a12373ca1..5b602985086 100644 --- a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts +++ b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts @@ -14,15 +14,18 @@ import { Position } from 'vs/editor/common/core/position'; import { Selection } from 'vs/editor/common/core/selection'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; +import { EditorAction, registerEditorAction, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, themeColorFromId } from 'vs/platform/theme/common/themeService'; import { editorBracketMatchBackground, editorBracketMatchBorder } from 'vs/editor/common/view/editorColorRegistry'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { TrackedRangeStickiness, IModelDeltaDecoration } from 'vs/editor/common/model'; +import { registerColor } from 'vs/platform/theme/common/colorRegistry'; +import { TrackedRangeStickiness, IModelDeltaDecoration, OverviewRulerLane } from 'vs/editor/common/model'; -class SelectBracketAction extends EditorAction { +const overviewRulerBracketMatchForeground = registerColor('editorOverviewRuler.bracketMatchForeground', { dark: '#A0A0A0', light: '#A0A0A0', hc: '#A0A0A0' }, nls.localize('overviewRulerBracketMatchForeground', 'Overview ruler marker color for matching brackets.')); + +class JumpToBracketAction extends EditorAction { constructor() { super({ id: 'editor.action.jumpToBracket', @@ -45,6 +48,25 @@ class SelectBracketAction extends EditorAction { } } +class SelectToBracketAction extends EditorAction { + constructor() { + super({ + id: 'editor.action.selectToBracket', + label: nls.localize('smartSelect.selectToBracket', "Select to Bracket"), + alias: 'Select to Bracket', + precondition: null + }); + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + let controller = BracketMatchingController.get(editor); + if (!controller) { + return; + } + controller.selectToBracket(); + } +} + type Brackets = [Range, Range]; class BracketsData { @@ -149,9 +171,58 @@ export class BracketMatchingController extends Disposable implements editorCommo this._editor.revealRange(newSelections[0]); } + public selectToBracket(): void { + const model = this._editor.getModel(); + if (!model) { + return; + } + const selection = this._editor.getSelection(); + if (!selection.isEmpty()) { + return; + } + + const position = selection.getStartPosition(); + + let brackets = model.matchBracket(position); + + let openBracket: Position = null; + let closeBracket: Position = null; + + if (!brackets) { + const nextBracket = model.findNextBracket(position); + if (nextBracket && nextBracket.range) { + brackets = model.matchBracket(nextBracket.range.getStartPosition()); + } + } + + if (brackets) { + if (brackets[0].startLineNumber === brackets[1].startLineNumber) { + openBracket = brackets[1].startColumn < brackets[0].startColumn ? + brackets[1].getStartPosition() : brackets[0].getStartPosition(); + closeBracket = brackets[1].startColumn < brackets[0].startColumn ? + brackets[0].getEndPosition() : brackets[1].getEndPosition(); + } else { + openBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? + brackets[1].getStartPosition() : brackets[0].getStartPosition(); + closeBracket = brackets[1].startLineNumber < brackets[0].startLineNumber ? + brackets[0].getEndPosition() : brackets[1].getEndPosition(); + } + } + + if (openBracket && closeBracket) { + this._editor.setSelection(new Range(openBracket.lineNumber, openBracket.column, closeBracket.lineNumber, closeBracket.column)); + } + } + + private static readonly _DECORATION_OPTIONS = ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - className: 'bracket-match' + className: 'bracket-match', + overviewRuler: { + color: themeColorFromId(overviewRulerBracketMatchForeground), + darkColor: themeColorFromId(overviewRulerBracketMatchForeground), + position: OverviewRulerLane.Center + } }); private _updateBrackets(): void { @@ -228,7 +299,8 @@ export class BracketMatchingController extends Disposable implements editorCommo } registerEditorContribution(BracketMatchingController); -registerEditorAction(SelectBracketAction); +registerEditorAction(SelectToBracketAction); +registerEditorAction(JumpToBracketAction); registerThemingParticipant((theme, collector) => { let bracketMatchBackground = theme.getColor(editorBracketMatchBackground); if (bracketMatchBackground) { diff --git a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts index 5a90a324fae..cecb3d534d2 100644 --- a/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts +++ b/src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor'; import { Position } from 'vs/editor/common/core/position'; +import { Selection } from 'vs/editor/common/core/selection'; import { TextModel } from 'vs/editor/common/model/textModel'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { MockMode } from 'vs/editor/test/common/mocks/mockMode'; @@ -98,4 +99,49 @@ suite('bracket matching', () => { model.dispose(); mode.dispose(); }); + + test('Select to next bracket', () => { + let mode = new BracketMode(); + let model = TextModel.createFromString('var x = (3 + (5-7)); y();', undefined, mode.getLanguageIdentifier()); + + withTestCodeEditor(null, { model: model }, (editor, cursor) => { + let bracketMatchingController = editor.registerAndInstantiateContribution(BracketMatchingController); + + + // start position in open brackets + editor.setPosition(new Position(1, 9)); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getPosition(), new Position(1, 20)); + assert.deepEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); + + // start position in close brackets + editor.setPosition(new Position(1, 20)); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getPosition(), new Position(1, 20)); + assert.deepEqual(editor.getSelection(), new Selection(1, 9, 1, 20)); + + // start position between brackets + editor.setPosition(new Position(1, 16)); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getPosition(), new Position(1, 19)); + assert.deepEqual(editor.getSelection(), new Selection(1, 14, 1, 19)); + + // start position outside brackets + editor.setPosition(new Position(1, 21)); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getPosition(), new Position(1, 25)); + assert.deepEqual(editor.getSelection(), new Selection(1, 23, 1, 25)); + + // do not break if no brackets are available + editor.setPosition(new Position(1, 26)); + bracketMatchingController.selectToBracket(); + assert.deepEqual(editor.getPosition(), new Position(1, 26)); + assert.deepEqual(editor.getSelection(), new Selection(1, 26, 1, 26)); + + bracketMatchingController.dispose(); + }); + + model.dispose(); + mode.dispose(); + }); }); diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index deacb765f44..7f0a8ac7ab4 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -396,7 +396,7 @@ export class FindModelBoundToEditorModel { const findScope = this._decorations.getFindScope(); if (findScope === null && this._state.matchesCount >= MATCHES_LIMIT) { - // Doing a replace on the entire file that is over 1k matches + // Doing a replace on the entire file that is over ${MATCHES_LIMIT} matches this._largeReplaceAll(); } else { this._regularReplaceAll(findScope); diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 283801a2d60..d898a618ca4 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -101,7 +101,7 @@ export class FoldingController implements IEditorContribution { */ public saveViewState(): { collapsedRegions?: CollapseMemento, lineCount?: number } { let model = this.editor.getModel(); - if (!model || !this._isEnabled) { + if (!model || !this._isEnabled || model.isTooLargeForTokenization()) { return {}; } return { collapsedRegions: this.foldingModel.getMemento(), lineCount: model.getLineCount() }; @@ -112,7 +112,7 @@ export class FoldingController implements IEditorContribution { */ public restoreViewState(state: { collapsedRegions?: CollapseMemento, lineCount?: number }): void { let model = this.editor.getModel(); - if (!model || !this._isEnabled) { + if (!model || !this._isEnabled || model.isTooLargeForTokenization()) { return; } if (!state || !state.collapsedRegions || state.lineCount !== model.getLineCount()) { @@ -133,7 +133,8 @@ export class FoldingController implements IEditorContribution { this.localToDispose = dispose(this.localToDispose); let model = this.editor.getModel(); - if (!this._isEnabled || !model) { + if (!this._isEnabled || !model || model.isTooLargeForTokenization()) { + // huge files get no view model, so they cannot support hidden areas return; } diff --git a/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts index b3ecb2c6d4b..f79912d8323 100644 --- a/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts @@ -14,20 +14,7 @@ import { DefinitionProviderRegistry, ImplementationProviderRegistry, TypeDefinit import { CancellationToken } from 'vs/base/common/cancellation'; import { asWinJsPromise } from 'vs/base/common/async'; import { Position } from 'vs/editor/common/core/position'; - -function outputResults(promises: TPromise[]) { - return TPromise.join(promises).then(allReferences => { - let result: Location[] = []; - for (let references of allReferences) { - if (Array.isArray(references)) { - result.push(...references); - } else if (references) { - result.push(references); - } - } - return result; - }); -} +import { flatten } from 'vs/base/common/arrays'; function getDefinitions( model: ITextModel, @@ -38,7 +25,7 @@ function getDefinitions( const provider = registry.ordered(model); // get results - const promises = provider.map((provider, idx) => { + const promises = provider.map((provider, idx): TPromise => { return asWinJsPromise((token) => { return provide(provider, model, position, token); }).then(undefined, err => { @@ -46,7 +33,9 @@ function getDefinitions( return null; }); }); - return outputResults(promises); + return TPromise.join(promises) + .then(flatten) + .then(references => references.filter(x => !!x)); } diff --git a/src/vs/editor/contrib/quickFix/codeActionTrigger.ts b/src/vs/editor/contrib/quickFix/codeActionTrigger.ts new file mode 100644 index 00000000000..a210e484446 --- /dev/null +++ b/src/vs/editor/contrib/quickFix/codeActionTrigger.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { startsWith } from 'vs/base/common/strings'; + +export class CodeActionKind { + private static readonly sep = '.'; + + public static readonly Empty = new CodeActionKind(''); + public static readonly Refactor = new CodeActionKind('refactor'); + + constructor( + public readonly value: string + ) { } + + public contains(other: string): boolean { + return this.value === other || startsWith(other, this.value + CodeActionKind.sep); + } +} + +export enum CodeActionAutoApply { + IfSingle = 1, + First = 2, + Never = 3 +} + +export interface CodeActionTrigger { + type: 'auto' | 'manual'; + kind?: CodeActionKind; + autoApply?: CodeActionAutoApply; +} \ No newline at end of file diff --git a/src/vs/editor/contrib/quickFix/quickFix.ts b/src/vs/editor/contrib/quickFix/quickFix.ts index 8e619e15c03..10bbbe4d5e8 100644 --- a/src/vs/editor/contrib/quickFix/quickFix.ts +++ b/src/vs/editor/contrib/quickFix/quickFix.ts @@ -14,16 +14,19 @@ import { onUnexpectedExternalError, illegalArgument } from 'vs/base/common/error import { IModelService } from 'vs/editor/common/services/modelService'; import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { CodeActionKind } from './codeActionTrigger'; -export function getCodeActions(model: ITextModel, range: Range): TPromise { +export function getCodeActions(model: ITextModel, range: Range, scope?: CodeActionKind): TPromise { const allResults: CodeAction[] = []; const promises = CodeActionProviderRegistry.all(model).map(support => { - return asWinJsPromise(token => support.provideCodeActions(model, range, token)).then(result => { + return asWinJsPromise(token => support.provideCodeActions(model, range, { only: scope ? scope.value : undefined }, token)).then(result => { if (Array.isArray(result)) { for (const quickFix of result) { if (quickFix) { - allResults.push(quickFix); + if (!scope || (quickFix.kind && scope.contains(quickFix.kind))) { + allResults.push(quickFix); + } } } } diff --git a/src/vs/editor/contrib/quickFix/quickFixCommands.ts b/src/vs/editor/contrib/quickFix/quickFixCommands.ts index 2d067db0bf0..61f424520f6 100644 --- a/src/vs/editor/contrib/quickFix/quickFixCommands.ts +++ b/src/vs/editor/contrib/quickFix/quickFixCommands.ts @@ -15,14 +15,15 @@ import { optional } from 'vs/platform/instantiation/common/instantiation'; import { IMarkerService } from 'vs/platform/markers/common/markers'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; +import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { QuickFixContextMenu } from './quickFixWidget'; import { LightBulbWidget } from './lightBulbWidget'; import { QuickFixModel, QuickFixComputeEvent } from './quickFixModel'; +import { CodeActionKind, CodeActionAutoApply } from './codeActionTrigger'; import { TPromise } from 'vs/base/common/winjs.base'; import { CodeAction } from 'vs/editor/common/modes'; -import { createBulkEdit } from 'vs/editor/browser/services/bulkEdit'; +import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; import { IFileService } from 'vs/platform/files/common/files'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -57,7 +58,7 @@ export class QuickFixController implements IEditorContribution { this._updateLightBulbTitle(); this._disposables.push( - this._quickFixContextMenu.onDidExecuteCodeAction(_ => this._model.trigger('auto')), + this._quickFixContextMenu.onDidExecuteCodeAction(_ => this._model.trigger({ type: 'auto' })), this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)), this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) @@ -70,9 +71,21 @@ export class QuickFixController implements IEditorContribution { } private _onQuickFixEvent(e: QuickFixComputeEvent): void { - if (e && e.type === 'manual') { - this._quickFixContextMenu.show(e.fixes, e.position); + if (e && e.trigger.kind) { + // Triggered for specific scope + // Apply if we only have one action or requested autoApply, otherwise show menu + e.fixes.then(fixes => { + if (e.trigger.autoApply === CodeActionAutoApply.First || (e.trigger.autoApply === CodeActionAutoApply.IfSingle && fixes.length === 1)) { + this._onApplyCodeAction(fixes[0]); + } else { + this._quickFixContextMenu.show(e.fixes, e.position); + } + }); + return; + } + if (e && e.trigger.type === 'manual') { + this._quickFixContextMenu.show(e.fixes, e.position); } else if (e && e.fixes) { // auto magically triggered // * update an existing list of code actions @@ -96,7 +109,11 @@ export class QuickFixController implements IEditorContribution { } public triggerFromEditorSelection(): void { - this._model.trigger('manual'); + this._model.trigger({ type: 'manual' }); + } + + public triggerCodeActionFromEditorSelection(kind?: CodeActionKind, autoApply?: CodeActionAutoApply): void { + this._model.trigger({ type: 'manual', kind, autoApply }); } private _updateLightBulbTitle(): void { @@ -112,9 +129,7 @@ export class QuickFixController implements IEditorContribution { private async _onApplyCodeAction(action: CodeAction): TPromise { if (action.edit) { - const edit = createBulkEdit(this._textModelService, this._editor, this._fileService); - edit.add(action.edit.edits); - await edit.finish(); + await BulkEdit.perform(action.edit.edits, this._textModelService, this._fileService, this._editor); } if (action.command) { @@ -148,5 +163,87 @@ export class QuickFixAction extends EditorAction { } } + +class CodeActionCommandArgs { + public static fromUser(arg: any): CodeActionCommandArgs { + if (!arg || typeof arg !== 'object') { + return new CodeActionCommandArgs(CodeActionKind.Empty, CodeActionAutoApply.IfSingle); + } + return new CodeActionCommandArgs( + CodeActionCommandArgs.getKindFromUser(arg), + CodeActionCommandArgs.getApplyFromUser(arg)); + } + + private static getApplyFromUser(arg: any) { + switch (typeof arg.apply === 'string' ? arg.apply.toLowerCase() : '') { + case 'first': + return CodeActionAutoApply.First; + + case 'never': + return CodeActionAutoApply.Never; + + case 'ifsingle': + default: + return CodeActionAutoApply.IfSingle; + } + } + + private static getKindFromUser(arg: any) { + return typeof arg.kind === 'string' + ? new CodeActionKind(arg.kind) + : CodeActionKind.Empty; + } + + private constructor( + public readonly kind: CodeActionKind, + public readonly apply: CodeActionAutoApply + ) { } +} + +export class CodeActionCommand extends EditorCommand { + + static readonly Id = 'editor.action.codeAction'; + + constructor() { + super({ + id: CodeActionCommand.Id, + precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider) + }); + } + + public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, userArg: any) { + const controller = QuickFixController.get(editor); + if (controller) { + const args = CodeActionCommandArgs.fromUser(userArg); + controller.triggerCodeActionFromEditorSelection(args.kind, args.apply); + } + } +} + + +export class RefactorAction extends EditorAction { + + static readonly Id = 'editor.action.refactor'; + + constructor() { + super({ + id: RefactorAction.Id, + label: nls.localize('refactor.label', "Refactor"), + alias: 'Refactor', + precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider) + }); + } + + public run(accessor: ServicesAccessor, editor: ICodeEditor): void { + const controller = QuickFixController.get(editor); + if (controller) { + controller.triggerCodeActionFromEditorSelection(CodeActionKind.Refactor, CodeActionAutoApply.Never); + } + } +} + + registerEditorContribution(QuickFixController); registerEditorAction(QuickFixAction); +registerEditorAction(RefactorAction); +registerEditorCommand(new CodeActionCommand()); diff --git a/src/vs/editor/contrib/quickFix/quickFixModel.ts b/src/vs/editor/contrib/quickFix/quickFixModel.ts index e2ff0dcd2a1..3e4366c4d63 100644 --- a/src/vs/editor/contrib/quickFix/quickFixModel.ts +++ b/src/vs/editor/contrib/quickFix/quickFixModel.ts @@ -13,6 +13,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { CodeActionProviderRegistry, CodeAction } from 'vs/editor/common/modes'; import { getCodeActions } from './quickFix'; +import { CodeActionTrigger } from './codeActionTrigger'; import { Position } from 'vs/editor/common/core/position'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -36,26 +37,26 @@ export class QuickFixOracle { this._disposables = dispose(this._disposables); } - trigger(type: 'manual' | 'auto'): void { + trigger(trigger: CodeActionTrigger): void { let rangeOrSelection = this._getRangeOfMarker() || this._getRangeOfSelectionUnlessWhitespaceEnclosed(); - if (!rangeOrSelection && type === 'manual') { + if (!rangeOrSelection && trigger.type === 'manual') { rangeOrSelection = this._editor.getSelection(); } - this._createEventAndSignalChange(type, rangeOrSelection); + this._createEventAndSignalChange(trigger, rangeOrSelection); } private _onMarkerChanges(resources: URI[]): void { const { uri } = this._editor.getModel(); for (const resource of resources) { if (resource.toString() === uri.toString()) { - this.trigger('auto'); + this.trigger({ type: 'auto' }); return; } } } private _onCursorChange(): void { - this.trigger('auto'); + this.trigger({ type: 'auto' }); } private _getRangeOfMarker(): Range { @@ -98,24 +99,24 @@ export class QuickFixOracle { return selection; } - private _createEventAndSignalChange(type: 'auto' | 'manual', rangeOrSelection: Range | Selection): void { + private _createEventAndSignalChange(trigger: CodeActionTrigger, rangeOrSelection: Range | Selection): void { if (!rangeOrSelection) { // cancel this._signalChange({ - type, + trigger, range: undefined, position: undefined, - fixes: undefined + fixes: undefined, }); } else { // actual const model = this._editor.getModel(); const range = model.validateRange(rangeOrSelection); const position = rangeOrSelection instanceof Selection ? rangeOrSelection.getPosition() : rangeOrSelection.getStartPosition(); - const fixes = getCodeActions(model, range); + const fixes = getCodeActions(model, range, trigger && trigger.kind); this._signalChange({ - type, + trigger, range, position, fixes @@ -125,7 +126,7 @@ export class QuickFixOracle { } export interface QuickFixComputeEvent { - type: 'auto' | 'manual'; + trigger: CodeActionTrigger; range: Range; position: Position; fixes: TPromise; @@ -172,13 +173,13 @@ export class QuickFixModel { && !this._editor.getConfiguration().readOnly) { this._quickFixOracle = new QuickFixOracle(this._editor, this._markerService, p => this._onDidChangeFixes.fire(p)); - this._quickFixOracle.trigger('auto'); + this._quickFixOracle.trigger({ type: 'auto' }); } } - trigger(type: 'auto' | 'manual'): void { + trigger(trigger: CodeActionTrigger): void { if (this._quickFixOracle) { - this._quickFixOracle.trigger(type); + this._quickFixOracle.trigger(trigger); } } } diff --git a/src/vs/editor/contrib/quickFix/test/quickFix.test.ts b/src/vs/editor/contrib/quickFix/test/quickFix.test.ts index 8e1fdc79473..2d2185e7529 100644 --- a/src/vs/editor/contrib/quickFix/test/quickFix.test.ts +++ b/src/vs/editor/contrib/quickFix/test/quickFix.test.ts @@ -8,10 +8,11 @@ import * as assert from 'assert'; import URI from 'vs/base/common/uri'; import Severity from 'vs/base/common/severity'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { CodeActionProviderRegistry, LanguageIdentifier, CodeActionProvider, Command, WorkspaceEdit, IResourceEdit } from 'vs/editor/common/modes'; +import { CodeActionProviderRegistry, LanguageIdentifier, CodeActionProvider, Command, WorkspaceEdit, ResourceTextEdit, CodeAction, CodeActionContext } from 'vs/editor/common/modes'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Range } from 'vs/editor/common/core/range'; import { getCodeActions } from 'vs/editor/contrib/quickFix/quickFix'; +import { CodeActionKind } from 'vs/editor/contrib/quickFix/codeActionTrigger'; suite('QuickFix', () => { @@ -57,7 +58,7 @@ suite('QuickFix', () => { bcd: { diagnostics: [], edit: new class implements WorkspaceEdit { - edits: IResourceEdit[]; + edits: ResourceTextEdit[]; }, title: 'abc' } @@ -120,4 +121,52 @@ suite('QuickFix', () => { assert.equal(actions.length, 6); assert.deepEqual(actions, expected); }); + + test('getCodeActions should filter by scope', async function () { + const provider = new class implements CodeActionProvider { + provideCodeActions(): CodeAction[] { + return [ + { title: 'a', kind: 'a' }, + { title: 'b', kind: 'b' }, + { title: 'a.b', kind: 'a.b' } + ]; + } + }; + + disposables.push(CodeActionProviderRegistry.register('fooLang', provider)); + + { + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a')); + assert.equal(actions.length, 2); + assert.strictEqual(actions[0].title, 'a'); + assert.strictEqual(actions[1].title, 'a.b'); + } + + { + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a.b')); + assert.equal(actions.length, 1); + assert.strictEqual(actions[0].title, 'a.b'); + } + + { + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a.b.c')); + assert.equal(actions.length, 0); + } + }); + + test('getCodeActions should forward requested scope to providers', async function () { + const provider = new class implements CodeActionProvider { + provideCodeActions(_model: any, _range: Range, context: CodeActionContext, _token: any): CodeAction[] { + return [ + { title: context.only, kind: context.only } + ]; + } + }; + + disposables.push(CodeActionProviderRegistry.register('fooLang', provider)); + + const actions = await getCodeActions(model, new Range(1, 1, 2, 1), new CodeActionKind('a')); + assert.equal(actions.length, 1); + assert.strictEqual(actions[0].title, 'a'); + }); }); diff --git a/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts b/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts index c2806d7d31e..a6c3b4663a7 100644 --- a/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts +++ b/src/vs/editor/contrib/quickFix/test/quickFixModel.test.ts @@ -47,7 +47,7 @@ suite('QuickFix', () => { test('Orcale -> marker added', done => { const oracle = new QuickFixOracle(editor, markerService, e => { - assert.equal(e.type, 'auto'); + assert.equal(e.trigger.type, 'auto'); assert.ok(e.fixes); e.fixes.then(fixes => { @@ -83,7 +83,7 @@ suite('QuickFix', () => { return new Promise((resolve, reject) => { const oracle = new QuickFixOracle(editor, markerService, e => { - assert.equal(e.type, 'auto'); + assert.equal(e.trigger.type, 'auto'); assert.ok(e.fixes); e.fixes.then(fixes => { oracle.dispose(); @@ -160,7 +160,7 @@ suite('QuickFix', () => { await new Promise(resolve => { let oracle = new QuickFixOracle(editor, markerService, e => { - assert.equal(e.type, 'auto'); + assert.equal(e.trigger.type, 'auto'); assert.deepEqual(e.range, { startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 4 }); assert.deepEqual(e.position, { lineNumber: 3, column: 1 }); diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index 88feea887c6..e164c10e766 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -18,7 +18,7 @@ import { registerEditorAction, registerEditorContribution, ServicesAccessor, Edi import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { createBulkEdit } from 'vs/editor/browser/services/bulkEdit'; +import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import RenameInputField from './renameInputField'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -190,9 +190,7 @@ class RenameController implements IEditorContribution { this._renameInputVisible.reset(); this.editor.focus(); - // start recording of file changes so that we can figure out if a file that - // is to be renamed conflicts with another (concurrent) modification - const edit = createBulkEdit(this._textModelResolverService, this.editor, this._fileService); + const edit = new BulkEdit(this.editor, null, this._textModelResolverService, this._fileService); const state = new EditorState(this.editor, CodeEditorStateFlag.Position | CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection | CodeEditorStateFlag.Scroll); const renameOperation = rename(this.editor.getModel(), this.editor.getPosition(), newName).then(result => { @@ -206,7 +204,7 @@ class RenameController implements IEditorContribution { } edit.add(result.edits); - return edit.finish().then(selection => { + return edit.perform().then(selection => { if (selection) { this.editor.setSelection(selection); } diff --git a/src/vs/editor/contrib/snippet/snippetSession.ts b/src/vs/editor/contrib/snippet/snippetSession.ts index af22d663d0b..30a06931cd7 100644 --- a/src/vs/editor/contrib/snippet/snippetSession.ts +++ b/src/vs/editor/contrib/snippet/snippetSession.ts @@ -15,7 +15,7 @@ import { Range } from 'vs/editor/common/core/range'; import { IPosition } from 'vs/editor/common/core/position'; import { groupBy } from 'vs/base/common/arrays'; import { dispose } from 'vs/base/common/lifecycle'; -import { SelectionBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, ClipboardBasedVariableResolver } from './snippetVariables'; +import { SelectionBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, ClipboardBasedVariableResolver, TimeBasedVariableResolver } from './snippetVariables'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -318,7 +318,8 @@ export class SnippetSession { .resolveVariables(new CompositeSnippetVariableResolver([ modelBasedVariableResolver, new ClipboardBasedVariableResolver(clipboardService, idx, indexedSelections.length), - new SelectionBasedVariableResolver(model, selection) + new SelectionBasedVariableResolver(model, selection), + new TimeBasedVariableResolver ])); const offset = model.getOffsetAt(start) + delta; diff --git a/src/vs/editor/contrib/snippet/snippetVariables.ts b/src/vs/editor/contrib/snippet/snippetVariables.ts index f3b77a67181..9ca69afdfa4 100644 --- a/src/vs/editor/contrib/snippet/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/snippetVariables.ts @@ -9,10 +9,17 @@ import { basename, dirname } from 'vs/base/common/paths'; import { ITextModel } from 'vs/editor/common/model'; import { Selection } from 'vs/editor/common/core/selection'; import { VariableResolver, Variable, Text } from 'vs/editor/contrib/snippet/snippetParser'; -import { getLeadingWhitespace, commonPrefixLength, isFalsyOrWhitespace } from 'vs/base/common/strings'; +import { getLeadingWhitespace, commonPrefixLength, isFalsyOrWhitespace, pad } from 'vs/base/common/strings'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; export const KnownSnippetVariableNames = Object.freeze({ + 'CURRENT_YEAR': true, + 'CURRENT_YEAR_SHORT': true, + 'CURRENT_MONTH': true, + 'CURRENT_DATE': true, + 'CURRENT_HOUR': true, + 'CURRENT_MINUTE': true, + 'CURRENT_SECOND': true, 'SELECTION': true, 'CLIPBOARD': true, 'TM_SELECTED_TEXT': true, @@ -170,3 +177,28 @@ export class ClipboardBasedVariableResolver implements VariableResolver { } } } + +export class TimeBasedVariableResolver implements VariableResolver { + + resolve(variable: Variable): string { + const { name } = variable; + + if (name === 'CURRENT_YEAR') { + return String(new Date().getFullYear()); + } else if (name === 'CURRENT_YEAR_SHORT') { + return String(new Date().getFullYear()).slice(-2); + } else if (name === 'CURRENT_MONTH') { + return pad((new Date().getMonth().valueOf() + 1), 2); + } else if (name === 'CURRENT_DATE') { + return pad(new Date().getDate().valueOf(), 2); + } else if (name === 'CURRENT_HOUR') { + return pad(new Date().getHours().valueOf(), 2); + } else if (name === 'CURRENT_MINUTE') { + return pad(new Date().getMinutes().valueOf(), 2); + } else if (name === 'CURRENT_SECOND') { + return pad(new Date().getSeconds().valueOf(), 2); + } + + return undefined; + } +} diff --git a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts index 704173368f7..7eb0f74f147 100644 --- a/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetVariables.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { isWindows } from 'vs/base/common/platform'; import URI from 'vs/base/common/uri'; import { Selection } from 'vs/editor/common/core/selection'; -import { SelectionBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, ClipboardBasedVariableResolver } from 'vs/editor/contrib/snippet/snippetVariables'; +import { SelectionBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, ClipboardBasedVariableResolver, TimeBasedVariableResolver } from 'vs/editor/contrib/snippet/snippetVariables'; import { SnippetParser, Variable, VariableResolver } from 'vs/editor/contrib/snippet/snippetParser'; import { TextModel } from 'vs/editor/common/model/textModel'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; @@ -261,4 +261,25 @@ suite('Snippet Variables Resolver', function () { resolver = new ClipboardBasedVariableResolver(clipboardService, 0, 2); assertVariableResolve(resolver, 'CLIPBOARD', 'line1'); }); + + + function assertVariableResolve3(resolver: VariableResolver, varName: string) { + const snippet = new SnippetParser().parse(`$${varName}`); + const variable = snippet.children[0]; + + assert.equal(variable.resolve(resolver), true, `${varName} failed to resolve`); + } + + test('Add time variables for snippets #41631', function () { + + const resolver = new TimeBasedVariableResolver; + + assertVariableResolve3(resolver, 'CURRENT_YEAR'); + assertVariableResolve3(resolver, 'CURRENT_YEAR_SHORT'); + assertVariableResolve3(resolver, 'CURRENT_MONTH'); + assertVariableResolve3(resolver, 'CURRENT_DATE'); + assertVariableResolve3(resolver, 'CURRENT_HOUR'); + assertVariableResolve3(resolver, 'CURRENT_MINUTE'); + assertVariableResolve3(resolver, 'CURRENT_SECOND'); + }); }); diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index c1222e825b2..b3a73b17cd9 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -95,7 +95,7 @@ export class SuggestController implements IEditorContribution { @IInstantiationService private _instantiationService: IInstantiationService, ) { this._model = new SuggestModel(this._editor); - this._memory = _instantiationService.createInstance(SuggestMemories); + this._memory = _instantiationService.createInstance(SuggestMemories, this._editor.getConfiguration().contribInfo.selectSuggestions); this._toDispose.push(this._model.onDidTrigger(e => { if (!this._widget) { @@ -103,29 +103,22 @@ export class SuggestController implements IEditorContribution { } this._widget.showTriggered(e.auto); })); - let lastSelectedItem: ICompletionItem; this._toDispose.push(this._model.onDidSuggest(e => { - let index = this._memory.select(this._editor.getModel().getLanguageIdentifier(), e.completionModel.items, lastSelectedItem); - if (index >= 0) { - lastSelectedItem = e.completionModel.items[index]; - } else { - index = 0; - lastSelectedItem = undefined; - } + let index = this._memory.select(this._editor.getModel(), this._editor.getPosition(), e.completionModel.items); this._widget.showSuggestions(e.completionModel, index, e.isFrozen, e.auto); })); this._toDispose.push(this._model.onDidCancel(e => { if (this._widget && !e.retrigger) { this._widget.hideWidget(); - lastSelectedItem = undefined; } })); // Manage the acceptSuggestionsOnEnter context key let acceptSuggestionsOnEnter = SuggestContext.AcceptSuggestionsOnEnter.bindTo(_contextKeyService); let updateFromConfig = () => { - const { acceptSuggestionOnEnter } = this._editor.getConfiguration().contribInfo; + const { acceptSuggestionOnEnter, selectSuggestions } = this._editor.getConfiguration().contribInfo; acceptSuggestionsOnEnter.set(acceptSuggestionOnEnter === 'on' || acceptSuggestionOnEnter === 'smart'); + this._memory.setMode(selectSuggestions); }; this._toDispose.push(this._editor.onDidChangeConfiguration((e) => updateFromConfig())); updateFromConfig(); @@ -194,7 +187,7 @@ export class SuggestController implements IEditorContribution { } protected _onDidSelectItem(event: ISelectedSuggestion): void { - if (!event.item) { + if (!event || !event.item) { this._model.cancel(); return; } @@ -209,12 +202,8 @@ export class SuggestController implements IEditorContribution { this._editor.pushUndoStop(); } - // remember this suggestion for future invocations - // when it wasn't the first suggestion but from the group - // of top suggestions (cons -> const, console, constructor) - if (event.model.items[0].score === event.item.score) { - this._memory.remember(this._editor.getModel().getLanguageIdentifier(), event.item); - } + // keep item in memory + this._memory.memorize(this._editor.getModel(), this._editor.getPosition(), event.item); let { insertText } = suggestion; if (suggestion.snippetType !== 'textmate') { diff --git a/src/vs/editor/contrib/suggest/suggestMemory.ts b/src/vs/editor/contrib/suggest/suggestMemory.ts index 46a02a46e85..e434231cf0e 100644 --- a/src/vs/editor/contrib/suggest/suggestMemory.ts +++ b/src/vs/editor/contrib/suggest/suggestMemory.ts @@ -5,119 +5,210 @@ 'use strict'; import { ICompletionItem } from 'vs/editor/contrib/suggest/completionModel'; -import { LRUCache } from 'vs/base/common/map'; -import { LanguageIdentifier } from 'vs/editor/common/modes'; +import { LRUCache, TernarySearchTree } from 'vs/base/common/map'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { ITextModel } from 'vs/editor/common/model'; +import { IPosition } from 'vs/editor/common/core/position'; +import { RunOnceScheduler } from 'vs/base/common/async'; -export class SuggestMemories { +export abstract class Memory { - private readonly _storagePrefix = 'suggest/memories'; - private readonly _data = new Map(); + abstract memorize(model: ITextModel, pos: IPosition, item: ICompletionItem): void; - constructor( - @IStorageService private _storageService: IStorageService - ) { + abstract select(model: ITextModel, pos: IPosition, items: ICompletionItem[]): number; + + abstract toJSON(): object; + + abstract fromJSON(data: object): void; +} + +export class NoMemory extends Memory { + + memorize(model: ITextModel, pos: IPosition, item: ICompletionItem): void { + // no-op + } + + select(model: ITextModel, pos: IPosition, items: ICompletionItem[]): number { + return 0; + } + + toJSON() { + return undefined; + } + + fromJSON() { // } +} - remember({ language }: LanguageIdentifier, item: ICompletionItem): void { - let memory = this._data.get(language); - if (!memory) { - memory = new SuggestMemory(); - this._data.set(language, memory); - } - memory.remember(item); - this._storageService.store(`${this._storagePrefix}/${language}`, JSON.stringify(memory), StorageScope.WORKSPACE); +export interface MemItem { + type: string; + insertText: string; + touch: number; +} + +export class LRUMemory extends Memory { + + private _cache = new LRUCache(300, .66); + private _seq = 0; + + memorize(model: ITextModel, pos: IPosition, item: ICompletionItem): void { + const { label } = item.suggestion; + const key = `${model.getLanguageIdentifier().language}/${label}`; + this._cache.set(key, { + touch: this._seq++, + type: item.suggestion.type, + insertText: undefined + }); } - select({ language }: LanguageIdentifier, items: ICompletionItem[], last: ICompletionItem): number { - let memory = this._data.get(language); - if (!memory) { - const key: string = `${this._storagePrefix}/${language}`; - const raw = this._storageService.get(key, StorageScope.WORKSPACE); - if (raw) { - try { - const tuples = <[string, MemoryItem][]>JSON.parse(raw); - memory = new SuggestMemory(tuples); - last = undefined; - this._data.set(language, memory); - } catch (e) { - this._storageService.remove(key, StorageScope.WORKSPACE); + select(model: ITextModel, pos: IPosition, items: ICompletionItem[]): number { + // in order of completions, select the first + // that has been used in the past + let { word } = model.getWordUntilPosition(pos); + + let res = 0; + let seq = -1; + if (word.length === 0) { + for (let i = 0; i < items.length; i++) { + const { suggestion } = items[i]; + const key = `${model.getLanguageIdentifier().language}/${suggestion.label}`; + const item = this._cache.get(key); + if (item && item.touch > seq && item.type === suggestion.type) { + seq = item.touch; + res = i; } } } - if (memory) { - return memory.select(items, last); - } else { - return -1; + return res; + } + + toJSON(): object { + let data: [string, MemItem][] = []; + this._cache.forEach((value, key) => { + data.push([key, value]); + }); + return data; + } + + fromJSON(data: [string, MemItem][]): void { + this._cache.clear(); + let seq = 0; + for (const [key, value] of data) { + value.touch = seq; + this._cache.set(key, value); } + this._seq = this._cache.size; } } -export interface MemoryItem { - type: string; - insertText: string; -} +export class PrefixMemory extends Memory { -export class SuggestMemory { + private _trie = TernarySearchTree.forStrings(); + private _seq = 0; - private readonly _memory = new LRUCache(400, 0.75); - - constructor(tuples?: [string, MemoryItem][]) { - if (tuples) { - for (const [word, item] of tuples) { - this._memory.set(word, item); - } - } + memorize(model: ITextModel, pos: IPosition, item: ICompletionItem): void { + const { word } = model.getWordUntilPosition(pos); + const key = `${model.getLanguageIdentifier().language}/${word}`; + this._trie.set(key, { + type: item.suggestion.type, + insertText: item.suggestion.insertText, + touch: this._seq++ + }); } - remember(item: ICompletionItem): void { - if (item.word) { - this._memory.set(item.word, { insertText: item.suggestion.insertText, type: item.suggestion.type }); + select(model: ITextModel, pos: IPosition, items: ICompletionItem[]): number { + let { word } = model.getWordUntilPosition(pos); + if (!word) { + return 0; } - } - - select(items: ICompletionItem[], last: ICompletionItem): number { - - if (items.length === 0) { - return -1; + let key = `${model.getLanguageIdentifier().language}/${word}`; + let item = this._trie.get(key); + if (!item) { + item = this._trie.findSubstr(key); } - - const topScore = items[0].score; - - for (let i = 0; i < items.length; i++) { - - if (topScore !== items[i].score) { - // we only take a look at the bucket - // of top matches, hence we return - // as soon as we see an item that - // hasn't the top score anymore - return -1; - } - - if (items[i] === last) { - // prefer the last selected item when - // there is one - return i; - } - if (items[i].word) { - const item = this._memory.get(items[i].word); - if (this._matches(item, items[i])) { + if (item) { + for (let i = 0; i < items.length; i++) { + let { type, insertText } = items[i].suggestion; + if (type === item.type && insertText === item.insertText) { return i; } } } - return -1; + return 0; } - private _matches(item: MemoryItem, candidate: ICompletionItem): boolean { - return item && item.insertText === candidate.suggestion.insertText && item.type === candidate.suggestion.type; + toJSON(): object { + + let entries: [string, MemItem][] = []; + this._trie.forEach((value, key) => entries.push([key, value])); + + // sort by last recently used (touch), then + // take the top 200 item and normalize their + // touch + entries + .sort((a, b) => -(a[1].touch - b[1].touch)) + .forEach((value, i) => value[1].touch = i); + + return entries.slice(0, 200); } - toJSON(): [string, MemoryItem][] { - const tuples: [string, MemoryItem][] = []; - this._memory.forEach((value, key) => tuples.push([key, value])); - return tuples; + fromJSON(data: [string, MemItem][]): void { + this._trie.clear(); + if (data.length > 0) { + this._seq = data[0][1].touch + 1; + for (const [key, value] of data) { + this._trie.set(key, value); + } + } + } +} + +export type MemMode = 'never' | 'byRecency' | 'byPrefix'; + +export class SuggestMemories { + + private readonly _storagePrefix = 'suggest/memories'; + + private _mode: MemMode; + private _strategy: Memory; + private _persistSoon: RunOnceScheduler; + + constructor( + mode: MemMode, + @IStorageService private _storageService: IStorageService + ) { + this._persistSoon = new RunOnceScheduler(() => this._flush(), 3000); + this.setMode(mode); + } + + setMode(mode: MemMode): void { + if (this._mode === mode) { + return; + } + this._mode = mode; + this._strategy = mode === 'byPrefix' ? new PrefixMemory() : mode === 'byRecency' ? new LRUMemory() : new NoMemory(); + + try { + const raw = this._storageService.get(`${this._storagePrefix}/${this._mode}`, StorageScope.WORKSPACE); + this._strategy.fromJSON(JSON.parse(raw)); + } catch (e) { + // things can go wrong with JSON... + } + } + + memorize(model: ITextModel, pos: IPosition, item: ICompletionItem): void { + this._strategy.memorize(model, pos, item); + this._persistSoon.schedule(); + } + + select(model: ITextModel, pos: IPosition, items: ICompletionItem[]): number { + return this._strategy.select(model, pos, items); + } + + private _flush() { + const raw = JSON.stringify(this._strategy); + this._storageService.store(`${this._storagePrefix}/${this._mode}`, raw, StorageScope.WORKSPACE); } } diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 6624f1ca547..05c83cead70 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -667,7 +667,7 @@ export class SuggestWidget implements IContentWidget, IDelegate this.show(); break; case State.Frozen: - hide(this.messageElement, this.details.element); + hide(this.messageElement); show(this.listElement); this.show(); break; diff --git a/src/vs/editor/contrib/suggest/test/completionModel.test.ts b/src/vs/editor/contrib/suggest/test/completionModel.test.ts index 7d78bfe1451..e86f045c606 100644 --- a/src/vs/editor/contrib/suggest/test/completionModel.test.ts +++ b/src/vs/editor/contrib/suggest/test/completionModel.test.ts @@ -11,37 +11,37 @@ import { CompletionModel } from 'vs/editor/contrib/suggest/completionModel'; import { IPosition } from 'vs/editor/common/core/position'; import { TPromise } from 'vs/base/common/winjs.base'; -suite('CompletionModel', function () { +export function createSuggestItem(label: string, overwriteBefore: number, type: SuggestionType = 'property', incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }): ISuggestionItem { - function createSuggestItem(label: string, overwriteBefore: number, type: SuggestionType = 'property', incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }): ISuggestionItem { + return new class implements ISuggestionItem { - return new class implements ISuggestionItem { + position = position; - position = position; + suggestion: ISuggestion = { + label, + overwriteBefore, + insertText: label, + type + }; - suggestion: ISuggestion = { - label, - overwriteBefore, - insertText: label, - type - }; + container: ISuggestResult = { + incomplete, + suggestions: [this.suggestion] + }; - container: ISuggestResult = { - incomplete, - suggestions: [this.suggestion] - }; - - support: ISuggestSupport = { - provideCompletionItems(): any { - return; - } - }; - - resolve(): TPromise { - return null; + support: ISuggestSupport = { + provideCompletionItems(): any { + return; } }; - } + + resolve(): TPromise { + return null; + } + }; +} +suite('CompletionModel', function () { + let model: CompletionModel; diff --git a/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts b/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts new file mode 100644 index 00000000000..9d69016057f --- /dev/null +++ b/src/vs/editor/contrib/suggest/test/suggestMemory.test.ts @@ -0,0 +1,86 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import { LRUMemory, NoMemory, PrefixMemory } from 'vs/editor/contrib/suggest/suggestMemory'; +import { ITextModel } from 'vs/editor/common/model'; +import { TextModel } from 'vs/editor/common/model/textModel'; +import { ICompletionItem } from 'vs/editor/contrib/suggest/completionModel'; +import { createSuggestItem } from 'vs/editor/contrib/suggest/test/completionModel.test'; +import { IPosition } from 'vs/editor/common/core/position'; + +suite('SuggestMemories', function () { + + let pos: IPosition; + let buffer: ITextModel; + let items: ICompletionItem[]; + + setup(function () { + pos = { lineNumber: 1, column: 1 }; + buffer = TextModel.createFromString('This is some text'); + items = [ + createSuggestItem('foo', 0), + createSuggestItem('bar', 0) + ]; + }); + + test('NoMemory', function () { + + const mem = new NoMemory(); + + assert.equal(mem.select(buffer, pos, items), 0); + assert.equal(mem.select(buffer, pos, []), 0); + + mem.memorize(buffer, pos, items[0]); + mem.memorize(buffer, pos, null); + }); + + test('ShyMemories', function () { + + const mem = new LRUMemory(); + mem.memorize(buffer, pos, items[1]); + + assert.equal(mem.select(buffer, pos, items), 1); + assert.equal(mem.select(buffer, { lineNumber: 1, column: 3 }, items), 0); + + mem.memorize(buffer, pos, items[0]); + assert.equal(mem.select(buffer, pos, items), 0); + + assert.equal(mem.select(buffer, pos, [ + createSuggestItem('new', 0), + createSuggestItem('bar', 0) + ]), 1); + + assert.equal(mem.select(buffer, pos, [ + createSuggestItem('new1', 0), + createSuggestItem('new2', 0) + ]), 0); + + }); + + test('PrefixMemory', function () { + + const mem = new PrefixMemory(); + buffer.setValue('constructor'); + const item0 = createSuggestItem('console', 0); + const item1 = createSuggestItem('const', 0); + const item2 = createSuggestItem('constructor', 0); + const item3 = createSuggestItem('constant', 0); + const items = [item0, item1, item2, item3]; + + mem.memorize(buffer, { lineNumber: 1, column: 2 }, item1); // c -> const + mem.memorize(buffer, { lineNumber: 1, column: 3 }, item0); // co -> console + mem.memorize(buffer, { lineNumber: 1, column: 4 }, item2); // con -> constructor + + assert.equal(mem.select(buffer, { lineNumber: 1, column: 1 }, items), 0); + assert.equal(mem.select(buffer, { lineNumber: 1, column: 2 }, items), 1); + assert.equal(mem.select(buffer, { lineNumber: 1, column: 3 }, items), 0); + assert.equal(mem.select(buffer, { lineNumber: 1, column: 4 }, items), 2); + assert.equal(mem.select(buffer, { lineNumber: 1, column: 7 }, items), 2); // find substr + }); + +}); diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 5c5b72caa39..eded61cea6f 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -329,11 +329,11 @@ export function registerCodeLensProvider(languageId: string, provider: modes.Cod */ export function registerCodeActionProvider(languageId: string, provider: CodeActionProvider): IDisposable { return modes.CodeActionProviderRegistry.register(languageId, { - provideCodeActions: (model: model.ITextModel, range: Range, token: CancellationToken): (modes.Command | modes.CodeAction)[] | Thenable<(modes.Command | modes.CodeAction)[]> => { + provideCodeActions: (model: model.ITextModel, range: Range, context: modes.CodeActionContext, token: CancellationToken): (modes.Command | modes.CodeAction)[] | Thenable<(modes.Command | modes.CodeAction)[]> => { let markers = StaticServices.markerService.get().read({ resource: model.uri }).filter(m => { return Range.areIntersectingOrTouching(m, range); }); - return provider.provideCodeActions(model, range, { markers }, token); + return provider.provideCodeActions(model, range, { markers, only: context.only }, token); } }); } @@ -401,6 +401,11 @@ export interface CodeActionContext { * @readonly */ readonly markers: IMarkerData[]; + + /** + * Requested kind of actions to return. + */ + readonly only?: string; } /** @@ -525,6 +530,18 @@ export interface CompletionItem { * line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~ */ textEdit?: model.ISingleEditOperation; + /** + * An optional array of additional text edits that are applied when + * selecting this completion. Edits must not overlap with the main edit + * nor with themselves. + */ + additionalTextEdits?: model.ISingleEditOperation[]; + /** + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + commitCharacters?: string[]; } /** * Represents a collection of [completion items](#CompletionItem) to be presented @@ -634,7 +651,9 @@ class SuggestAdapter { command: item.command, sortText: item.sortText, filterText: item.filterText, - snippetType: 'internal' + snippetType: 'internal', + additionalTextEdits: item.additionalTextEdits, + commitCharacters: item.commitCharacters }; let editRange = item.textEdit ? item.textEdit.range : item.range; if (editRange) { diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 8071e7863ea..552156aca88 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -40,6 +40,7 @@ import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyServ import { IMenuService } from 'vs/platform/actions/common/actions'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl'; +import { ILogService, NullLogService } from 'vs/platform/log/common/log'; export interface IEditorContextViewService extends IContextViewService { dispose(): void; @@ -142,6 +143,8 @@ export module StaticServices { export const storageService = define(IStorageService, () => NullStorageService); + export const logService = define(ILogService, () => new NullLogService()); + } export class DynamicStandaloneServices extends Disposable { diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 1ccd43194a1..87e6d2d6ea6 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -1852,6 +1852,36 @@ suite('Editor Controller - Regression tests', () => { assertCursor(cursor, new Selection(1, 12, 1, 12)); }); }); + + test('issue #41573 - delete across multiple lines does not shrink the selection when word wraps', () => { + const model = TextModel.createFromString([ + 'Authorization: \'Bearer pHKRfCTFSnGxs6akKlb9ddIXcca0sIUSZJutPHYqz7vEeHdMTMh0SGN0IGU3a0n59DXjTLRsj5EJ2u33qLNIFi9fk5XF8pK39PndLYUZhPt4QvHGLScgSkK0L4gwzkzMloTQPpKhqiikiIOvyNNSpd2o8j29NnOmdTUOKi9DVt74PD2ohKxyOrWZ6oZprTkb3eKajcpnS0LABKfaw2rmv4\',' + ].join('\n')); + const config = new TestConfiguration({ + wordWrap: 'wordWrapColumn', + wordWrapColumn: 100 + }); + const viewModel = new ViewModel(0, config, model, null); + const cursor = new Cursor(config, model, viewModel); + + console.log(viewModel.getLineCount()); + + moveTo(cursor, 1, 43, false); + moveTo(cursor, 1, 147, true); + assertCursor(cursor, new Selection(1, 43, 1, 147)); + + model.applyEdits([{ + range: new Range(1, 1, 1, 43), + text: '' + }]); + + assertCursor(cursor, new Selection(1, 1, 1, 105)); + + cursor.dispose(); + viewModel.dispose(); + config.dispose(); + model.dispose(); + }); }); suite('Editor Controller - Cursor Configuration', () => { diff --git a/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts new file mode 100644 index 00000000000..f466e4d21c8 --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/benchmarkUtils.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITextBufferBuilder, ITextBufferFactory, ITextBuffer, DefaultEndOfLine } from 'vs/editor/common/model'; +import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; +import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; +import { ChunksTextBufferBuilder } from 'vs/editor/common/model/chunksTextBuffer/chunksTextBufferBuilder'; + +export function doBenchmark(id: string, ts: T[], fn: (t: T) => void) { + let columns: string[] = [id]; + for (let i = 0; i < ts.length; i++) { + var start = process.hrtime(); + fn(ts[i]); + var diff = process.hrtime(start); + columns.push(`${(diff[0] * 1000 + diff[1] / 1000000).toFixed(3)} ms`); + } + console.log('|' + columns.join('\t|') + '|'); +} + +export interface IBenchmark { + name: string; + /** + * Before each cycle, this function will be called to create TextBufferFactory + */ + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => ITextBufferFactory; + /** + * Before each cycle, this function will be called to do pre-work for text buffer. + * This will be called onece `buildBuffer` is finished. + */ + preCycle: (textBuffer: ITextBuffer) => void; + /** + * The function we are benchmarking + */ + fn: (textBuffer: ITextBuffer) => void; +} + +export class BenchmarkSuite { + name: string; + iterations: number; + benchmarks: IBenchmark[]; + + constructor(suiteOptions: { name: string, iterations: number }) { + this.name = suiteOptions.name; + this.iterations = suiteOptions.iterations; + this.benchmarks = []; + } + + add(benchmark: IBenchmark) { + this.benchmarks.push(benchmark); + } + + run() { + console.log(`|${this.name}\t|line buffer\t|piece table\t|edcore\t`); + console.log('|---|---|---|---|'); + for (let i = 0; i < this.benchmarks.length; i++) { + let benchmark = this.benchmarks[i]; + let columns: string[] = [benchmark.name]; + [new LinesTextBufferBuilder(), new PieceTreeTextBufferBuilder(), new ChunksTextBufferBuilder()].forEach((builder: ITextBufferBuilder) => { + let timeDiffTotal = 0.0; + for (let j = 0; j < this.iterations; j++) { + let factory = benchmark.buildBuffer(builder); + let buffer = factory.create(DefaultEndOfLine.LF); + benchmark.preCycle(buffer); + var start = process.hrtime(); + benchmark.fn(buffer); + var diff = process.hrtime(start); + timeDiffTotal += (diff[0] * 1000 * 1000 + diff[1] / 1000); + } + columns.push(`${(timeDiffTotal / 1000 / this.iterations).toFixed(3)} ms`); + }); + console.log('|' + columns.join('\t|') + '|'); + } + console.log('\n'); + } +} diff --git a/src/vs/editor/test/common/model/benchmark/bootstrap.js b/src/vs/editor/test/common/model/benchmark/bootstrap.js new file mode 100644 index 00000000000..a93aabeb980 --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/bootstrap.js @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +require('../../../../../../bootstrap-amd').bootstrap('vs/editor/test/common/model/benchmark/entry'); \ No newline at end of file diff --git a/src/vs/editor/test/common/model/benchmark/entry.ts b/src/vs/editor/test/common/model/benchmark/entry.ts new file mode 100644 index 00000000000..e1b4221dd66 --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/entry.ts @@ -0,0 +1,9 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import 'vs/editor/test/common/model/benchmark/modelbuilder.benchmark'; +import 'vs/editor/test/common/model/benchmark/operations.benchmark'; +import 'vs/editor/test/common/model/benchmark/searchNReplace.benchmark'; \ No newline at end of file diff --git a/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts b/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts new file mode 100644 index 00000000000..41445a17df9 --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/modelbuilder.benchmark.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { LinesTextBufferBuilder } from 'vs/editor/common/model/linesTextBuffer/linesTextBufferBuilder'; +import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; +import { ITextBufferBuilder } from 'vs/editor/common/model'; +import { generateRandomChunkWithLF } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; +import { doBenchmark } from 'vs/editor/test/common/model/benchmark/benchmarkUtils'; + +let linesTextBufferBuilder = new LinesTextBufferBuilder(); +let pieceTreeTextBufferBuilder = new PieceTreeTextBufferBuilder(); +let chunks = []; + +for (let i = 0; i < 100; i++) { + chunks.push(generateRandomChunkWithLF(16 * 1000, 64 * 1000)); +} + +let modelBuildBenchmark = function (id: string, builders: ITextBufferBuilder[], chunkCnt: number) { + doBenchmark(id, builders, builder => { + for (let i = 0, len = Math.min(chunkCnt, chunks.length); i < len; i++) { + builder.acceptChunk(chunks[i]); + } + builder.finish(); + }); +}; + +console.log(`|model builder\t|line buffer\t|piece table\t|`); +console.log('|---|---|---|'); +for (let i of [10, 100]) { + modelBuildBenchmark(`${i} random chunks`, [linesTextBufferBuilder, pieceTreeTextBufferBuilder], i); +} diff --git a/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts b/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts new file mode 100644 index 00000000000..286fd3531e7 --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts @@ -0,0 +1,137 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITextBufferBuilder, EndOfLinePreference } from 'vs/editor/common/model'; +import { BenchmarkSuite } from 'vs/editor/test/common/model/benchmark/benchmarkUtils'; +import { generateRandomChunkWithLF, generateRandomEdits, generateSequentialInserts, getRandomInt } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; +import { Range } from 'vs/editor/common/core/range'; + +let fileSizes = [1, 1000, 64 * 1000, 32 * 1000 * 1000]; +let editTypes = [ + { + id: 'random edits', + generateEdits: generateRandomEdits + }, + { + id: 'sequential inserts', + generateEdits: generateSequentialInserts + } +]; + +for (let fileSize of fileSizes) { + let chunks = []; + + let chunkCnt = Math.floor(fileSize / (64 * 1000)); + if (chunkCnt === 0) { + chunks.push(generateRandomChunkWithLF(fileSize, fileSize)); + } else { + let chunk = generateRandomChunkWithLF(64 * 1000, 64 * 1000); + // try to avoid OOM + for (let j = 0; j < chunkCnt; j++) { + chunks.push(Buffer.from(chunk + j).toString()); + } + } + + for (let editType of editTypes) { + const edits = editType.generateEdits(chunks, 1000); + + let editsSuite = new BenchmarkSuite({ + name: `File Size: ${fileSize}Byte, ${editType.id}`, + iterations: 10 + }); + + editsSuite.add({ + name: `apply 1000 edits`, + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => { + chunks.forEach(ck => textBufferBuilder.acceptChunk(ck)); + return textBufferBuilder.finish(); + }, + preCycle: (textBuffer) => { + return textBuffer; + }, + fn: (textBuffer) => { + // for line model, this loop doesn't reflect the real situation. + for (let k = 0; k < edits.length; k++) { + textBuffer.applyEdits([edits[k]], false); + } + } + }); + + editsSuite.add({ + name: `Read all lines after 1000 edits`, + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => { + chunks.forEach(ck => textBufferBuilder.acceptChunk(ck)); + return textBufferBuilder.finish(); + }, + preCycle: (textBuffer) => { + for (let k = 0; k < edits.length; k++) { + textBuffer.applyEdits([edits[k]], false); + } + return textBuffer; + }, + fn: (textBuffer) => { + for (let j = 0, len = textBuffer.getLineCount(); j < len; j++) { + var str = textBuffer.getLineContent(j + 1); + let firstChar = str.charCodeAt(0); + let lastChar = str.charCodeAt(str.length - 1); + firstChar = firstChar - lastChar; + lastChar = firstChar + lastChar; + firstChar = lastChar - firstChar; + } + } + }); + + editsSuite.add({ + name: `Read 10 random windows after 1000 edits`, + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => { + chunks.forEach(ck => textBufferBuilder.acceptChunk(ck)); + return textBufferBuilder.finish(); + }, + preCycle: (textBuffer) => { + for (let k = 0; k < edits.length; k++) { + textBuffer.applyEdits([edits[k]], false); + } + return textBuffer; + }, + fn: (textBuffer) => { + for (let i = 0; i < 10; i++) { + let minLine = 1; + let maxLine = textBuffer.getLineCount(); + let startLine = getRandomInt(minLine, Math.max(minLine, maxLine - 100)); + let endLine = Math.min(maxLine, startLine + 100); + for (let j = startLine; j < endLine; j++) { + var str = textBuffer.getLineContent(j + 1); + let firstChar = str.charCodeAt(0); + let lastChar = str.charCodeAt(str.length - 1); + firstChar = firstChar - lastChar; + lastChar = firstChar + lastChar; + firstChar = lastChar - firstChar; + } + } + } + }); + + editsSuite.add({ + name: `save file after 1000 edits`, + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => { + chunks.forEach(ck => textBufferBuilder.acceptChunk(ck)); + return textBufferBuilder.finish(); + }, + preCycle: (textBuffer) => { + for (let k = 0; k < edits.length; k++) { + textBuffer.applyEdits([edits[k]], false); + } + return textBuffer; + }, + fn: (textBuffer) => { + const lineCount = textBuffer.getLineCount(); + const fullModelRange = new Range(1, 1, lineCount, textBuffer.getLineLength(lineCount) + 1); + textBuffer.getValueInRange(fullModelRange, EndOfLinePreference.LF); + } + }); + + editsSuite.run(); + } +} \ No newline at end of file diff --git a/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts b/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts new file mode 100644 index 00000000000..6c4667ca0fa --- /dev/null +++ b/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { ITextBufferBuilder } from 'vs/editor/common/model'; +import { generateRandomReplaces, generateRandomChunkWithLF } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; +import { BenchmarkSuite } from 'vs/editor/test/common/model/benchmark/benchmarkUtils'; + +let fileSizes = [1, 1000, 64 * 1000, 32 * 1000 * 1000]; + +for (let fileSize of fileSizes) { + let chunks = []; + + let chunkCnt = Math.floor(fileSize / (64 * 1000)); + if (chunkCnt === 0) { + chunks.push(generateRandomChunkWithLF(fileSize, fileSize)); + } else { + let chunk = generateRandomChunkWithLF(64 * 1000, 64 * 1000); + // try to avoid OOM + for (let j = 0; j < chunkCnt; j++) { + chunks.push(Buffer.from(chunk + j).toString()); + } + } + + let replaceSuite = new BenchmarkSuite({ + name: `File Size: ${fileSize}Byte`, + iterations: 10 + }); + + let edits = generateRandomReplaces(chunks, 500, 5, 10); + + for (let i of [10, 100, 500]) { + replaceSuite.add({ + name: `replace ${i} occurrences`, + buildBuffer: (textBufferBuilder: ITextBufferBuilder) => { + chunks.forEach(ck => textBufferBuilder.acceptChunk(ck)); + return textBufferBuilder.finish(); + }, + preCycle: (textBuffer) => { + return textBuffer; + }, + fn: (textBuffer) => { + textBuffer.applyEdits(edits.slice(0, i), false); + } + }); + } + + replaceSuite.run(); +} \ No newline at end of file diff --git a/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts b/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts new file mode 100644 index 00000000000..a6cc8f6f22d --- /dev/null +++ b/src/vs/editor/test/common/model/chunksTextBuffer/bufferPiece.test.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import { BufferPiece } from 'vs/editor/common/model/chunksTextBuffer/bufferPiece'; + +suite('BufferPiece', () => { + test('findLineStartBeforeOffset', () => { + let piece = new BufferPiece([ + 'Line1\r\n', + 'l2\n', + 'another\r', + 'and\r\n', + 'finally\n', + 'last' + ].join('')); + + assert.equal(piece.length(), 35); + assert.deepEqual(piece.findLineStartBeforeOffset(0), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(1), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(2), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(3), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(4), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(5), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(6), -1); + assert.deepEqual(piece.findLineStartBeforeOffset(7), 0); + assert.deepEqual(piece.findLineStartBeforeOffset(8), 0); + assert.deepEqual(piece.findLineStartBeforeOffset(9), 0); + assert.deepEqual(piece.findLineStartBeforeOffset(10), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(11), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(12), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(13), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(14), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(15), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(16), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(17), 1); + assert.deepEqual(piece.findLineStartBeforeOffset(18), 2); + assert.deepEqual(piece.findLineStartBeforeOffset(19), 2); + assert.deepEqual(piece.findLineStartBeforeOffset(20), 2); + assert.deepEqual(piece.findLineStartBeforeOffset(21), 2); + assert.deepEqual(piece.findLineStartBeforeOffset(22), 2); + assert.deepEqual(piece.findLineStartBeforeOffset(23), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(24), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(25), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(26), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(27), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(28), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(29), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(30), 3); + assert.deepEqual(piece.findLineStartBeforeOffset(31), 4); + assert.deepEqual(piece.findLineStartBeforeOffset(32), 4); + assert.deepEqual(piece.findLineStartBeforeOffset(33), 4); + assert.deepEqual(piece.findLineStartBeforeOffset(34), 4); + assert.deepEqual(piece.findLineStartBeforeOffset(35), 4); + assert.deepEqual(piece.findLineStartBeforeOffset(36), 4); + }); +}); diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts index 9b1c70f96b1..8d7119d2077 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBufferBuilderAuto.test.ts @@ -5,7 +5,7 @@ 'use strict'; import { testModelBuilder } from './linesTextBufferBuilder.test'; -import { CharCode } from 'vs/base/common/charCode'; +import { getRandomInt, getRandomEOLSequence, getRandomString } from 'vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils'; const GENERATE_TESTS = false; @@ -21,30 +21,6 @@ suite('ModelBuilder Auto Tests', () => { }); -function getRandomInt(min: number, max: number): number { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function getRandomEOLSequence(): string { - let rnd = getRandomInt(1, 3); - if (rnd === 1) { - return '\n'; - } - if (rnd === 2) { - return '\r'; - } - return '\r\n'; -} - -function getRandomString(minLength: number, maxLength: number): string { - let length = getRandomInt(minLength, maxLength); - let r = ''; - for (let i = 0; i < length; i++) { - r += String.fromCharCode(getRandomInt(CharCode.a, CharCode.z)); - } - return r; -} - function generateRandomFile(): string { let lineCount = getRandomInt(1, 10); let mixedEOLSequence = getRandomInt(1, 2) === 1 ? true : false; diff --git a/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts b/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts new file mode 100644 index 00000000000..b43de70c81b --- /dev/null +++ b/src/vs/editor/test/common/model/linesTextBuffer/textBufferAutoTestUtils.ts @@ -0,0 +1,170 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { CharCode } from 'vs/base/common/charCode'; +import { IIdentifiedSingleEditOperation, DefaultEndOfLine, ITextBufferBuilder, ITextBuffer } from 'vs/editor/common/model'; +import { Range } from 'vs/editor/common/core/range'; + +export function getRandomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +export function getRandomEOLSequence(): string { + let rnd = getRandomInt(1, 3); + if (rnd === 1) { + return '\n'; + } + if (rnd === 2) { + return '\r'; + } + return '\r\n'; +} + +export function getRandomString(minLength: number, maxLength: number): string { + let length = getRandomInt(minLength, maxLength); + let r = ''; + for (let i = 0; i < length; i++) { + r += String.fromCharCode(getRandomInt(CharCode.a, CharCode.z)); + } + return r; +} + +export function generateRandomEdits(chunks: string[], editCnt: number): IIdentifiedSingleEditOperation[] { + let lines = []; + for (let i = 0; i < chunks.length; i++) { + let newLines = chunks[i].split(/\r\n|\r|\n/); + if (lines.length === 0) { + lines.push(...newLines); + } else { + newLines[0] = lines[lines.length - 1] + newLines[0]; + lines.splice(lines.length - 1, 1, ...newLines); + } + } + + let ops: IIdentifiedSingleEditOperation[] = []; + + for (let i = 0; i < editCnt; i++) { + let line = getRandomInt(1, lines.length); + let startColumn = getRandomInt(1, Math.max(lines[line - 1].length, 1)); + let endColumn = getRandomInt(startColumn, Math.max(lines[line - 1].length, startColumn)); + let text: string = ''; + if (Math.random() < .5) { + text = getRandomString(5, 10); + } + + ops.push({ + text: text, + range: new Range(line, startColumn, line, endColumn) + }); + lines[line - 1] = lines[line - 1].substring(0, startColumn - 1) + text + lines[line - 1].substring(endColumn - 1); + } + + return ops; +} + +export function generateSequentialInserts(chunks: string[], editCnt: number): IIdentifiedSingleEditOperation[] { + let lines = []; + for (let i = 0; i < chunks.length; i++) { + let newLines = chunks[i].split(/\r\n|\r|\n/); + if (lines.length === 0) { + lines.push(...newLines); + } else { + newLines[0] = lines[lines.length - 1] + newLines[0]; + lines.splice(lines.length - 1, 1, ...newLines); + } + } + + let ops: IIdentifiedSingleEditOperation[] = []; + + for (let i = 0; i < editCnt; i++) { + let line = lines.length; + let column = lines[line - 1].length + 1; + let text: string = ''; + if (Math.random() < .5) { + text = '\n'; + lines.push(''); + } else { + text = getRandomString(1, 2); + lines[line - 1] += text; + } + + ops.push({ + text: text, + range: new Range(line, column, line, column) + }); + } + + return ops; +} + +export function generateRandomReplaces(chunks: string[], editCnt: number, searchStringLen: number, replaceStringLen: number): IIdentifiedSingleEditOperation[] { + let lines = []; + for (let i = 0; i < chunks.length; i++) { + let newLines = chunks[i].split(/\r\n|\r|\n/); + if (lines.length === 0) { + lines.push(...newLines); + } else { + newLines[0] = lines[lines.length - 1] + newLines[0]; + lines.splice(lines.length - 1, 1, ...newLines); + } + } + + let ops: IIdentifiedSingleEditOperation[] = []; + let chunkSize = Math.max(1, Math.floor(lines.length / editCnt)); + let chunkCnt = Math.floor(lines.length / chunkSize); + let replaceString = getRandomString(replaceStringLen, replaceStringLen); + + let previousChunksLength = 0; + for (let i = 0; i < chunkCnt; i++) { + let startLine = previousChunksLength + 1; + let endLine = previousChunksLength + chunkSize; + let line = getRandomInt(startLine, endLine); + let maxColumn = lines[line - 1].length + 1; + let startColumn = getRandomInt(1, maxColumn); + let endColumn = Math.min(maxColumn, startColumn + searchStringLen); + + ops.push({ + text: replaceString, + range: new Range(line, startColumn, line, endColumn) + }); + previousChunksLength = endLine; + } + + return ops; +} + +export function createMockText(lineCount: number, minColumn: number, maxColumn: number) { + let fixedEOL = getRandomEOLSequence(); + let lines: string[] = []; + for (let i = 0; i < lineCount; i++) { + if (i !== 0) { + lines.push(fixedEOL); + } + lines.push(getRandomString(minColumn, maxColumn)); + } + return lines.join(''); +} + +export function createMockBuffer(str: string, bufferBuilder: ITextBufferBuilder): ITextBuffer { + bufferBuilder.acceptChunk(str); + let bufferFactory = bufferBuilder.finish(); + let buffer = bufferFactory.create(DefaultEndOfLine.LF); + return buffer; +} + +export function generateRandomChunkWithLF(minLength: number, maxLength: number): string { + let length = getRandomInt(minLength, maxLength); + let r = ''; + for (let i = 0; i < length; i++) { + let randomI = getRandomInt(0, CharCode.z - CharCode.a + 1); + if (randomI === 0 && Math.random() < 0.3) { + r += '\n'; + } else { + r += String.fromCharCode(randomI + CharCode.a - 1); + } + } + return r; +} \ No newline at end of file diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index 92b7e5b714a..e610caa3ddf 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -129,7 +129,6 @@ suite('Editor Model - Model', () => { thisModel.applyEdits([EditOperation.insert(new Position(1, 3), ' new line\nNo longer')]); assert.deepEqual(e, new ModelRawContentChangedEvent( [ - new ModelRawLineChanged(1, 'My new line First Line'), new ModelRawLineChanged(1, 'My new line'), new ModelRawLinesInserted(2, 2, ['No longer First Line']), ], @@ -245,7 +244,6 @@ suite('Editor Model - Model', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 2, 6))]); assert.deepEqual(e, new ModelRawContentChangedEvent( [ - new ModelRawLineChanged(1, 'My '), new ModelRawLineChanged(1, 'My Second Line'), new ModelRawLinesDeleted(2, 2), ], @@ -266,7 +264,6 @@ suite('Editor Model - Model', () => { thisModel.applyEdits([EditOperation.delete(new Range(1, 4, 3, 5))]); assert.deepEqual(e, new ModelRawContentChangedEvent( [ - new ModelRawLineChanged(1, 'My '), new ModelRawLineChanged(1, 'My Third Line'), new ModelRawLinesDeleted(2, 3), ], diff --git a/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts new file mode 100644 index 00000000000..a396f91cc40 --- /dev/null +++ b/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.test.ts @@ -0,0 +1,1592 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as assert from 'assert'; +import { Position } from 'vs/editor/common/core/position'; +import { Range } from 'vs/editor/common/core/range'; +import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; +import { DefaultEndOfLine } from 'vs/editor/common/model'; +import { PieceTreeBase } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; +import { SENTINEL, NodeColor, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase'; +import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; + +const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n'; + +function randomChar() { + return alphabet[randomInt(alphabet.length)]; +} + +function randomInt(bound: number) { + return Math.floor(Math.random() * bound); +} + +function randomStr(len: number) { + if (len === null) { + len = 10; + } + return (function () { + var j, ref, results; + results = []; + for ( + j = 1, ref = len; + 1 <= ref ? j < ref : j > ref; + 1 <= ref ? j++ : j-- + ) { + results.push(randomChar()); + } + return results; + })().join(''); +} + +function trimLineFeed(text: string): string { + if (text.length === 0) { + return text; + } + + if (text.length === 1) { + if ( + text.charCodeAt(text.length - 1) === 10 || + text.charCodeAt(text.length - 1) === 13 + ) { + return ''; + } + return text; + } + + if (text.charCodeAt(text.length - 1) === 10) { + if (text.charCodeAt(text.length - 2) === 13) { + return text.slice(0, -2); + } + return text.slice(0, -1); + } + + if (text.charCodeAt(text.length - 1) === 13) { + return text.slice(0, -1); + } + + return text; +} + +//#region Assertion + +function testLinesContent(str: string, pieceTable: PieceTreeBase) { + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assert.equal(pieceTable.getLinesRawContent(), str); + for (let i = 0; i < lines.length; i++) { + assert.equal(pieceTable.getLineContent(i + 1), lines[i]); + assert.equal( + trimLineFeed( + pieceTable.getValueInRange( + new Range( + i + 1, + 1, + i + 1, + lines[i].length + (i === lines.length - 1 ? 1 : 2) + ) + ) + ), + lines[i] + ); + } +} + +function testLineStarts(str: string, pieceTable: PieceTreeBase) { + let lineStarts = [0]; + + // Reset regex to search from the beginning + let _regex = new RegExp(/\r\n|\r|\n/g); + _regex.lastIndex = 0; + let prevMatchStartIndex = -1; + let prevMatchLength = 0; + + let m: RegExpExecArray; + do { + if (prevMatchStartIndex + prevMatchLength === str.length) { + // Reached the end of the line + break; + } + + m = _regex.exec(str); + if (!m) { + break; + } + + const matchStartIndex = m.index; + const matchLength = m[0].length; + + if ( + matchStartIndex === prevMatchStartIndex && + matchLength === prevMatchLength + ) { + // Exit early if the regex matches the same range twice + break; + } + + prevMatchStartIndex = matchStartIndex; + prevMatchLength = matchLength; + + lineStarts.push(matchStartIndex + matchLength); + } while (m); + + for (let i = 0; i < lineStarts.length; i++) { + assert.deepEqual( + pieceTable.getPositionAt(lineStarts[i]), + new Position(i + 1, 1) + ); + assert.equal(pieceTable.getOffsetAt(i + 1, 1), lineStarts[i]); + } + + for (let i = 1; i < lineStarts.length; i++) { + let pos = pieceTable.getPositionAt(lineStarts[i] - 1); + assert.equal( + pieceTable.getOffsetAt(pos.lineNumber, pos.column), + lineStarts[i] - 1 + ); + } +} + +function createTextBuffer(val: string[], normalizeEOL: boolean = true): PieceTreeBase { + let bufferBuilder = new PieceTreeTextBufferBuilder(); + for (let i = 0; i < val.length; i++) { + bufferBuilder.acceptChunk(val[i]); + } + let factory = bufferBuilder.finish(normalizeEOL); + return (factory.create(DefaultEndOfLine.LF)).getPieceTree(); +} + +function assertTreeInvariants(T: PieceTreeBase): void { + assert(SENTINEL.color === NodeColor.Black); + assert(SENTINEL.parent === SENTINEL); + assert(SENTINEL.left === SENTINEL); + assert(SENTINEL.right === SENTINEL); + assert(SENTINEL.size_left === 0); + assert(SENTINEL.lf_left === 0); + assertValidTree(T); +} + +function depth(n: TreeNode): number { + if (n === SENTINEL) { + // The leafs are black + return 1; + } + assert(depth(n.left) === depth(n.right)); + return (n.color === NodeColor.Black ? 1 : 0) + depth(n.left); +} + +function assertValidNode(n: TreeNode): { size: number, lf_cnt: number } { + if (n === SENTINEL) { + return { size: 0, lf_cnt: 0 }; + } + + let l = n.left; + let r = n.right; + + if (n.color === NodeColor.Red) { + assert(l.color === NodeColor.Black); + assert(r.color === NodeColor.Black); + } + + let actualLeft = assertValidNode(l); + assert(actualLeft.lf_cnt === n.lf_left); + assert(actualLeft.size === n.size_left); + let actualRight = assertValidNode(r); + + return { size: n.size_left + n.piece.length + actualRight.size, lf_cnt: n.lf_left + n.piece.lineFeedCnt + actualRight.lf_cnt }; +} + +function assertValidTree(T: PieceTreeBase): void { + if (T.root === SENTINEL) { + return; + } + assert(T.root.color === NodeColor.Black); + assert(depth(T.root.left) === depth(T.root.right)); + assertValidNode(T.root); +} + +//#endregion + +suite('inserts and deletes', () => { + test('basic insert/delete', () => { + let pieceTable = createTextBuffer([ + 'This is a document with some text.' + ]); + + pieceTable.insert(34, 'This is some more text to insert at offset 34.'); + assert.equal( + pieceTable.getLinesRawContent(), + 'This is a document with some text.This is some more text to insert at offset 34.' + ); + pieceTable.delete(42, 5); + assert.equal( + pieceTable.getLinesRawContent(), + 'This is a document with some text.This is more text to insert at offset 34.' + ); + assertTreeInvariants(pieceTable); + }); + + test('more inserts', () => { + let pt = createTextBuffer(['']); + + pt.insert(0, 'AAA'); + assert.equal(pt.getLinesRawContent(), 'AAA'); + pt.insert(0, 'BBB'); + assert.equal(pt.getLinesRawContent(), 'BBBAAA'); + pt.insert(6, 'CCC'); + assert.equal(pt.getLinesRawContent(), 'BBBAAACCC'); + pt.insert(5, 'DDD'); + assert.equal(pt.getLinesRawContent(), 'BBBAADDDACCC'); + assertTreeInvariants(pt); + }); + + test('more deletes', () => { + let pt = createTextBuffer(['012345678']); + pt.delete(8, 1); + assert.equal(pt.getLinesRawContent(), '01234567'); + pt.delete(0, 1); + assert.equal(pt.getLinesRawContent(), '1234567'); + pt.delete(5, 1); + assert.equal(pt.getLinesRawContent(), '123457'); + pt.delete(5, 1); + assert.equal(pt.getLinesRawContent(), '12345'); + pt.delete(0, 5); + assert.equal(pt.getLinesRawContent(), ''); + assertTreeInvariants(pt); + }); + + test('random test 1', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'ceLPHmFzvCtFeHkCBej '); + str = str.substring(0, 0) + 'ceLPHmFzvCtFeHkCBej ' + str.substring(0); + assert.equal(pieceTable.getLinesRawContent(), str); + pieceTable.insert(8, 'gDCEfNYiBUNkSwtvB K '); + str = str.substring(0, 8) + 'gDCEfNYiBUNkSwtvB K ' + str.substring(8); + assert.equal(pieceTable.getLinesRawContent(), str); + pieceTable.insert(38, 'cyNcHxjNPPoehBJldLS '); + str = str.substring(0, 38) + 'cyNcHxjNPPoehBJldLS ' + str.substring(38); + assert.equal(pieceTable.getLinesRawContent(), str); + pieceTable.insert(59, 'ejMx\nOTgWlbpeDExjOk '); + str = str.substring(0, 59) + 'ejMx\nOTgWlbpeDExjOk ' + str.substring(59); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random test 2', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'VgPG '); + str = str.substring(0, 0) + 'VgPG ' + str.substring(0); + pieceTable.insert(2, 'DdWF '); + str = str.substring(0, 2) + 'DdWF ' + str.substring(2); + pieceTable.insert(0, 'hUJc '); + str = str.substring(0, 0) + 'hUJc ' + str.substring(0); + pieceTable.insert(8, 'lQEq '); + str = str.substring(0, 8) + 'lQEq ' + str.substring(8); + pieceTable.insert(10, 'Gbtp '); + str = str.substring(0, 10) + 'Gbtp ' + str.substring(10); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random test 3', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'gYSz'); + str = str.substring(0, 0) + 'gYSz' + str.substring(0); + pieceTable.insert(1, 'mDQe'); + str = str.substring(0, 1) + 'mDQe' + str.substring(1); + pieceTable.insert(1, 'DTMQ'); + str = str.substring(0, 1) + 'DTMQ' + str.substring(1); + pieceTable.insert(2, 'GGZB'); + str = str.substring(0, 2) + 'GGZB' + str.substring(2); + pieceTable.insert(12, 'wXpq'); + str = str.substring(0, 12) + 'wXpq' + str.substring(12); + assert.equal(pieceTable.getLinesRawContent(), str); + }); + + test('random delete 1', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + + pieceTable.insert(0, 'vfb'); + str = str.substring(0, 0) + 'vfb' + str.substring(0); + assert.equal(pieceTable.getLinesRawContent(), str); + pieceTable.insert(0, 'zRq'); + str = str.substring(0, 0) + 'zRq' + str.substring(0); + assert.equal(pieceTable.getLinesRawContent(), str); + + pieceTable.delete(5, 1); + str = str.substring(0, 5) + str.substring(5 + 1); + assert.equal(pieceTable.getLinesRawContent(), str); + + pieceTable.insert(1, 'UNw'); + str = str.substring(0, 1) + 'UNw' + str.substring(1); + assert.equal(pieceTable.getLinesRawContent(), str); + + pieceTable.delete(4, 3); + str = str.substring(0, 4) + str.substring(4 + 3); + assert.equal(pieceTable.getLinesRawContent(), str); + + pieceTable.delete(1, 4); + str = str.substring(0, 1) + str.substring(1 + 4); + assert.equal(pieceTable.getLinesRawContent(), str); + + pieceTable.delete(0, 1); + str = str.substring(0, 0) + str.substring(0 + 1); + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random delete 2', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + + pieceTable.insert(0, 'IDT'); + str = str.substring(0, 0) + 'IDT' + str.substring(0); + pieceTable.insert(3, 'wwA'); + str = str.substring(0, 3) + 'wwA' + str.substring(3); + pieceTable.insert(3, 'Gnr'); + str = str.substring(0, 3) + 'Gnr' + str.substring(3); + pieceTable.delete(6, 3); + str = str.substring(0, 6) + str.substring(6 + 3); + pieceTable.insert(4, 'eHp'); + str = str.substring(0, 4) + 'eHp' + str.substring(4); + pieceTable.insert(1, 'UAi'); + str = str.substring(0, 1) + 'UAi' + str.substring(1); + pieceTable.insert(2, 'FrR'); + str = str.substring(0, 2) + 'FrR' + str.substring(2); + pieceTable.delete(6, 7); + str = str.substring(0, 6) + str.substring(6 + 7); + pieceTable.delete(3, 5); + str = str.substring(0, 3) + str.substring(3 + 5); + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random delete 3', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'PqM'); + str = str.substring(0, 0) + 'PqM' + str.substring(0); + pieceTable.delete(1, 2); + str = str.substring(0, 1) + str.substring(1 + 2); + pieceTable.insert(1, 'zLc'); + str = str.substring(0, 1) + 'zLc' + str.substring(1); + pieceTable.insert(0, 'MEX'); + str = str.substring(0, 0) + 'MEX' + str.substring(0); + pieceTable.insert(0, 'jZh'); + str = str.substring(0, 0) + 'jZh' + str.substring(0); + pieceTable.insert(8, 'GwQ'); + str = str.substring(0, 8) + 'GwQ' + str.substring(8); + pieceTable.delete(5, 6); + str = str.substring(0, 5) + str.substring(5 + 6); + pieceTable.insert(4, 'ktw'); + str = str.substring(0, 4) + 'ktw' + str.substring(4); + pieceTable.insert(5, 'GVu'); + str = str.substring(0, 5) + 'GVu' + str.substring(5); + pieceTable.insert(9, 'jdm'); + str = str.substring(0, 9) + 'jdm' + str.substring(9); + pieceTable.insert(15, 'na\n'); + str = str.substring(0, 15) + 'na\n' + str.substring(15); + pieceTable.delete(5, 8); + str = str.substring(0, 5) + str.substring(5 + 8); + pieceTable.delete(3, 4); + str = str.substring(0, 3) + str.substring(3 + 4); + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random insert/delete \\r bug 1', () => { + let str = 'a'; + let pieceTable = createTextBuffer(['a']); + pieceTable.delete(0, 1); + str = str.substring(0, 0) + str.substring(0 + 1); + pieceTable.insert(0, '\r\r\n\n'); + str = str.substring(0, 0) + '\r\r\n\n' + str.substring(0); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.insert(2, '\n\n\ra'); + str = str.substring(0, 2) + '\n\n\ra' + str.substring(2); + pieceTable.delete(4, 3); + str = str.substring(0, 4) + str.substring(4 + 3); + pieceTable.insert(2, '\na\r\r'); + str = str.substring(0, 2) + '\na\r\r' + str.substring(2); + pieceTable.insert(6, '\ra\n\n'); + str = str.substring(0, 6) + '\ra\n\n' + str.substring(6); + pieceTable.insert(0, 'aa\n\n'); + str = str.substring(0, 0) + 'aa\n\n' + str.substring(0); + pieceTable.insert(5, '\n\na\r'); + str = str.substring(0, 5) + '\n\na\r' + str.substring(5); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random insert/delete \\r bug 2', () => { + let str = 'a'; + let pieceTable = createTextBuffer(['a']); + pieceTable.insert(1, '\naa\r'); + str = str.substring(0, 1) + '\naa\r' + str.substring(1); + pieceTable.delete(0, 4); + str = str.substring(0, 0) + str.substring(0 + 4); + pieceTable.insert(1, '\r\r\na'); + str = str.substring(0, 1) + '\r\r\na' + str.substring(1); + pieceTable.insert(2, '\n\r\ra'); + str = str.substring(0, 2) + '\n\r\ra' + str.substring(2); + pieceTable.delete(4, 1); + str = str.substring(0, 4) + str.substring(4 + 1); + pieceTable.insert(8, '\r\n\r\r'); + str = str.substring(0, 8) + '\r\n\r\r' + str.substring(8); + pieceTable.insert(7, '\n\n\na'); + str = str.substring(0, 7) + '\n\n\na' + str.substring(7); + pieceTable.insert(13, 'a\n\na'); + str = str.substring(0, 13) + 'a\n\na' + str.substring(13); + pieceTable.delete(17, 3); + str = str.substring(0, 17) + str.substring(17 + 3); + pieceTable.insert(2, 'a\ra\n'); + str = str.substring(0, 2) + 'a\ra\n' + str.substring(2); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random insert/delete \\r bug 3', () => { + let str = 'a'; + let pieceTable = createTextBuffer(['a']); + pieceTable.insert(0, '\r\na\r'); + str = str.substring(0, 0) + '\r\na\r' + str.substring(0); + pieceTable.delete(2, 3); + str = str.substring(0, 2) + str.substring(2 + 3); + pieceTable.insert(2, 'a\r\n\r'); + str = str.substring(0, 2) + 'a\r\n\r' + str.substring(2); + pieceTable.delete(4, 2); + str = str.substring(0, 4) + str.substring(4 + 2); + pieceTable.insert(4, 'a\n\r\n'); + str = str.substring(0, 4) + 'a\n\r\n' + str.substring(4); + pieceTable.insert(1, 'aa\n\r'); + str = str.substring(0, 1) + 'aa\n\r' + str.substring(1); + pieceTable.insert(7, '\na\r\n'); + str = str.substring(0, 7) + '\na\r\n' + str.substring(7); + pieceTable.insert(5, '\n\na\r'); + str = str.substring(0, 5) + '\n\na\r' + str.substring(5); + pieceTable.insert(10, '\r\r\n\r'); + str = str.substring(0, 10) + '\r\r\n\r' + str.substring(10); + assert.equal(pieceTable.getLinesRawContent(), str); + pieceTable.delete(21, 3); + str = str.substring(0, 21) + str.substring(21 + 3); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + + test('random insert/delete \\r bug 4s', () => { + let str = 'a'; + let pieceTable = createTextBuffer(['a']); + pieceTable.delete(0, 1); + str = str.substring(0, 0) + str.substring(0 + 1); + pieceTable.insert(0, '\naaa'); + str = str.substring(0, 0) + '\naaa' + str.substring(0); + pieceTable.insert(2, '\n\naa'); + str = str.substring(0, 2) + '\n\naa' + str.substring(2); + pieceTable.delete(1, 4); + str = str.substring(0, 1) + str.substring(1 + 4); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.delete(1, 2); + str = str.substring(0, 1) + str.substring(1 + 2); + pieceTable.delete(0, 1); + str = str.substring(0, 0) + str.substring(0 + 1); + pieceTable.insert(0, 'a\n\n\r'); + str = str.substring(0, 0) + 'a\n\n\r' + str.substring(0); + pieceTable.insert(2, 'aa\r\n'); + str = str.substring(0, 2) + 'aa\r\n' + str.substring(2); + pieceTable.insert(3, 'a\naa'); + str = str.substring(0, 3) + 'a\naa' + str.substring(3); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); + test('random insert/delete \\r bug 5', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, '\n\n\n\r'); + str = str.substring(0, 0) + '\n\n\n\r' + str.substring(0); + pieceTable.insert(1, '\n\n\n\r'); + str = str.substring(0, 1) + '\n\n\n\r' + str.substring(1); + pieceTable.insert(2, '\n\r\r\r'); + str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2); + pieceTable.insert(8, '\n\r\n\r'); + str = str.substring(0, 8) + '\n\r\n\r' + str.substring(8); + pieceTable.delete(5, 2); + str = str.substring(0, 5) + str.substring(5 + 2); + pieceTable.insert(4, '\n\r\r\r'); + str = str.substring(0, 4) + '\n\r\r\r' + str.substring(4); + pieceTable.insert(8, '\n\n\n\r'); + str = str.substring(0, 8) + '\n\n\n\r' + str.substring(8); + pieceTable.delete(0, 7); + str = str.substring(0, 0) + str.substring(0 + 7); + pieceTable.insert(1, '\r\n\r\r'); + str = str.substring(0, 1) + '\r\n\r\r' + str.substring(1); + pieceTable.insert(15, '\n\r\r\r'); + str = str.substring(0, 15) + '\n\r\r\r' + str.substring(15); + + assert.equal(pieceTable.getLinesRawContent(), str); + assertTreeInvariants(pieceTable); + }); +}); + +suite('prefix sum for line feed', () => { + test('basic', () => { + let pieceTable = createTextBuffer(['1\n2\n3\n4']); + + assert.equal(pieceTable.getLineCount(), 4); + assert.deepEqual(pieceTable.getPositionAt(0), new Position(1, 1)); + assert.deepEqual(pieceTable.getPositionAt(1), new Position(1, 2)); + assert.deepEqual(pieceTable.getPositionAt(2), new Position(2, 1)); + assert.deepEqual(pieceTable.getPositionAt(3), new Position(2, 2)); + assert.deepEqual(pieceTable.getPositionAt(4), new Position(3, 1)); + assert.deepEqual(pieceTable.getPositionAt(5), new Position(3, 2)); + assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + + assert.equal(pieceTable.getOffsetAt(1, 1), 0); + assert.equal(pieceTable.getOffsetAt(1, 2), 1); + assert.equal(pieceTable.getOffsetAt(2, 1), 2); + assert.equal(pieceTable.getOffsetAt(2, 2), 3); + assert.equal(pieceTable.getOffsetAt(3, 1), 4); + assert.equal(pieceTable.getOffsetAt(3, 2), 5); + assert.equal(pieceTable.getOffsetAt(4, 1), 6); + assertTreeInvariants(pieceTable); + }); + + test('append', () => { + let pieceTable = createTextBuffer(['a\nb\nc\nde']); + pieceTable.insert(8, 'fh\ni\njk'); + + assert.equal(pieceTable.getLineCount(), 6); + assert.deepEqual(pieceTable.getPositionAt(9), new Position(4, 4)); + assert.equal(pieceTable.getOffsetAt(1, 1), 0); + assertTreeInvariants(pieceTable); + }); + + test('insert', () => { + let pieceTable = createTextBuffer(['a\nb\nc\nde']); + pieceTable.insert(7, 'fh\ni\njk'); + + assert.equal(pieceTable.getLineCount(), 6); + assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepEqual(pieceTable.getPositionAt(9), new Position(4, 4)); + assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 1)); + assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 2)); + assert.deepEqual(pieceTable.getPositionAt(14), new Position(6, 3)); + + assert.equal(pieceTable.getOffsetAt(4, 1), 6); + assert.equal(pieceTable.getOffsetAt(4, 2), 7); + assert.equal(pieceTable.getOffsetAt(4, 3), 8); + assert.equal(pieceTable.getOffsetAt(4, 4), 9); + assert.equal(pieceTable.getOffsetAt(6, 1), 12); + assert.equal(pieceTable.getOffsetAt(6, 2), 13); + assert.equal(pieceTable.getOffsetAt(6, 3), 14); + assertTreeInvariants(pieceTable); + }); + + test('delete', () => { + let pieceTable = createTextBuffer(['a\nb\nc\ndefh\ni\njk']); + pieceTable.delete(7, 2); + + assert.equal(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); + assert.equal(pieceTable.getLineCount(), 6); + assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepEqual(pieceTable.getPositionAt(9), new Position(5, 1)); + assert.deepEqual(pieceTable.getPositionAt(11), new Position(6, 1)); + assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 2)); + assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 3)); + + assert.equal(pieceTable.getOffsetAt(4, 1), 6); + assert.equal(pieceTable.getOffsetAt(4, 2), 7); + assert.equal(pieceTable.getOffsetAt(4, 3), 8); + assert.equal(pieceTable.getOffsetAt(5, 1), 9); + assert.equal(pieceTable.getOffsetAt(6, 1), 11); + assert.equal(pieceTable.getOffsetAt(6, 2), 12); + assert.equal(pieceTable.getOffsetAt(6, 3), 13); + assertTreeInvariants(pieceTable); + }); + + test('add+delete 1', () => { + let pieceTable = createTextBuffer(['a\nb\nc\nde']); + pieceTable.insert(8, 'fh\ni\njk'); + pieceTable.delete(7, 2); + + assert.equal(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk'); + assert.equal(pieceTable.getLineCount(), 6); + assert.deepEqual(pieceTable.getPositionAt(6), new Position(4, 1)); + assert.deepEqual(pieceTable.getPositionAt(7), new Position(4, 2)); + assert.deepEqual(pieceTable.getPositionAt(8), new Position(4, 3)); + assert.deepEqual(pieceTable.getPositionAt(9), new Position(5, 1)); + assert.deepEqual(pieceTable.getPositionAt(11), new Position(6, 1)); + assert.deepEqual(pieceTable.getPositionAt(12), new Position(6, 2)); + assert.deepEqual(pieceTable.getPositionAt(13), new Position(6, 3)); + + assert.equal(pieceTable.getOffsetAt(4, 1), 6); + assert.equal(pieceTable.getOffsetAt(4, 2), 7); + assert.equal(pieceTable.getOffsetAt(4, 3), 8); + assert.equal(pieceTable.getOffsetAt(5, 1), 9); + assert.equal(pieceTable.getOffsetAt(6, 1), 11); + assert.equal(pieceTable.getOffsetAt(6, 2), 12); + assert.equal(pieceTable.getOffsetAt(6, 3), 13); + assertTreeInvariants(pieceTable); + }); + + test('insert random bug 1: prefixSumComputer.removeValues(start, cnt) cnt is 1 based.', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, ' ZX \n Z\nZ\n YZ\nY\nZXX '); + str = + str.substring(0, 0) + + ' ZX \n Z\nZ\n YZ\nY\nZXX ' + + str.substring(0); + pieceTable.insert(14, 'X ZZ\nYZZYZXXY Y XY\n '); + str = + str.substring(0, 14) + 'X ZZ\nYZZYZXXY Y XY\n ' + str.substring(14); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('insert random bug 2: prefixSumComputer initialize does not do deep copy of UInt32Array.', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'ZYZ\nYY XY\nX \nZ Y \nZ '); + str = + str.substring(0, 0) + 'ZYZ\nYY XY\nX \nZ Y \nZ ' + str.substring(0); + pieceTable.insert(3, 'XXY \n\nY Y YYY ZYXY '); + str = str.substring(0, 3) + 'XXY \n\nY Y YYY ZYXY ' + str.substring(3); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('delete random bug 1: I forgot to update the lineFeedCnt when deletion is on one single piece.', () => { + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'ba\na\nca\nba\ncbab\ncaa '); + pieceTable.insert(13, 'cca\naabb\ncac\nccc\nab '); + pieceTable.delete(5, 8); + pieceTable.delete(30, 2); + pieceTable.insert(24, 'cbbacccbac\nbaaab\n\nc '); + pieceTable.delete(29, 3); + pieceTable.delete(23, 9); + pieceTable.delete(21, 5); + pieceTable.delete(30, 3); + pieceTable.insert(3, 'cb\nac\nc\n\nacc\nbb\nb\nc '); + pieceTable.delete(19, 5); + pieceTable.insert(18, '\nbb\n\nacbc\ncbb\nc\nbb\n '); + pieceTable.insert(65, 'cbccbac\nbc\n\nccabba\n '); + pieceTable.insert(77, 'a\ncacb\n\nac\n\n\n\n\nabab '); + pieceTable.delete(30, 9); + pieceTable.insert(45, 'b\n\nc\nba\n\nbbbba\n\naa\n '); + pieceTable.insert(82, 'ab\nbb\ncabacab\ncbc\na '); + pieceTable.delete(123, 9); + pieceTable.delete(71, 2); + pieceTable.insert(33, 'acaa\nacb\n\naa\n\nc\n\n\n\n '); + + let str = pieceTable.getLinesRawContent(); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('delete random bug rb tree 1', () => { + let str = ''; + let pieceTable = createTextBuffer([str]); + pieceTable.insert(0, 'YXXZ\n\nYY\n'); + str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0); + pieceTable.delete(0, 5); + str = str.substring(0, 0) + str.substring(0 + 5); + pieceTable.insert(0, 'ZXYY\nX\nZ\n'); + str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0); + pieceTable.insert(10, '\nXY\nYXYXY'); + str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('delete random bug rb tree 2', () => { + let str = ''; + let pieceTable = createTextBuffer([str]); + pieceTable.insert(0, 'YXXZ\n\nYY\n'); + str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0); + pieceTable.insert(0, 'ZXYY\nX\nZ\n'); + str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0); + pieceTable.insert(10, '\nXY\nYXYXY'); + str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10); + pieceTable.insert(8, 'YZXY\nZ\nYX'); + str = str.substring(0, 8) + 'YZXY\nZ\nYX' + str.substring(8); + pieceTable.insert(12, 'XX\nXXYXYZ'); + str = str.substring(0, 12) + 'XX\nXXYXYZ' + str.substring(12); + pieceTable.delete(0, 4); + str = str.substring(0, 0) + str.substring(0 + 4); + + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('delete random bug rb tree 3', () => { + let str = ''; + let pieceTable = createTextBuffer([str]); + pieceTable.insert(0, 'YXXZ\n\nYY\n'); + str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0); + pieceTable.delete(7, 2); + str = str.substring(0, 7) + str.substring(7 + 2); + pieceTable.delete(6, 1); + str = str.substring(0, 6) + str.substring(6 + 1); + pieceTable.delete(0, 5); + str = str.substring(0, 0) + str.substring(0 + 5); + pieceTable.insert(0, 'ZXYY\nX\nZ\n'); + str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0); + pieceTable.insert(10, '\nXY\nYXYXY'); + str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10); + pieceTable.insert(8, 'YZXY\nZ\nYX'); + str = str.substring(0, 8) + 'YZXY\nZ\nYX' + str.substring(8); + pieceTable.insert(12, 'XX\nXXYXYZ'); + str = str.substring(0, 12) + 'XX\nXXYXYZ' + str.substring(12); + pieceTable.delete(0, 4); + str = str.substring(0, 0) + str.substring(0 + 4); + pieceTable.delete(30, 3); + str = str.substring(0, 30) + str.substring(30 + 3); + + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('offset 2 position', () => { + test('random tests bug 1', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'huuyYzUfKOENwGgZLqn '); + str = str.substring(0, 0) + 'huuyYzUfKOENwGgZLqn ' + str.substring(0); + pieceTable.delete(18, 2); + str = str.substring(0, 18) + str.substring(18 + 2); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.delete(12, 4); + str = str.substring(0, 12) + str.substring(12 + 4); + pieceTable.insert(3, 'hMbnVEdTSdhLlPevXKF '); + str = str.substring(0, 3) + 'hMbnVEdTSdhLlPevXKF ' + str.substring(3); + pieceTable.delete(22, 8); + str = str.substring(0, 22) + str.substring(22 + 8); + pieceTable.insert(4, 'S umSnYrqOmOAV\nEbZJ '); + str = str.substring(0, 4) + 'S umSnYrqOmOAV\nEbZJ ' + str.substring(4); + + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('get text in range', () => { + test('getContentInRange', () => { + let pieceTable = createTextBuffer(['a\nb\nc\nde']); + pieceTable.insert(8, 'fh\ni\njk'); + pieceTable.delete(7, 2); + // 'a\nb\nc\ndh\ni\njk' + + assert.equal(pieceTable.getValueInRange(new Range(1, 1, 1, 3)), 'a\n'); + assert.equal(pieceTable.getValueInRange(new Range(2, 1, 2, 3)), 'b\n'); + assert.equal(pieceTable.getValueInRange(new Range(3, 1, 3, 3)), 'c\n'); + assert.equal(pieceTable.getValueInRange(new Range(4, 1, 4, 4)), 'dh\n'); + assert.equal(pieceTable.getValueInRange(new Range(5, 1, 5, 3)), 'i\n'); + assert.equal(pieceTable.getValueInRange(new Range(6, 1, 6, 3)), 'jk'); + assertTreeInvariants(pieceTable); + }); + + test('random test value in range', () => { + let str = ''; + let pieceTable = createTextBuffer([str]); + + pieceTable.insert(0, 'ZXXY'); + str = str.substring(0, 0) + 'ZXXY' + str.substring(0); + pieceTable.insert(1, 'XZZY'); + str = str.substring(0, 1) + 'XZZY' + str.substring(1); + pieceTable.insert(5, '\nX\n\n'); + str = str.substring(0, 5) + '\nX\n\n' + str.substring(5); + pieceTable.insert(3, '\nXX\n'); + str = str.substring(0, 3) + '\nXX\n' + str.substring(3); + pieceTable.insert(12, 'YYYX'); + str = str.substring(0, 12) + 'YYYX' + str.substring(12); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random test value in range exception', () => { + let str = ''; + let pieceTable = createTextBuffer([str]); + + pieceTable.insert(0, 'XZ\nZ'); + str = str.substring(0, 0) + 'XZ\nZ' + str.substring(0); + pieceTable.delete(0, 3); + str = str.substring(0, 0) + str.substring(0 + 3); + pieceTable.delete(0, 1); + str = str.substring(0, 0) + str.substring(0 + 1); + pieceTable.insert(0, 'ZYX\n'); + str = str.substring(0, 0) + 'ZYX\n' + str.substring(0); + pieceTable.delete(0, 4); + str = str.substring(0, 0) + str.substring(0 + 4); + + pieceTable.getValueInRange(new Range(1, 1, 1, 1)); + assertTreeInvariants(pieceTable); + }); + + test('random tests bug 1', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'huuyYzUfKOENwGgZLqn '); + str = str.substring(0, 0) + 'huuyYzUfKOENwGgZLqn ' + str.substring(0); + pieceTable.delete(18, 2); + str = str.substring(0, 18) + str.substring(18 + 2); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.delete(12, 4); + str = str.substring(0, 12) + str.substring(12 + 4); + pieceTable.insert(3, 'hMbnVEdTSdhLlPevXKF '); + str = str.substring(0, 3) + 'hMbnVEdTSdhLlPevXKF ' + str.substring(3); + pieceTable.delete(22, 8); + str = str.substring(0, 22) + str.substring(22 + 8); + pieceTable.insert(4, 'S umSnYrqOmOAV\nEbZJ '); + str = str.substring(0, 4) + 'S umSnYrqOmOAV\nEbZJ ' + str.substring(4); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random tests bug 2', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'xfouRDZwdAHjVXJAMV\n '); + str = str.substring(0, 0) + 'xfouRDZwdAHjVXJAMV\n ' + str.substring(0); + pieceTable.insert(16, 'dBGndxpFZBEAIKykYYx '); + str = str.substring(0, 16) + 'dBGndxpFZBEAIKykYYx ' + str.substring(16); + pieceTable.delete(7, 6); + str = str.substring(0, 7) + str.substring(7 + 6); + pieceTable.delete(9, 7); + str = str.substring(0, 9) + str.substring(9 + 7); + pieceTable.delete(17, 6); + str = str.substring(0, 17) + str.substring(17 + 6); + pieceTable.delete(0, 4); + str = str.substring(0, 0) + str.substring(0 + 4); + pieceTable.insert(9, 'qvEFXCNvVkWgvykahYt '); + str = str.substring(0, 9) + 'qvEFXCNvVkWgvykahYt ' + str.substring(9); + pieceTable.delete(4, 6); + str = str.substring(0, 4) + str.substring(4 + 6); + pieceTable.insert(11, 'OcSChUYT\nzPEBOpsGmR '); + str = + str.substring(0, 11) + 'OcSChUYT\nzPEBOpsGmR ' + str.substring(11); + pieceTable.insert(15, 'KJCozaXTvkE\nxnqAeTz '); + str = + str.substring(0, 15) + 'KJCozaXTvkE\nxnqAeTz ' + str.substring(15); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('get line content', () => { + let pieceTable = createTextBuffer(['1']); + assert.equal(pieceTable.getLineRawContent(1), '1'); + pieceTable.insert(1, '2'); + assert.equal(pieceTable.getLineRawContent(1), '12'); + assertTreeInvariants(pieceTable); + }); + + test('get line content basic', () => { + let pieceTable = createTextBuffer(['1\n2\n3\n4']); + assert.equal(pieceTable.getLineRawContent(1), '1\n'); + assert.equal(pieceTable.getLineRawContent(2), '2\n'); + assert.equal(pieceTable.getLineRawContent(3), '3\n'); + assert.equal(pieceTable.getLineRawContent(4), '4'); + assertTreeInvariants(pieceTable); + }); + + test('get line content after inserts/deletes', () => { + let pieceTable = createTextBuffer(['a\nb\nc\nde']); + pieceTable.insert(8, 'fh\ni\njk'); + pieceTable.delete(7, 2); + // 'a\nb\nc\ndh\ni\njk' + + assert.equal(pieceTable.getLineRawContent(1), 'a\n'); + assert.equal(pieceTable.getLineRawContent(2), 'b\n'); + assert.equal(pieceTable.getLineRawContent(3), 'c\n'); + assert.equal(pieceTable.getLineRawContent(4), 'dh\n'); + assert.equal(pieceTable.getLineRawContent(5), 'i\n'); + assert.equal(pieceTable.getLineRawContent(6), 'jk'); + assertTreeInvariants(pieceTable); + }); + + test('random 1', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + + pieceTable.insert(0, 'J eNnDzQpnlWyjmUu\ny '); + str = str.substring(0, 0) + 'J eNnDzQpnlWyjmUu\ny ' + str.substring(0); + pieceTable.insert(0, 'QPEeRAQmRwlJqtZSWhQ '); + str = str.substring(0, 0) + 'QPEeRAQmRwlJqtZSWhQ ' + str.substring(0); + pieceTable.delete(5, 1); + str = str.substring(0, 5) + str.substring(5 + 1); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random 2', () => { + let str = ''; + let pieceTable = createTextBuffer(['']); + pieceTable.insert(0, 'DZoQ tglPCRHMltejRI '); + str = str.substring(0, 0) + 'DZoQ tglPCRHMltejRI ' + str.substring(0); + pieceTable.insert(10, 'JRXiyYqJ qqdcmbfkKX '); + str = str.substring(0, 10) + 'JRXiyYqJ qqdcmbfkKX ' + str.substring(10); + pieceTable.delete(16, 3); + str = str.substring(0, 16) + str.substring(16 + 3); + pieceTable.delete(25, 1); + str = str.substring(0, 25) + str.substring(25 + 1); + pieceTable.insert(18, 'vH\nNlvfqQJPm\nSFkhMc '); + str = + str.substring(0, 18) + 'vH\nNlvfqQJPm\nSFkhMc ' + str.substring(18); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('CRLF', () => { + test('delete CR in CRLF 1', () => { + let pieceTable = createTextBuffer([''], false); + pieceTable.insert(0, 'a\r\nb'); + pieceTable.delete(0, 2); + + assert.equal(pieceTable.getLineCount(), 2); + assertTreeInvariants(pieceTable); + }); + + test('delete CR in CRLF 2', () => { + let pieceTable = createTextBuffer([''], false); + pieceTable.insert(0, 'a\r\nb'); + pieceTable.delete(2, 2); + + assert.equal(pieceTable.getLineCount(), 2); + assertTreeInvariants(pieceTable); + }); + + test('random bug 1', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + pieceTable.insert(0, '\n\n\r\r'); + str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0); + pieceTable.insert(1, '\r\n\r\n'); + str = str.substring(0, 1) + '\r\n\r\n' + str.substring(1); + pieceTable.delete(5, 3); + str = str.substring(0, 5) + str.substring(5 + 3); + pieceTable.delete(2, 3); + str = str.substring(0, 2) + str.substring(2 + 3); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + test('random bug 2', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\r\n\r'); + str = str.substring(0, 0) + '\n\r\n\r' + str.substring(0); + pieceTable.insert(2, '\n\r\r\r'); + str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2); + pieceTable.delete(4, 1); + str = str.substring(0, 4) + str.substring(4 + 1); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + test('random bug 3', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\n\n\r'); + str = str.substring(0, 0) + '\n\n\n\r' + str.substring(0); + pieceTable.delete(2, 2); + str = str.substring(0, 2) + str.substring(2 + 2); + pieceTable.delete(0, 2); + str = str.substring(0, 0) + str.substring(0 + 2); + pieceTable.insert(0, '\r\r\r\r'); + str = str.substring(0, 0) + '\r\r\r\r' + str.substring(0); + pieceTable.insert(2, '\r\n\r\r'); + str = str.substring(0, 2) + '\r\n\r\r' + str.substring(2); + pieceTable.insert(3, '\r\r\r\n'); + str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + test('random bug 4', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\n\n\n'); + str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.insert(1, '\r\r\r\r'); + str = str.substring(0, 1) + '\r\r\r\r' + str.substring(1); + pieceTable.insert(6, '\r\n\n\r'); + str = str.substring(0, 6) + '\r\n\n\r' + str.substring(6); + pieceTable.delete(5, 3); + str = str.substring(0, 5) + str.substring(5 + 3); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random bug 5', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\n\n\n'); + str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0); + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.insert(0, '\n\r\r\n'); + str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0); + pieceTable.insert(4, '\n\r\r\n'); + str = str.substring(0, 4) + '\n\r\r\n' + str.substring(4); + pieceTable.delete(4, 3); + str = str.substring(0, 4) + str.substring(4 + 3); + pieceTable.insert(5, '\r\r\n\r'); + str = str.substring(0, 5) + '\r\r\n\r' + str.substring(5); + pieceTable.insert(12, '\n\n\n\r'); + str = str.substring(0, 12) + '\n\n\n\r' + str.substring(12); + pieceTable.insert(5, '\r\r\r\n'); + str = str.substring(0, 5) + '\r\r\r\n' + str.substring(5); + pieceTable.insert(20, '\n\n\r\n'); + str = str.substring(0, 20) + '\n\n\r\n' + str.substring(20); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random bug 6', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\r\r\n'); + str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0); + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(3, '\r\n\n\n'); + str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3); + pieceTable.delete(4, 8); + str = str.substring(0, 4) + str.substring(4 + 8); + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(0, '\r\n\n\r'); + str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0); + pieceTable.delete(4, 0); + str = str.substring(0, 4) + str.substring(4 + 0); + pieceTable.delete(8, 4); + str = str.substring(0, 8) + str.substring(8 + 4); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random bug 8', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\r\n\n\r'); + str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0); + pieceTable.delete(1, 0); + str = str.substring(0, 1) + str.substring(1 + 0); + pieceTable.insert(3, '\n\n\n\r'); + str = str.substring(0, 3) + '\n\n\n\r' + str.substring(3); + pieceTable.insert(7, '\n\n\r\n'); + str = str.substring(0, 7) + '\n\n\r\n' + str.substring(7); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + test('random bug 7', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\r\r\n\n'); + str = str.substring(0, 0) + '\r\r\n\n' + str.substring(0); + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(7, '\n\r\r\r'); + str = str.substring(0, 7) + '\n\r\r\r' + str.substring(7); + pieceTable.insert(11, '\n\n\r\n'); + str = str.substring(0, 11) + '\n\n\r\n' + str.substring(11); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 10', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, 'qneW'); + str = str.substring(0, 0) + 'qneW' + str.substring(0); + pieceTable.insert(0, 'YhIl'); + str = str.substring(0, 0) + 'YhIl' + str.substring(0); + pieceTable.insert(0, 'qdsm'); + str = str.substring(0, 0) + 'qdsm' + str.substring(0); + pieceTable.delete(7, 0); + str = str.substring(0, 7) + str.substring(7 + 0); + pieceTable.insert(12, 'iiPv'); + str = str.substring(0, 12) + 'iiPv' + str.substring(12); + pieceTable.insert(9, 'V\rSA'); + str = str.substring(0, 9) + 'V\rSA' + str.substring(9); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 9', () => { + let str = ''; + let pieceTable = createTextBuffer([''], false); + + pieceTable.insert(0, '\n\n\n\n'); + str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0); + pieceTable.insert(3, '\n\r\n\r'); + str = str.substring(0, 3) + '\n\r\n\r' + str.substring(3); + pieceTable.insert(2, '\n\r\n\n'); + str = str.substring(0, 2) + '\n\r\n\n' + str.substring(2); + pieceTable.insert(0, '\n\n\r\r'); + str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0); + pieceTable.insert(3, '\r\r\r\r'); + str = str.substring(0, 3) + '\r\r\r\r' + str.substring(3); + pieceTable.insert(3, '\n\n\r\r'); + str = str.substring(0, 3) + '\n\n\r\r' + str.substring(3); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('centralized lineStarts with CRLF', () => { + test('delete CR in CRLF 1', () => { + let pieceTable = createTextBuffer(['a\r\nb'], false); + pieceTable.delete(2, 2); + assert.equal(pieceTable.getLineCount(), 2); + assertTreeInvariants(pieceTable); + }); + test('delete CR in CRLF 2', () => { + let pieceTable = createTextBuffer(['a\r\nb']); + pieceTable.delete(0, 2); + + assert.equal(pieceTable.getLineCount(), 2); + assertTreeInvariants(pieceTable); + }); + + test('random bug 1', () => { + let str = '\n\n\r\r'; + let pieceTable = createTextBuffer(['\n\n\r\r'], false); + pieceTable.insert(1, '\r\n\r\n'); + str = str.substring(0, 1) + '\r\n\r\n' + str.substring(1); + pieceTable.delete(5, 3); + str = str.substring(0, 5) + str.substring(5 + 3); + pieceTable.delete(2, 3); + str = str.substring(0, 2) + str.substring(2 + 3); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + test('random bug 2', () => { + let str = '\n\r\n\r'; + let pieceTable = createTextBuffer(['\n\r\n\r'], false); + + pieceTable.insert(2, '\n\r\r\r'); + str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2); + pieceTable.delete(4, 1); + str = str.substring(0, 4) + str.substring(4 + 1); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + + test('random bug 3', () => { + let str = '\n\n\n\r'; + let pieceTable = createTextBuffer(['\n\n\n\r'], false); + + pieceTable.delete(2, 2); + str = str.substring(0, 2) + str.substring(2 + 2); + pieceTable.delete(0, 2); + str = str.substring(0, 0) + str.substring(0 + 2); + pieceTable.insert(0, '\r\r\r\r'); + str = str.substring(0, 0) + '\r\r\r\r' + str.substring(0); + pieceTable.insert(2, '\r\n\r\r'); + str = str.substring(0, 2) + '\r\n\r\r' + str.substring(2); + pieceTable.insert(3, '\r\r\r\n'); + str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3); + + let lines = str.split(/\r\n|\r|\n/); + assert.equal(pieceTable.getLineCount(), lines.length); + assertTreeInvariants(pieceTable); + }); + + test('random bug 4', () => { + let str = '\n\n\n\n'; + let pieceTable = createTextBuffer(['\n\n\n\n'], false); + + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.insert(1, '\r\r\r\r'); + str = str.substring(0, 1) + '\r\r\r\r' + str.substring(1); + pieceTable.insert(6, '\r\n\n\r'); + str = str.substring(0, 6) + '\r\n\n\r' + str.substring(6); + pieceTable.delete(5, 3); + str = str.substring(0, 5) + str.substring(5 + 3); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 5', () => { + let str = '\n\n\n\n'; + let pieceTable = createTextBuffer(['\n\n\n\n'], false); + + pieceTable.delete(3, 1); + str = str.substring(0, 3) + str.substring(3 + 1); + pieceTable.insert(0, '\n\r\r\n'); + str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0); + pieceTable.insert(4, '\n\r\r\n'); + str = str.substring(0, 4) + '\n\r\r\n' + str.substring(4); + pieceTable.delete(4, 3); + str = str.substring(0, 4) + str.substring(4 + 3); + pieceTable.insert(5, '\r\r\n\r'); + str = str.substring(0, 5) + '\r\r\n\r' + str.substring(5); + pieceTable.insert(12, '\n\n\n\r'); + str = str.substring(0, 12) + '\n\n\n\r' + str.substring(12); + pieceTable.insert(5, '\r\r\r\n'); + str = str.substring(0, 5) + '\r\r\r\n' + str.substring(5); + pieceTable.insert(20, '\n\n\r\n'); + str = str.substring(0, 20) + '\n\n\r\n' + str.substring(20); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 6', () => { + let str = '\n\r\r\n'; + let pieceTable = createTextBuffer(['\n\r\r\n'], false); + + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(3, '\r\n\n\n'); + str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3); + pieceTable.delete(4, 8); + str = str.substring(0, 4) + str.substring(4 + 8); + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(0, '\r\n\n\r'); + str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0); + pieceTable.delete(4, 0); + str = str.substring(0, 4) + str.substring(4 + 0); + pieceTable.delete(8, 4); + str = str.substring(0, 8) + str.substring(8 + 4); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 7', () => { + let str = '\r\n\n\r'; + let pieceTable = createTextBuffer(['\r\n\n\r'], false); + + pieceTable.delete(1, 0); + str = str.substring(0, 1) + str.substring(1 + 0); + pieceTable.insert(3, '\n\n\n\r'); + str = str.substring(0, 3) + '\n\n\n\r' + str.substring(3); + pieceTable.insert(7, '\n\n\r\n'); + str = str.substring(0, 7) + '\n\n\r\n' + str.substring(7); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 8', () => { + let str = '\r\r\n\n'; + let pieceTable = createTextBuffer(['\r\r\n\n'], false); + + pieceTable.insert(4, '\r\n\n\r'); + str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4); + pieceTable.insert(7, '\n\r\r\r'); + str = str.substring(0, 7) + '\n\r\r\r' + str.substring(7); + pieceTable.insert(11, '\n\n\r\n'); + str = str.substring(0, 11) + '\n\n\r\n' + str.substring(11); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 9', () => { + let str = 'qneW'; + let pieceTable = createTextBuffer(['qneW'], false); + + pieceTable.insert(0, 'YhIl'); + str = str.substring(0, 0) + 'YhIl' + str.substring(0); + pieceTable.insert(0, 'qdsm'); + str = str.substring(0, 0) + 'qdsm' + str.substring(0); + pieceTable.delete(7, 0); + str = str.substring(0, 7) + str.substring(7 + 0); + pieceTable.insert(12, 'iiPv'); + str = str.substring(0, 12) + 'iiPv' + str.substring(12); + pieceTable.insert(9, 'V\rSA'); + str = str.substring(0, 9) + 'V\rSA' + str.substring(9); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random bug 10', () => { + let str = '\n\n\n\n'; + let pieceTable = createTextBuffer(['\n\n\n\n'], false); + + pieceTable.insert(3, '\n\r\n\r'); + str = str.substring(0, 3) + '\n\r\n\r' + str.substring(3); + pieceTable.insert(2, '\n\r\n\n'); + str = str.substring(0, 2) + '\n\r\n\n' + str.substring(2); + pieceTable.insert(0, '\n\n\r\r'); + str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0); + pieceTable.insert(3, '\r\r\r\r'); + str = str.substring(0, 3) + '\r\r\r\r' + str.substring(3); + pieceTable.insert(3, '\n\n\r\r'); + str = str.substring(0, 3) + '\n\n\r\r' + str.substring(3); + + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random chunk bug 1', () => { + let pieceTable = createTextBuffer(['\n\r\r\n\n\n\r\n\r'], false); + let str = '\n\r\r\n\n\n\r\n\r'; + pieceTable.delete(0, 2); + str = str.substring(0, 0) + str.substring(0 + 2); + pieceTable.insert(1, '\r\r\n\n'); + str = str.substring(0, 1) + '\r\r\n\n' + str.substring(1); + pieceTable.insert(7, '\r\r\r\r'); + str = str.substring(0, 7) + '\r\r\r\r' + str.substring(7); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random chunk bug 2', () => { + let pieceTable = createTextBuffer([ + '\n\r\n\n\n\r\n\r\n\r\r\n\n\n\r\r\n\r\n' + ], false); + let str = '\n\r\n\n\n\r\n\r\n\r\r\n\n\n\r\r\n\r\n'; + pieceTable.insert(16, '\r\n\r\r'); + str = str.substring(0, 16) + '\r\n\r\r' + str.substring(16); + pieceTable.insert(13, '\n\n\r\r'); + str = str.substring(0, 13) + '\n\n\r\r' + str.substring(13); + pieceTable.insert(19, '\n\n\r\n'); + str = str.substring(0, 19) + '\n\n\r\n' + str.substring(19); + pieceTable.delete(5, 0); + str = str.substring(0, 5) + str.substring(5 + 0); + pieceTable.delete(11, 2); + str = str.substring(0, 11) + str.substring(11 + 2); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random chunk bug 3', () => { + let pieceTable = createTextBuffer(['\r\n\n\n\n\n\n\r\n'], false); + let str = '\r\n\n\n\n\n\n\r\n'; + pieceTable.insert(4, '\n\n\r\n\r\r\n\n\r'); + str = str.substring(0, 4) + '\n\n\r\n\r\r\n\n\r' + str.substring(4); + pieceTable.delete(4, 4); + str = str.substring(0, 4) + str.substring(4 + 4); + pieceTable.insert(11, '\r\n\r\n\n\r\r\n\n'); + str = str.substring(0, 11) + '\r\n\r\n\n\r\r\n\n' + str.substring(11); + pieceTable.delete(1, 2); + str = str.substring(0, 1) + str.substring(1 + 2); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random chunk bug 4', () => { + let pieceTable = createTextBuffer(['\n\r\n\r'], false); + let str = '\n\r\n\r'; + pieceTable.insert(4, '\n\n\r\n'); + str = str.substring(0, 4) + '\n\n\r\n' + str.substring(4); + pieceTable.insert(3, '\r\n\n\n'); + str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3); + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('random is unsupervised', () => { + test('random insert delete', () => { + let str = ''; + let pieceTable = createTextBuffer([str], false); + + for (let i = 0; i < 1000; i++) { + if (Math.random() < 0.6) { + // insert + let text = randomStr(100); + let pos = randomInt(str.length + 1); + pieceTable.insert(pos, text); + str = str.substring(0, pos) + text + str.substring(pos); + } else { + // delete + let pos = randomInt(str.length); + let length = Math.min( + str.length - pos, + Math.floor(Math.random() * 10) + ); + pieceTable.delete(pos, length); + str = str.substring(0, pos) + str.substring(pos + length); + } + } + + assert.equal(pieceTable.getLinesRawContent(), str); + + testLineStarts(str, pieceTable); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); + + test('random chunks', () => { + let chunks = []; + for (let i = 0; i < 5; i++) { + chunks.push(randomStr(1000)); + } + + let pieceTable = createTextBuffer(chunks, false); + let str = chunks.join(''); + + for (let i = 0; i < 1000; i++) { + if (Math.random() < 0.6) { + // insert + let text = randomStr(100); + let pos = randomInt(str.length + 1); + pieceTable.insert(pos, text); + str = str.substring(0, pos) + text + str.substring(pos); + } else { + // delete + let pos = randomInt(str.length); + let length = Math.min( + str.length - pos, + Math.floor(Math.random() * 10) + ); + pieceTable.delete(pos, length); + str = str.substring(0, pos) + str.substring(pos + length); + } + } + + assert.equal(pieceTable.getLinesRawContent(), str); + testLineStarts(str, pieceTable); + testLinesContent(str, pieceTable); + assertTreeInvariants(pieceTable); + }); +}); + +suite('buffer api', () => { + test('equal', () => { + let a = createTextBuffer(['abc']); + let b = createTextBuffer(['ab', 'c']); + let c = createTextBuffer(['abd']); + let d = createTextBuffer(['abcd']); + + assert(a.equal(b)); + assert(!a.equal(c)); + assert(!a.equal(d)); + }); + + test('equal 2, empty buffer', () => { + let a = createTextBuffer(['']); + let b = createTextBuffer(['']); + + assert(a.equal(b)); + }); + + test('equal 3, empty buffer', () => { + let a = createTextBuffer(['a']); + let b = createTextBuffer(['']); + + assert(!a.equal(b)); + }); +}); + +suite('search offset cache', () => { + test('render white space exception', () => { + let pieceTable = createTextBuffer(['class Name{\n\t\n\t\t\tget() {\n\n\t\t\t}\n\t\t}']); + let str = 'class Name{\n\t\n\t\t\tget() {\n\n\t\t\t}\n\t\t}'; + + pieceTable.insert(12, 's'); + str = str.substring(0, 12) + 's' + str.substring(12); + + pieceTable.insert(13, 'e'); + str = str.substring(0, 13) + 'e' + str.substring(13); + + pieceTable.insert(14, 't'); + str = str.substring(0, 14) + 't' + str.substring(14); + + pieceTable.insert(15, '()'); + str = str.substring(0, 15) + '()' + str.substring(15); + + pieceTable.delete(16, 1); + str = str.substring(0, 16) + str.substring(16 + 1); + + pieceTable.insert(17, '()'); + str = str.substring(0, 17) + '()' + str.substring(17); + + pieceTable.delete(18, 1); + str = str.substring(0, 18) + str.substring(18 + 1); + + pieceTable.insert(18, '}'); + str = str.substring(0, 18) + '}' + str.substring(18); + + pieceTable.insert(12, '\n'); + str = str.substring(0, 12) + '\n' + str.substring(12); + + pieceTable.delete(12, 1); + str = str.substring(0, 12) + str.substring(12 + 1); + + pieceTable.delete(18, 1); + str = str.substring(0, 18) + str.substring(18 + 1); + + pieceTable.insert(18, '}'); + str = str.substring(0, 18) + '}' + str.substring(18); + + pieceTable.delete(17, 2); + str = str.substring(0, 17) + str.substring(17 + 2); + + pieceTable.delete(16, 1); + str = str.substring(0, 16) + str.substring(16 + 1); + + pieceTable.insert(16, ')'); + str = str.substring(0, 16) + ')' + str.substring(16); + + pieceTable.delete(15, 2); + str = str.substring(0, 15) + str.substring(15 + 2); + + var content = pieceTable.getLinesRawContent(); + assert(content === str); + }); +}); \ No newline at end of file diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 323ca9886b3..a99bde0f438 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -9,6 +9,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; import { DefaultEndOfLine } from 'vs/editor/common/model'; +import { UTF8_BOM_CHARACTER } from 'vs/base/common/strings'; function testGuessIndentation(defaultInsertSpaces: boolean, defaultTabSize: number, expectedInsertSpaces: boolean, expectedTabSize: number, text: string[], msg?: string): void { var m = TextModel.createFromString( @@ -763,6 +764,66 @@ suite('Editor Model - TextModel', () => { model.dispose(); }); + + test('getLineFirstNonWhitespaceColumn', () => { + let model = TextModel.createFromString([ + 'asd', + ' asd', + '\tasd', + ' asd', + '\t\tasd', + ' ', + ' ', + '\t', + '\t\t', + ' \tasd', + '', + '' + ].join('\n')); + + assert.equal(model.getLineFirstNonWhitespaceColumn(1), 1, '1'); + assert.equal(model.getLineFirstNonWhitespaceColumn(2), 2, '2'); + assert.equal(model.getLineFirstNonWhitespaceColumn(3), 2, '3'); + assert.equal(model.getLineFirstNonWhitespaceColumn(4), 3, '4'); + assert.equal(model.getLineFirstNonWhitespaceColumn(5), 3, '5'); + assert.equal(model.getLineFirstNonWhitespaceColumn(6), 0, '6'); + assert.equal(model.getLineFirstNonWhitespaceColumn(7), 0, '7'); + assert.equal(model.getLineFirstNonWhitespaceColumn(8), 0, '8'); + assert.equal(model.getLineFirstNonWhitespaceColumn(9), 0, '9'); + assert.equal(model.getLineFirstNonWhitespaceColumn(10), 4, '10'); + assert.equal(model.getLineFirstNonWhitespaceColumn(11), 0, '11'); + assert.equal(model.getLineFirstNonWhitespaceColumn(12), 0, '12'); + }); + + test('getLineLastNonWhitespaceColumn', () => { + let model = TextModel.createFromString([ + 'asd', + 'asd ', + 'asd\t', + 'asd ', + 'asd\t\t', + ' ', + ' ', + '\t', + '\t\t', + 'asd \t', + '', + '' + ].join('\n')); + + assert.equal(model.getLineLastNonWhitespaceColumn(1), 4, '1'); + assert.equal(model.getLineLastNonWhitespaceColumn(2), 4, '2'); + assert.equal(model.getLineLastNonWhitespaceColumn(3), 4, '3'); + assert.equal(model.getLineLastNonWhitespaceColumn(4), 4, '4'); + assert.equal(model.getLineLastNonWhitespaceColumn(5), 4, '5'); + assert.equal(model.getLineLastNonWhitespaceColumn(6), 0, '6'); + assert.equal(model.getLineLastNonWhitespaceColumn(7), 0, '7'); + assert.equal(model.getLineLastNonWhitespaceColumn(8), 0, '8'); + assert.equal(model.getLineLastNonWhitespaceColumn(9), 0, '9'); + assert.equal(model.getLineLastNonWhitespaceColumn(10), 4, '10'); + assert.equal(model.getLineLastNonWhitespaceColumn(11), 0, '11'); + assert.equal(model.getLineLastNonWhitespaceColumn(12), 0, '12'); + }); }); suite('TextModel.mightContainRTL', () => { @@ -792,3 +853,60 @@ suite('TextModel.mightContainRTL', () => { }); }); + +suite('TextModel.createSnapshot', () => { + + test('empty file', () => { + let model = TextModel.createFromString(''); + let snapshot = model.createSnapshot(); + assert.equal(snapshot.read(), null); + model.dispose(); + }); + + test('file with BOM', () => { + let model = TextModel.createFromString(UTF8_BOM_CHARACTER + 'Hello'); + assert.equal(model.getLineContent(1), 'Hello'); + let snapshot = model.createSnapshot(true); + assert.equal(snapshot.read(), UTF8_BOM_CHARACTER + 'Hello'); + assert.equal(snapshot.read(), null); + model.dispose(); + }); + + test('regular file', () => { + let model = TextModel.createFromString('My First Line\n\t\tMy Second Line\n Third Line\n\n1'); + let snapshot = model.createSnapshot(); + assert.equal(snapshot.read(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1'); + assert.equal(snapshot.read(), null); + model.dispose(); + }); + + test('large file', () => { + let lines: string[] = []; + for (let i = 0; i < 1000; i++) { + lines[i] = 'Just some text that is a bit long such that it can consume some memory'; + } + const text = lines.join('\n'); + + let model = TextModel.createFromString(text); + let snapshot = model.createSnapshot(); + let actual = ''; + + // 70999 length => at most 2 read calls are necessary + let tmp1 = snapshot.read(); + assert.ok(tmp1); + actual += tmp1; + + let tmp2 = snapshot.read(); + if (tmp2 === null) { + // all good + } else { + actual += tmp2; + assert.equal(snapshot.read(), null); + } + + assert.equal(actual, text); + + model.dispose(); + }); + +}); diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index 53ac8d481a6..eddae34ccc2 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -31,6 +31,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -55,6 +56,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 99, @@ -87,6 +89,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 13, verticalScrollbarHasArrows: true, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -111,6 +114,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 97, @@ -143,6 +147,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -167,6 +172,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 89, @@ -199,6 +205,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -223,6 +230,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 89, @@ -255,6 +263,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -279,6 +288,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 89, @@ -311,6 +321,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -335,6 +346,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 84, @@ -367,6 +379,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -391,6 +404,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 84, @@ -423,6 +437,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -447,6 +462,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 83, @@ -479,6 +495,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -503,6 +520,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 172, @@ -535,6 +553,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -559,6 +578,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 900, renderMinimap: RenderMinimap.None, + minimapLeft: 0, minimapWidth: 0, viewportColumn: 170, @@ -591,6 +611,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -615,6 +636,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.Small, + minimapLeft: 910, minimapWidth: 90, viewportColumn: 90, @@ -647,6 +669,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 2, @@ -671,6 +694,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.Large, + minimapLeft: 910, minimapWidth: 90, viewportColumn: 90, @@ -703,6 +727,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 4, @@ -727,6 +752,65 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { contentHeight: 800, renderMinimap: RenderMinimap.Large, + minimapLeft: 953, + minimapWidth: 47, + viewportColumn: 94, + + verticalScrollbarWidth: 0, + horizontalScrollbarHeight: 0, + + overviewRuler: { + top: 0, + width: 0, + height: 800, + right: 0 + } + }); + }); + + test('EditorLayoutProvider 10 - render minimap to left', () => { + doTest({ + outerWidth: 1000, + outerHeight: 800, + showGlyphMargin: false, + lineHeight: 16, + showLineNumbers: false, + lineNumbersMinChars: 0, + lineNumbersDigitCount: 1, + lineDecorationsWidth: 10, + typicalHalfwidthCharacterWidth: 10, + maxDigitWidth: 10, + verticalScrollbarWidth: 0, + horizontalScrollbarHeight: 0, + scrollbarArrowSize: 0, + verticalScrollbarHasArrows: false, + minimap: true, + minimapSide: 'left', + minimapRenderCharacters: true, + minimapMaxColumn: 150, + pixelRatio: 4, + }, { + width: 1000, + height: 800, + + glyphMarginLeft: 47, + glyphMarginWidth: 0, + glyphMarginHeight: 800, + + lineNumbersLeft: 47, + lineNumbersWidth: 0, + lineNumbersHeight: 800, + + decorationsLeft: 47, + decorationsWidth: 10, + decorationsHeight: 800, + + contentLeft: 57, + contentWidth: 943, + contentHeight: 800, + + renderMinimap: RenderMinimap.Large, + minimapLeft: 0, minimapWidth: 47, viewportColumn: 94, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index c2fd7d84dbe..de1d4a87e45 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2395,6 +2395,11 @@ declare module monaco.editor { * Defaults to false. */ enabled?: boolean; + /** + * Control the side of the minimap in editor. + * Defaults to 'right'. + */ + side?: 'right' | 'left'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. @@ -2737,6 +2742,10 @@ declare module monaco.editor { * Enable word based suggestions. Defaults to 'true' */ wordBasedSuggestions?: boolean; + /** + * The history mode for suggestions. + */ + selectSuggestions?: string; /** * The font size for the suggest widget. * Defaults to the editor font size. @@ -2961,6 +2970,7 @@ declare module monaco.editor { export interface InternalEditorMinimapOptions { readonly enabled: boolean; + readonly side: 'right' | 'left'; readonly showSlider: 'always' | 'mouseover'; readonly renderCharacters: boolean; readonly maxColumn: number; @@ -3042,6 +3052,7 @@ declare module monaco.editor { readonly acceptSuggestionOnCommitCharacter: boolean; readonly snippetSuggestions: 'top' | 'bottom' | 'inline' | 'none'; readonly wordBasedSuggestions: boolean; + readonly selectSuggestions: 'never' | 'byRecency' | 'byPrefix'; readonly suggestFontSize: number; readonly suggestLineHeight: number; readonly selectionHighlight: boolean; @@ -3162,6 +3173,10 @@ declare module monaco.editor { * The height of the content (actual height) */ readonly contentHeight: number; + /** + * The position for the minimap + */ + readonly minimapLeft: number; /** * The width of the minimap */ @@ -4043,6 +4058,10 @@ declare module monaco.languages { * @readonly */ readonly markers: editor.IMarkerData[]; + /** + * Requested kind of actions to return. + */ + readonly only?: string; } /** @@ -4166,6 +4185,18 @@ declare module monaco.languages { * line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~ */ textEdit?: editor.ISingleEditOperation; + /** + * An optional array of additional text edits that are applied when + * selecting this completion. Edits must not overlap with the main edit + * nor with themselves. + */ + additionalTextEdits?: editor.ISingleEditOperation[]; + /** + * An optional set of characters that when pressed while this completion is active will accept it first and + * then type that character. *Note* that all commit characters should have `length=1` and that superfluous + * characters will be ignored. + */ + commitCharacters?: string[]; } /** @@ -4495,6 +4526,7 @@ declare module monaco.languages { command?: Command; edit?: WorkspaceEdit; diagnostics?: editor.IMarkerData[]; + kind?: string; } /** @@ -4908,14 +4940,19 @@ declare module monaco.languages { provideColorPresentations(model: editor.ITextModel, colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable; } - export interface IResourceEdit { + export interface ResourceFileEdit { + oldUri: Uri; + newUri: Uri; + } + + export interface ResourceTextEdit { resource: Uri; - range: IRange; - newText: string; + modelVersionId?: number; + edits: TextEdit[]; } export interface WorkspaceEdit { - edits: IResourceEdit[]; + edits: Array; rejectReason?: string; } diff --git a/src/vs/nls.js b/src/vs/nls.js index 231b85d0c86..2d633b44f9a 100644 --- a/src/vs/nls.js +++ b/src/vs/nls.js @@ -1,126 +1,140 @@ /*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -* Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------- -*--------------------------------------------------------------------------------------------*/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + * Please make sure to make edits in the .ts file at https://github.com/Microsoft/vscode-loader/ + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------- + *--------------------------------------------------------------------------------------------*/ 'use strict'; var NLSLoaderPlugin; (function (NLSLoaderPlugin) { - var Environment = (function () { - function Environment(isPseudo) { - this.isPseudo = isPseudo; - // - } - Environment.detect = function () { - var isPseudo = (typeof document !== 'undefined' && document.location && document.location.hash.indexOf('pseudo=true') >= 0); - return new Environment(isPseudo); - }; - return Environment; - }()); - function _format(message, args, env) { - var result; - if (args.length === 0) { - result = message; - } - else { - result = message.replace(/\{(\d+)\}/g, function (match, rest) { - var index = rest[0]; - return typeof args[index] !== 'undefined' ? args[index] : match; - }); - } - if (env.isPseudo) { - // FF3B and FF3D is the Unicode zenkaku representation for [ and ] - result = '\uFF3B' + result.replace(/[aouei]/g, '$&$&') + '\uFF3D'; - } - return result; - } - function findLanguageForModule(config, name) { - var result = config[name]; - if (result) - return result; - result = config['*']; - if (result) - return result; - return null; - } - function localize(env, data, message) { - var args = []; - for (var _i = 3; _i < arguments.length; _i++) { - args[_i - 3] = arguments[_i]; - } - return _format(message, args, env); - } - function createScopedLocalize(scope, env) { - return function (idx, defaultValue) { - var restArgs = Array.prototype.slice.call(arguments, 2); - return _format(scope[idx], restArgs, env); - }; - } - var NLSPlugin = (function () { - function NLSPlugin(env) { - var _this = this; - this._env = env; - this.localize = function (data, message) { - var args = []; - for (var _i = 2; _i < arguments.length; _i++) { - args[_i - 2] = arguments[_i]; - } - return localize.apply(void 0, [_this._env, data, message].concat(args)); - }; - } - NLSPlugin.prototype.setPseudoTranslation = function (value) { - this._env = new Environment(value); - }; - NLSPlugin.prototype.create = function (key, data) { - return { - localize: createScopedLocalize(data[key], this._env) - }; - }; - NLSPlugin.prototype.load = function (name, req, load, config) { - var _this = this; - config = config || {}; - if (!name || name.length === 0) { - load({ - localize: this.localize - }); - } - else { - var pluginConfig = config['vs/nls'] || {}; - var language = pluginConfig.availableLanguages ? findLanguageForModule(pluginConfig.availableLanguages, name) : null; - var suffix = '.nls'; - if (language !== null && language !== NLSPlugin.DEFAULT_TAG) { - suffix = suffix + '.' + language; - } - req([name + suffix], function (messages) { - if (Array.isArray(messages)) { - messages.localize = createScopedLocalize(messages, _this._env); - } - else { - messages.localize = createScopedLocalize(messages[name], _this._env); - } - load(messages); - }); - } - }; - return NLSPlugin; - }()); - NLSPlugin.DEFAULT_TAG = 'i-default'; - NLSLoaderPlugin.NLSPlugin = NLSPlugin; - function init() { - define('vs/nls', new NLSPlugin(Environment.detect())); - } - NLSLoaderPlugin.init = init; - if (typeof doNotInitLoader === 'undefined') { - init(); - } + var Environment = /** @class */ (function () { + function Environment(isPseudo) { + this.isPseudo = isPseudo; + // + } + Environment.detect = function () { + var isPseudo = (typeof document !== 'undefined' && document.location && document.location.hash.indexOf('pseudo=true') >= 0); + return new Environment(isPseudo); + }; + return Environment; + }()); + function _format(message, args, env) { + var result; + if (args.length === 0) { + result = message; + } + else { + result = message.replace(/\{(\d+)\}/g, function (match, rest) { + var index = rest[0]; + return typeof args[index] !== 'undefined' ? args[index] : match; + }); + } + if (env.isPseudo) { + // FF3B and FF3D is the Unicode zenkaku representation for [ and ] + result = '\uFF3B' + result.replace(/[aouei]/g, '$&$&') + '\uFF3D'; + } + return result; + } + function findLanguageForModule(config, name) { + var result = config[name]; + if (result) + return result; + result = config['*']; + if (result) + return result; + return null; + } + function localize(env, data, message) { + var args = []; + for (var _i = 3; _i < arguments.length; _i++) { + args[_i - 3] = arguments[_i]; + } + return _format(message, args, env); + } + function createScopedLocalize(scope, env) { + return function (idx, defaultValue) { + var restArgs = Array.prototype.slice.call(arguments, 2); + return _format(scope[idx], restArgs, env); + }; + } + var NLSPlugin = /** @class */ (function () { + function NLSPlugin(env) { + var _this = this; + this._env = env; + this.localize = function (data, message) { + var args = []; + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + return localize.apply(void 0, [_this._env, data, message].concat(args)); + }; + } + NLSPlugin.prototype.setPseudoTranslation = function (value) { + this._env = new Environment(value); + }; + NLSPlugin.prototype.create = function (key, data) { + return { + localize: createScopedLocalize(data[key], this._env) + }; + }; + NLSPlugin.prototype.load = function (name, req, load, config) { + var _this = this; + config = config || {}; + if (!name || name.length === 0) { + load({ + localize: this.localize + }); + } + else { + var pluginConfig = config['vs/nls'] || {}; + var language = pluginConfig.availableLanguages ? findLanguageForModule(pluginConfig.availableLanguages, name) : null; + var suffix = '.nls'; + if (language !== null && language !== NLSPlugin.DEFAULT_TAG) { + suffix = suffix + '.' + language; + } + var messagesLoaded_1 = function (messages) { + if (Array.isArray(messages)) { + messages.localize = createScopedLocalize(messages, _this._env); + } + else { + messages.localize = createScopedLocalize(messages[name], _this._env); + } + load(messages); + }; + if (typeof pluginConfig.loadBundle === 'function') { + pluginConfig.loadBundle(name, language, function (err, messages) { + // We have an error. Load the English default strings to not fail + if (err) { + req([name + '.nls'], messagesLoaded_1); + } + else { + messagesLoaded_1(messages); + } + }); + } + else { + req([name + suffix], messagesLoaded_1); + } + } + }; + NLSPlugin.DEFAULT_TAG = 'i-default'; + return NLSPlugin; + }()); + NLSLoaderPlugin.NLSPlugin = NLSPlugin; + function init() { + define('vs/nls', new NLSPlugin(Environment.detect())); + } + NLSLoaderPlugin.init = init; + if (typeof doNotInitLoader === 'undefined') { + init(); + } })(NLSLoaderPlugin || (NLSLoaderPlugin = {})); diff --git a/src/vs/platform/actions/browser/menuItemActionItem.ts b/src/vs/platform/actions/browser/menuItemActionItem.ts index 5d81043100e..2ce14fddef7 100644 --- a/src/vs/platform/actions/browser/menuItemActionItem.ts +++ b/src/vs/platform/actions/browser/menuItemActionItem.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IMenu, MenuItemAction, IMenuActionOptions } from 'vs/platform/actions/common/actions'; +import { IMenu, MenuItemAction, IMenuActionOptions, ICommandAction } from 'vs/platform/actions/common/actions'; import { IMessageService } from 'vs/platform/message/common/message'; import Severity from 'vs/base/common/severity'; import { IAction } from 'vs/base/common/actions'; @@ -17,6 +17,9 @@ import { domEvent } from 'vs/base/browser/event'; import { Emitter } from 'vs/base/common/event'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { memoize } from 'vs/base/common/decorators'; +import { IdGenerator } from 'vs/base/common/idGenerator'; +import { createCSSRule } from 'vs/base/browser/dom'; +import URI from 'vs/base/common/uri'; class AltKeyEmitter extends Emitter { @@ -114,17 +117,22 @@ export function createActionItem(action: IAction, keybindingService: IKeybinding return undefined; } +const ids = new IdGenerator('menu-item-action-item-icon-'); + export class MenuItemActionItem extends ActionItem { + static readonly ICON_PATH_TO_CSS_RULES: Map = new Map(); + private _wantsAltCommand: boolean = false; + private _itemClassDispose: IDisposable; constructor( - action: MenuItemAction, + public _action: MenuItemAction, @IKeybindingService private _keybindingService: IKeybindingService, @IMessageService protected _messageService: IMessageService, @IContextMenuService private _contextMenuService: IContextMenuService ) { - super(undefined, action, { icon: !!action.class, label: !action.class }); + super(undefined, _action, { icon: !!(_action.class || _action.item.iconPath), label: !_action.class && !_action.item.iconPath }); } protected get _commandAction(): IAction { @@ -142,6 +150,8 @@ export class MenuItemActionItem extends ActionItem { render(container: HTMLElement): void { super.render(container); + this._updateItemClass(this._action.item); + let mouseOver = false; let altDown = false; @@ -189,13 +199,41 @@ export class MenuItemActionItem extends ActionItem { _updateClass(): void { if (this.options.icon) { - const element = this.$e.getHTMLElement(); if (this._commandAction !== this._action) { - element.classList.remove(this._action.class); + this._updateItemClass(this._action.alt.item); } else if ((this._action).alt) { - element.classList.remove((this._action).alt.class); + this._updateItemClass(this._action.item); } - element.classList.add('icon', this._commandAction.class); } } + + _updateItemClass(item: ICommandAction): void { + dispose(this._itemClassDispose); + this._itemClassDispose = undefined; + + if (item.iconPath) { + let iconClass: string; + + if (MenuItemActionItem.ICON_PATH_TO_CSS_RULES.has(item.iconPath.dark)) { + iconClass = MenuItemActionItem.ICON_PATH_TO_CSS_RULES.get(item.iconPath.dark); + } else { + iconClass = ids.nextId(); + createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(item.iconPath.light || item.iconPath.dark).toString()}")`); + createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: url("${URI.file(item.iconPath.dark).toString()}")`); + MenuItemActionItem.ICON_PATH_TO_CSS_RULES.set(item.iconPath.dark, iconClass); + } + + this.$e.getHTMLElement().classList.add('icon', iconClass); + this._itemClassDispose = { dispose: () => this.$e.getHTMLElement().classList.remove('icon', iconClass) }; + } + } + + dispose(): void { + if (this._itemClassDispose) { + dispose(this._itemClassDispose); + this._itemClassDispose = undefined; + } + + super.dispose(); + } } diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 5e0eaceed36..f8786606a24 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -23,8 +23,7 @@ export interface ICommandAction { id: string; title: string | ILocalizedString; category?: string | ILocalizedString; - iconClass?: string; - iconPath?: string; + iconPath?: { dark: string; light?: string; }; precondition?: ContextKeyExpr; } @@ -180,7 +179,7 @@ export class MenuItemAction extends ExecuteCommandAction { @ICommandService commandService: ICommandService ) { typeof item.title === 'string' ? super(item.id, item.title, commandService) : super(item.id, item.title.value, commandService); - this._cssClass = item.iconClass; + this._cssClass = undefined; this._enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition); this._options = options || {}; diff --git a/src/vs/platform/actions/electron-browser/menusExtensionPoint.ts b/src/vs/platform/actions/electron-browser/menusExtensionPoint.ts index 2295ddd7b90..3955afd293e 100644 --- a/src/vs/platform/actions/electron-browser/menusExtensionPoint.ts +++ b/src/vs/platform/actions/electron-browser/menusExtensionPoint.ts @@ -4,12 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; -import { createCSSRule } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { join } from 'path'; -import { IdGenerator } from 'vs/base/common/idGenerator'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { forEach } from 'vs/base/common/collections'; import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; @@ -281,33 +278,27 @@ namespace schema { ExtensionsRegistry.registerExtensionPoint('commands', [], schema.commandsContribution).setHandler(extensions => { - const ids = new IdGenerator('contrib-cmd-icon-'); - function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser) { if (!schema.isValidCommand(userFriendlyCommand, extension.collector)) { return; } - let { icon, category, title, command } = userFriendlyCommand; - let iconClass: string; - let iconPath: string; - if (icon) { - iconClass = ids.nextId(); - if (typeof icon === 'string') { - iconPath = join(extension.description.extensionFolderPath, icon); - createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(iconPath).toString()}")`); - } else { - const light = join(extension.description.extensionFolderPath, icon.light); - const dark = join(extension.description.extensionFolderPath, icon.dark); - createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(light).toString()}")`); - createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: url("${URI.file(dark).toString()}")`); + const { icon, category, title, command } = userFriendlyCommand; - iconPath = join(extension.description.extensionFolderPath, icon.dark); + let absoluteIcon: { dark: string; light?: string; }; + if (icon) { + if (typeof icon === 'string') { + absoluteIcon = { dark: join(extension.description.extensionFolderPath, icon) }; + } else { + absoluteIcon = { + dark: join(extension.description.extensionFolderPath, icon.dark), + light: join(extension.description.extensionFolderPath, icon.light) + }; } } - if (MenuRegistry.addCommand({ id: command, title, category, iconClass, iconPath })) { + if (MenuRegistry.addCommand({ id: command, title, category, iconPath: absoluteIcon })) { extension.collector.info(localize('dup', "Command `{0}` appears multiple times in the `commands` section.", userFriendlyCommand.command)); } } diff --git a/src/vs/platform/actions/test/common/menuService.test.ts b/src/vs/platform/actions/test/common/menuService.test.ts index d3844428fbe..caf6313eafb 100644 --- a/src/vs/platform/actions/test/common/menuService.test.ts +++ b/src/vs/platform/actions/test/common/menuService.test.ts @@ -48,6 +48,10 @@ class MockExtensionService implements IExtensionService { throw new Error('Not implemented'); } + public canProfileExtensionHost() { + return false; + } + public startExtensionHostProfile(): TPromise { throw new Error('Not implemented'); } diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 0fae04bac59..60c83ef1746 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -34,7 +34,7 @@ suite('BackupMainService', () => { class TestBackupMainService extends BackupMainService { constructor(backupHome: string, backupWorkspacesPath: string, configService: TestConfigurationService) { - super(environmentService, configService, new ConsoleLogMainService(environmentService)); + super(environmentService, configService, new ConsoleLogMainService()); this.backupHome = backupHome; this.workspacesJsonPath = backupWorkspacesPath; diff --git a/src/vs/platform/commands/test/commandService.test.ts b/src/vs/platform/commands/test/commandService.test.ts index 9b03a2f1eea..1a08ba578ef 100644 --- a/src/vs/platform/commands/test/commandService.test.ts +++ b/src/vs/platform/commands/test/commandService.test.ts @@ -40,6 +40,9 @@ class SimpleExtensionService implements IExtensionService { getExtensions(): TPromise { return TPromise.wrap([]); } + canProfileExtensionHost() { + return false; + } startExtensionHostProfile(): TPromise { throw new Error('Not implemented'); } diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 033f4501766..518898d9d85 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -143,7 +143,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { } public notifyConfigurationSchemaUpdated(configuration: IConfigurationNode) { - contributionRegistry.registerSchema(editorConfigurationSchemaId, this.editorConfigurationSchema); + contributionRegistry.notifySchemaChanged(editorConfigurationSchemaId); } public registerOverrideIdentifiers(overrideIdentifiers: string[]): void { diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 69381904e0a..f40bd669a54 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -6,13 +6,15 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import Event from 'vs/base/common/event'; +import { isFalsyOrWhitespace } from 'vs/base/common/strings'; export enum ContextKeyExprType { Defined = 1, Not = 2, Equals = 3, NotEquals = 4, - And = 5 + And = 5, + Regex = 6 } export abstract class ContextKeyExpr { @@ -29,6 +31,10 @@ export abstract class ContextKeyExpr { return new ContextKeyNotEqualsExpr(key, value); } + public static regex(key: string, value: RegExp): ContextKeyExpr { + return new ContextKeyRegexExpr(key, value); + } + public static not(key: string): ContextKeyExpr { return new ContextKeyNotExpr(key); } @@ -60,6 +66,11 @@ export abstract class ContextKeyExpr { return new ContextKeyEqualsExpr(pieces[0].trim(), this._deserializeValue(pieces[1])); } + if (serializedOne.indexOf('=~') >= 0) { + let pieces = serializedOne.split('=~'); + return new ContextKeyRegexExpr(pieces[0].trim(), this._deserializeRegexValue(pieces[1])); + } + if (/^\!\s*/.test(serializedOne)) { return new ContextKeyNotExpr(serializedOne.substr(1).trim()); } @@ -86,6 +97,29 @@ export abstract class ContextKeyExpr { return serializedValue; } + private static _deserializeRegexValue(serializedValue: string): RegExp { + + if (isFalsyOrWhitespace(serializedValue)) { + console.warn('missing regexp-value for =~-expression'); + return null; + } + + let start = serializedValue.indexOf('/'); + let end = serializedValue.lastIndexOf('/'); + if (start === end || start < 0 /* || to < 0 */) { + console.warn(`bad regexp-value '${serializedValue}', missing /-enclosure`); + return null; + } + + let value = serializedValue.slice(start + 1, end); + try { + return new RegExp(value); + } catch (e) { + console.warn(`bad regexp-value '${serializedValue}', parse error: ${e}`); + return null; + } + } + public abstract getType(): ContextKeyExprType; public abstract equals(other: ContextKeyExpr): boolean; public abstract evaluate(context: IContext): boolean; @@ -109,6 +143,8 @@ function cmp(a: ContextKeyExpr, b: ContextKeyExpr): number { return (a).cmp(b); case ContextKeyExprType.NotEquals: return (a).cmp(b); + case ContextKeyExprType.Regex: + return (a).cmp(b); default: throw new Error('Unknown ContextKeyExpr!'); } @@ -320,6 +356,58 @@ export class ContextKeyNotExpr implements ContextKeyExpr { } } +export class ContextKeyRegexExpr implements ContextKeyExpr { + + constructor(private key: string, private regexp: RegExp) { + // + } + + public getType(): ContextKeyExprType { + return ContextKeyExprType.Regex; + } + + public cmp(other: ContextKeyRegexExpr): number { + if (this.key < other.key) { + return -1; + } + if (this.key > other.key) { + return 1; + } + const source = this.regexp ? this.regexp.source : undefined; + if (source < other.regexp.source) { + return -1; + } + if (source > other.regexp.source) { + return 1; + } + return 0; + } + + public equals(other: ContextKeyExpr): boolean { + if (other instanceof ContextKeyRegexExpr) { + const source = this.regexp ? this.regexp.source : undefined; + return (this.key === other.key && source === other.regexp.source); + } + return false; + } + + public evaluate(context: IContext): boolean { + return this.regexp ? this.regexp.test(context.getValue(this.key)) : false; + } + + public normalize(): ContextKeyExpr { + return this; + } + + public serialize(): string { + return `${this.keys} =~ /${this.regexp ? this.regexp.source : ''}/`; + } + + public keys(): string[] { + return [this.key]; + } +} + export class ContextKeyAndExpr implements ContextKeyExpr { public readonly expr: ContextKeyExpr[]; diff --git a/src/vs/platform/contextkey/test/common/contextkey.test.ts b/src/vs/platform/contextkey/test/common/contextkey.test.ts index 69f8bca0930..beafc373f80 100644 --- a/src/vs/platform/contextkey/test/common/contextkey.test.ts +++ b/src/vs/platform/contextkey/test/common/contextkey.test.ts @@ -21,6 +21,8 @@ suite('ContextKeyExpr', () => { ContextKeyExpr.has('a1'), ContextKeyExpr.and(ContextKeyExpr.has('and.a')), ContextKeyExpr.has('a2'), + ContextKeyExpr.regex('d3', /d.*/), + ContextKeyExpr.regex('d4', /\*\*3*/), ContextKeyExpr.equals('b1', 'bb1'), ContextKeyExpr.equals('b2', 'bb2'), ContextKeyExpr.notEquals('c1', 'cc1'), @@ -32,9 +34,11 @@ suite('ContextKeyExpr', () => { ContextKeyExpr.equals('b2', 'bb2'), ContextKeyExpr.notEquals('c1', 'cc1'), ContextKeyExpr.not('d1'), + ContextKeyExpr.regex('d4', /\*\*3*/), ContextKeyExpr.notEquals('c2', 'cc2'), ContextKeyExpr.has('a2'), ContextKeyExpr.equals('b1', 'bb1'), + ContextKeyExpr.regex('d3', /d.*/), ContextKeyExpr.has('a1'), ContextKeyExpr.and(ContextKeyExpr.equals('and.a', true)), ContextKeyExpr.not('d2') @@ -59,9 +63,11 @@ suite('ContextKeyExpr', () => { let context = createContext({ 'a': true, 'b': false, - 'c': '5' + 'c': '5', + 'd': 'd' }); function testExpression(expr: string, expected: boolean): void { + // console.log(expr + ' ' + expected); let rules = ContextKeyExpr.deserialize(expr); assert.equal(rules.evaluate(context), expected, expr); } @@ -74,16 +80,19 @@ suite('ContextKeyExpr', () => { testExpression(expr + ' == 5', value == '5'); testExpression(expr + ' != 5', value != '5'); testExpression('!' + expr, !value); + testExpression(expr + ' =~ /d.*/', /d.*/.test(value)); } testBatch('a', true); testBatch('b', false); testBatch('c', '5'); + testBatch('d', 'd'); testBatch('z', undefined); testExpression('a && !b', true && !false); testExpression('a && b', true && false); testExpression('a && !b && c == 5', true && !false && '5' == '5'); + testExpression('dddd =~ d.*', false); /* tslint:enable:triple-equals */ }); }); diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index d75fdae4684..7af1337322a 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { LogLevel } from 'vs/platform/log/common/log'; export interface ParsedArgs { [arg: string]: any; @@ -116,7 +115,6 @@ export interface IEnvironmentService { // logging logsPath: string; verbose: boolean; - logLevel: LogLevel; skipGettingStarted: boolean | undefined; skipReleaseNotes: boolean | undefined; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 21a2f2d16c0..967ad4ab533 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -49,6 +49,7 @@ const options: minimist.Opts = { 'list-extensions', 'show-versions', 'nolazy', + 'issue', 'skip-getting-started', 'skip-release-notes', 'sticky-quickopen', @@ -165,7 +166,7 @@ const troubleshootingHelp: { [name: string]: string; } = { '--inspect-extensions': localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection uri."), '--inspect-brk-extensions': 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': localize('disableGPU', "Disable GPU hardware acceleration."), - '--upload-logs': localize('uploadLogs', "Uploads logs from current session to a secure endpoint.") + '--upload-logs': localize('uploadLogs', "Uploads logs from current session to a secure endpoint."), }; export function formatOptions(options: { [name: string]: string; }, columns: number): string { diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index b5e01b791cc..f70b6e81a5a 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -12,7 +12,6 @@ import URI from 'vs/base/common/uri'; import { memoize } from 'vs/base/common/decorators'; import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; -import { LogLevel } from 'vs/platform/log/common/log'; import { toLocalISOString } from 'vs/base/common/date'; import { isWindows, isLinux } from 'vs/base/common/platform'; @@ -152,33 +151,6 @@ export class EnvironmentService implements IEnvironmentService { get isBuilt(): boolean { return !process.env['VSCODE_DEV']; } get verbose(): boolean { return this._args.verbose; } - @memoize - get logLevel(): LogLevel { - if (this.verbose) { - return LogLevel.Trace; - } - if (typeof this._args.log === 'string') { - const logLevel = this._args.log.toLowerCase(); - switch (logLevel) { - case 'trace': - return LogLevel.Trace; - case 'debug': - return LogLevel.Debug; - case 'info': - return LogLevel.Info; - case 'warn': - return LogLevel.Warning; - case 'error': - return LogLevel.Error; - case 'critical': - return LogLevel.Critical; - case 'off': - return LogLevel.Off; - } - } - return LogLevel.Info; - } - get wait(): boolean { return this._args.wait; } get logExtensionHostCommunication(): boolean { return this._args.logExtensionHostCommunication; } diff --git a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts index 1f475504c98..1a787fc24c1 100644 --- a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts @@ -8,8 +8,8 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { distinct, coalesce } from 'vs/base/common/arrays'; import Event, { Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { adoptToGalleryExtensionId, getIdFromLocalExtensionId, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState, ILocalExtension, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { adoptToGalleryExtensionId, getIdFromLocalExtensionId, areSameExtensions, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -77,13 +77,19 @@ export class ExtensionEnablementService implements IExtensionEnablementService { return EnablementState.Enabled; } - canChangeEnablement(): boolean { - return !this.environmentService.disableExtensions; + canChangeEnablement(extension: ILocalExtension): boolean { + return !this.environmentService.disableExtensions && !(extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length); } - setEnablement(identifier: IExtensionIdentifier, newState: EnablementState): TPromise { - if (this.environmentService.disableExtensions) { - return TPromise.wrap(false); + setEnablement(arg: ILocalExtension | IExtensionIdentifier, newState: EnablementState): TPromise { + let identifier; + if (isIExtensionIdentifier(arg)) { + identifier = arg; + } else { + if (!this.canChangeEnablement(arg)) { + return TPromise.wrap(false); + } + identifier = { id: getGalleryExtensionIdFromLocal(arg), uuid: arg.identifier.uuid }; } const workspace = newState === EnablementState.WorkspaceDisabled || newState === EnablementState.WorkspaceEnabled; diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index ca36e02bff8..5eb1cb408ab 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -85,6 +85,12 @@ export interface IColor { defaults: { light: string, dark: string, highContrast: string }; } +export interface ILocalization { + languageId: string; + languageName?: string; + translations: string; +} + export interface IExtensionContributions { commands?: ICommand[]; configuration?: IConfiguration; @@ -98,7 +104,8 @@ export interface IExtensionContributions { themes?: ITheme[]; iconThemes?: ITheme[]; views?: { [location: string]: IView[] }; - colors: IColor[]; + colors?: IColor[]; + localizations?: ILocalization[]; } export interface IExtensionManifest { @@ -136,6 +143,13 @@ export interface IGalleryExtensionAssets { repository: IGalleryExtensionAsset; } +export function isIExtensionIdentifier(thing: any): thing is IExtensionIdentifier { + return thing + && typeof thing === 'object' + && typeof thing.id === 'string' + && (!thing.uuid || typeof thing.uuid === 'string'); +} + export interface IExtensionIdentifier { id: string; uuid?: string; @@ -215,6 +229,11 @@ export enum StatisticType { Uninstall = 'uninstall' } +export interface IReportedExtension { + id: IExtensionIdentifier; + malicious: boolean; +} + export interface IExtensionGalleryService { _serviceBrand: any; isEnabled(): boolean; @@ -226,6 +245,7 @@ export interface IExtensionGalleryService { getChangelog(extension: IGalleryExtension): TPromise; loadCompatibleVersion(extension: IGalleryExtension): TPromise; loadAllDependencies(dependencies: IExtensionIdentifier[]): TPromise; + getExtensionsReport(): TPromise; } export interface InstallExtensionEvent { @@ -259,6 +279,7 @@ export interface IExtensionManagementService { installFromGallery(extension: IGalleryExtension): TPromise; uninstall(extension: ILocalExtension, force?: boolean): TPromise; getInstalled(type?: LocalExtensionType): TPromise; + getExtensionsReport(): TPromise; updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): TPromise; } @@ -295,7 +316,7 @@ export interface IExtensionEnablementService { /** * Returns `true` if the enablement can be changed. */ - canChangeEnablement(): boolean; + canChangeEnablement(extension: ILocalExtension): boolean; /** * Returns `true` if the given extension identifier is enabled. @@ -311,6 +332,10 @@ export interface IExtensionEnablementService { * * Throws error if enablement is requested for workspace and there is no workspace */ + setEnablement(extension: ILocalExtension, state: EnablementState): TPromise; + /** + * TODO: @Sandy. Use setEnablement(extension: ILocalExtension, state: EnablementState): TPromise. Use one model for extension management and runtime + */ setEnablement(identifier: IExtensionIdentifier, state: EnablementState): TPromise; migrateToIdentifiers(installed: IExtensionIdentifier[]): void; diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index 15bb2aa58df..9cb9488880e 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata } from './extensionManagement'; +import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from './extensionManagement'; import Event, { buffer } from 'vs/base/common/event'; export interface IExtensionManagementChannel extends IChannel { @@ -19,6 +19,7 @@ export interface IExtensionManagementChannel extends IChannel { call(command: 'installFromGallery', extension: IGalleryExtension): TPromise; call(command: 'uninstall', args: [ILocalExtension, boolean]): TPromise; call(command: 'getInstalled'): TPromise; + call(command: 'getExtensionsReport'): TPromise; call(command: string, arg?: any): TPromise; } @@ -47,6 +48,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel { case 'uninstall': return this.service.uninstall(arg[0], arg[1]); case 'getInstalled': return this.service.getInstalled(arg); case 'updateMetadata': return this.service.updateMetadata(arg[0], arg[1]); + case 'getExtensionsReport': return this.service.getExtensionsReport(); } return undefined; } @@ -89,4 +91,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): TPromise { return this.channel.call('updateMetadata', [local, metadata]); } + + getExtensionsReport(): TPromise { + return this.channel.call('getExtensionsReport'); + } } \ No newline at end of file diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index 3b60c27a367..73519179b53 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -5,7 +5,7 @@ 'use strict'; -import { ILocalExtension, IGalleryExtension, EXTENSION_IDENTIFIER_REGEX, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ILocalExtension, IGalleryExtension, EXTENSION_IDENTIFIER_REGEX, IExtensionIdentifier, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean { if (a.uuid && b.uuid) { @@ -101,4 +101,16 @@ export function getGalleryExtensionTelemetryData(extension: IGalleryExtension): } export const BetterMergeDisabledNowKey = 'extensions/bettermergedisablednow'; -export const BetterMergeId = 'pprice.better-merge'; \ No newline at end of file +export const BetterMergeId = 'pprice.better-merge'; + +export function getMaliciousExtensionsSet(report: IReportedExtension[]): Set { + const result = new Set(); + + for (const extension of report) { + if (extension.malicious) { + result.add(extension.id.id); + } + } + + return result; +} \ No newline at end of file diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index e79adfe2cbc..81b8e3cc744 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import { TPromise } from 'vs/base/common/winjs.base'; import { distinct } from 'vs/base/common/arrays'; import { getErrorMessage, isPromiseCanceledError } from 'vs/base/common/errors'; -import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionManifest, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionManifest, IExtensionIdentifier, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { assign, getOrDefault } from 'vs/base/common/objects'; import { IRequestService } from 'vs/platform/request/node/request'; @@ -23,6 +23,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { readFile } from 'vs/base/node/pfs'; import { writeFileAndFlushSync } from 'vs/base/node/extfs'; import { generateUuid, isUUID } from 'vs/base/common/uuid'; +import { values } from 'vs/base/common/map'; interface IRawGalleryExtensionFile { assetType: string; @@ -309,11 +310,17 @@ function toExtension(galleryExtension: IRawGalleryExtension, extensionsGalleryUr }; } +interface IRawExtensionsReport { + malicious: string[]; + slow: string[]; +} + export class ExtensionGalleryService implements IExtensionGalleryService { _serviceBrand: any; private extensionsGalleryUrl: string; + private extensionsControlUrl: string; private readonly commonHeadersPromise: TPromise<{ [key: string]: string; }>; @@ -324,6 +331,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { ) { const config = product.extensionsGallery; this.extensionsGalleryUrl = config && config.serviceUrl; + this.extensionsControlUrl = config && config.controlUrl; this.commonHeadersPromise = resolveMarketplaceHeaders(this.environmentService); } @@ -711,6 +719,34 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } return false; } + + getExtensionsReport(): TPromise { + if (!this.isEnabled()) { + return TPromise.wrapError(new Error('No extension gallery service configured.')); + } + + if (!this.extensionsControlUrl) { + return TPromise.as([]); + } + + return this.requestService.request({ type: 'GET', url: this.extensionsControlUrl }).then(context => { + if (context.res.statusCode !== 200) { + return TPromise.wrapError(new Error('Could not get extensions report.')); + } + + return asJson(context).then(result => { + const map = new Map(); + + for (const id of result.malicious) { + const ext = map.get(id) || { id: { id }, malicious: true, slow: false }; + ext.malicious = true; + map.set(id, ext); + } + + return TPromise.as(values(map)); + }); + }); + } } export function resolveMarketplaceHeaders(environmentService: IEnvironmentService): TPromise<{ [key: string]: string; }> { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index f3752b10161..4688278bde0 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -10,7 +10,7 @@ import * as path from 'path'; import * as pfs from 'vs/base/node/pfs'; import * as errors from 'vs/base/common/errors'; import { assign } from 'vs/base/common/objects'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { flatten, distinct } from 'vs/base/common/arrays'; import { extract, buffer } from 'vs/base/node/zip'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -19,9 +19,10 @@ import { IGalleryExtension, IExtensionManifest, IGalleryMetadata, InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, LocalExtensionType, StatisticType, - IExtensionIdentifier + IExtensionIdentifier, + IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { getGalleryExtensionIdFromLocal, adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { getGalleryExtensionIdFromLocal, adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { localizeManifest } from '../common/extensionNls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Limiter } from 'vs/base/common/async'; @@ -45,6 +46,8 @@ const INSTALL_ERROR_GALLERY = 'gallery'; const INSTALL_ERROR_LOCAL = 'local'; const INSTALL_ERROR_EXTRACTING = 'extracting'; const INSTALL_ERROR_DELETING = 'deleting'; +const INSTALL_ERROR_READING_EXTENSION_FROM_DISK = 'readingExtension'; +const INSTALL_ERROR_SAVING_METADATA = 'savingMetadata'; const INSTALL_ERROR_UNKNOWN = 'unknown'; export class ExtensionManagementError extends Error { @@ -101,36 +104,39 @@ export class ExtensionManagementService implements IExtensionManagementService { private extensionsPath: string; private uninstalledPath: string; - private userDataPath: string; private uninstalledFileLimiter: Limiter; + private reportedExtensions: TPromise | undefined; + private lastReportTimestamp = 0; private disposables: IDisposable[] = []; - private _onInstallExtension = new Emitter(); - onInstallExtension: Event = this._onInstallExtension.event; + private readonly _onInstallExtension = new Emitter(); + readonly onInstallExtension: Event = this._onInstallExtension.event; - private _onDidInstallExtension = new Emitter(); - onDidInstallExtension: Event = this._onDidInstallExtension.event; + private readonly _onDidInstallExtension = new Emitter(); + readonly onDidInstallExtension: Event = this._onDidInstallExtension.event; - private _onUninstallExtension = new Emitter(); - onUninstallExtension: Event = this._onUninstallExtension.event; + private readonly _onUninstallExtension = new Emitter(); + readonly onUninstallExtension: Event = this._onUninstallExtension.event; + + private readonly installingExtensions: Map> = new Map>(); private _onDidUninstallExtension = new Emitter(); onDidUninstallExtension: Event = this._onDidUninstallExtension.event; constructor( - @IEnvironmentService environmentService: IEnvironmentService, + @IEnvironmentService private environmentService: IEnvironmentService, @IChoiceService private choiceService: IChoiceService, @IExtensionGalleryService private galleryService: IExtensionGalleryService, - @ILogService private logService: ILogService, + @ILogService private logService: ILogService ) { this.extensionsPath = environmentService.extensionsPath; this.uninstalledPath = path.join(this.extensionsPath, '.obsolete'); - this.userDataPath = environmentService.userDataPath; this.uninstalledFileLimiter = new Limiter(1); + this.disposables.push(toDisposable(() => this.installingExtensions.clear())); } private deleteExtensionsManifestCache(): void { - const cacheFolder = path.join(this.userDataPath, MANIFEST_CACHE_FOLDER); + const cacheFolder = path.join(this.environmentService.userDataPath, MANIFEST_CACHE_FOLDER); const cacheFile = path.join(cacheFolder, USER_MANIFEST_CACHE_FILE); pfs.del(cacheFile).done(() => { }, () => { }); @@ -257,9 +263,31 @@ export class ExtensionManagementService implements IExtensionManagementService { } private downloadAndInstallExtensions(extensions: IGalleryExtension[]): TPromise { - return TPromise.join(extensions.map(extensionToInstall => this.downloadInstallableExtension(extensionToInstall) - .then(installableExtension => this.installExtension(installableExtension)) - )).then(null, errors => this.rollback(extensions).then(() => TPromise.wrapError(errors), () => TPromise.wrapError(errors))); + return TPromise.join(extensions.map(extensionToInstall => this.downloadAndInstallExtension(extensionToInstall))) + .then(null, errors => this.rollback(extensions).then(() => TPromise.wrapError(errors), () => TPromise.wrapError(errors))); + } + + private downloadAndInstallExtension(extension: IGalleryExtension): TPromise { + let installingExtension = this.installingExtensions.get(extension.identifier.id); + if (!installingExtension) { + installingExtension = this.getExtensionsReport() + .then(report => { + if (getMaliciousExtensionsSet(report).has(extension.identifier.id)) { + throw new Error(nls.localize('malicious extension', "Can't install extension since it was reported to be malicious.")); + } else { + return extension; + } + }) + .then(extension => this.downloadInstallableExtension(extension)) + .then(installableExtension => this.installExtension(installableExtension)) + .then( + local => { this.installingExtensions.delete(extension.identifier.id); return local; }, + e => { this.installingExtensions.delete(extension.identifier.id); return TPromise.wrapError(e); } + ); + + this.installingExtensions.set(extension.identifier.id, installingExtension); + } + return installingExtension; } private downloadInstallableExtension(extension: IGalleryExtension): TPromise { @@ -353,6 +381,8 @@ export class ExtensionManagementService implements IExtensionManagementService { } private installExtension(installableExtension: InstallableExtension): TPromise { + // BLOCK REPORTED EXTENSIONS HERE? + return this.unsetUninstalledAndGetLocal(installableExtension.id) .then( local => { @@ -396,7 +426,7 @@ export class ExtensionManagementService implements IExtensionManagementService { () => { this.logService.info(`Extracted extension to ${extensionPath}:`, id); return TPromise.join([readManifest(extensionPath), pfs.readdir(extensionPath)]) - .then(null, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_LOCAL))); + .then(null, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_READING_EXTENSION_FROM_DISK))); }, e => TPromise.wrapError(new ExtensionManagementError(e.message, INSTALL_ERROR_EXTRACTING))) .then(([{ manifest }, children]) => { @@ -414,7 +444,7 @@ export class ExtensionManagementService implements IExtensionManagementService { .then(() => { this.logService.info(`Updated metadata of the extension:`, id); return local; - }, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_LOCAL))); + }, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_SAVING_METADATA))); }); }, e => TPromise.wrapError(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING))); } @@ -682,7 +712,7 @@ export class ExtensionManagementService implements IExtensionManagementService { if (manifest.extensionDependencies) { manifest.extensionDependencies = manifest.extensionDependencies.map(id => adoptToGalleryExtensionId(id)); } - const identifier = { id, uuid: metadata ? metadata.id : null }; + const identifier = { id: type === LocalExtensionType.System ? id : getLocalExtensionIdFromManifest(manifest), uuid: metadata ? metadata.id : null }; return { type, identifier, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl }; }); }).then(null, () => null); @@ -762,6 +792,30 @@ export class ExtensionManagementService implements IExtensionManagementService { }); } + getExtensionsReport(): TPromise { + const now = new Date().getTime(); + + if (!this.reportedExtensions || now - this.lastReportTimestamp > 1000 * 60 * 5) { // 5 minute cache freshness + this.reportedExtensions = this.updateReportCache(); + this.lastReportTimestamp = now; + } + + return this.reportedExtensions; + } + + private updateReportCache(): TPromise { + this.logService.trace('ExtensionManagementService.refreshReportedCache'); + + return this.galleryService.getExtensionsReport() + .then(result => { + this.logService.trace(`ExtensionManagementService.refreshReportedCache - got ${result.length} reported extensions from service`); + return result; + }, err => { + this.logService.trace('ExtensionManagementService.refreshReportedCache - failed to get extension report'); + return []; + }); + } + dispose() { this.disposables = dispose(this.disposables); } diff --git a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts index 93bfae02c16..63d92406632 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { IExtensionManagementService, IExtensionEnablementService, DidUninstallExtensionEvent, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, IExtensionEnablementService, DidUninstallExtensionEvent, EnablementState, IExtensionContributions, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { Emitter } from 'vs/base/common/event'; @@ -39,7 +39,7 @@ export class TestExtensionEnablementService extends ExtensionEnablementService { } public reset(): TPromise { - return this.getDisabledExtensions().then(extensions => extensions.forEach(d => this.setEnablement(d, EnablementState.Enabled))); + return this.getDisabledExtensions().then(extensions => extensions.forEach(d => this.setEnablement(aLocalExtension(d.id), EnablementState.Enabled))); } } @@ -52,7 +52,7 @@ suite('ExtensionEnablementService Test', () => { setup(() => { instantiationService = new TestInstantiationService(); - instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, }); + instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event }); testObject = new TestExtensionEnablementService(instantiationService); }); @@ -65,7 +65,7 @@ suite('ExtensionEnablementService Test', () => { }); test('test when no extensions are disabled for workspace when there is no workspace', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => { instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY); return testObject.getDisabledExtensions().then(extensions => assert.deepEqual([], extensions)); @@ -73,255 +73,271 @@ suite('ExtensionEnablementService Test', () => { }); test('test disable an extension globally', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([{ id: 'pub.a' }], extensions)); }); test('test disable an extension globally should return truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(value => assert.ok(value)); }); test('test disable an extension globally triggers the change event', () => { const target = sinon.spy(); testObject.onEnablementChanged(target); - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a' }))); + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))); }); test('test disable an extension globally again should return a falsy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(value => assert.ok(!value)); }); test('test state of globally disabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); }); test('test state of globally enabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); }); test('test disable an extension for workspace', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([{ id: 'pub.a' }], extensions)); }); test('test disable an extension for workspace returns a truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(value => assert.ok(value)); }); test('test disable an extension for workspace again should return a falsy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(value => assert.ok(!value)); }); test('test state of workspace disabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); }); test('test state of workspace and globally disabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); }); test('test state of workspace enabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceEnabled)); }); test('test state of globally disabled and workspace enabled extension', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceEnabled)); }); test('test state of an extension when disabled for workspace from workspace enabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.WorkspaceDisabled)); }); test('test state of an extension when disabled globally from workspace enabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); }); test('test state of an extension when disabled globally from workspace disabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Disabled)); }); test('test state of an extension when enabled globally from workspace enabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); }); test('test state of an extension when enabled globally from workspace disabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(() => assert.equal(testObject.getEnablementState({ id: 'pub.a' }), EnablementState.Enabled)); }); test('test disable an extension for workspace and then globally', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([{ id: 'pub.a' }], extensions)); }); test('test disable an extension for workspace and then globally return a truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(value => assert.ok(value)); }); test('test disable an extension for workspace and then globally trigger the change event', () => { const target = sinon.spy(); - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => testObject.onEnablementChanged(target)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a' }))); + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))); }); test('test disable an extension globally and then for workspace', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([{ id: 'pub.a' }], extensions)); }); test('test disable an extension globally and then for workspace return a truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) .then(value => assert.ok(value)); }); test('test disable an extension globally and then for workspace triggers the change event', () => { const target = sinon.spy(); - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.onEnablementChanged(target)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled)) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a' }))); + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled)) + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))); }); test('test disable an extension for workspace when there is no workspace throws error', (done) => { instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY); - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => assert.fail('should throw an error'), error => assert.ok(error)) .then(done, done); }); test('test enable an extension globally', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([], extensions)); }); test('test enable an extension globally return truthy promise', (done) => { - testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(value => assert.ok(value)) .then(done, done); }); test('test enable an extension globally triggers change event', (done) => { const target = sinon.spy(); - testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => testObject.onEnablementChanged(target)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a' }))) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.a', uuid: void 0 }))) .then(done, done); }); test('test enable an extension globally when already enabled return falsy promise', (done) => { - testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled) + testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled) .then(value => assert.ok(!value)) .then(done, done); }); test('test enable an extension for workspace', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([], extensions)); }); test('test enable an extension for workspace return truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(value => assert.ok(value)); }); test('test enable an extension for workspace triggers change event', () => { const target = sinon.spy(); - return testObject.setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.b'), EnablementState.WorkspaceDisabled) .then(() => testObject.onEnablementChanged(target)) - .then(() => testObject.setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceEnabled)) - .then(() => assert.ok(target.calledWithExactly({ id: 'pub.b' }))); + .then(() => testObject.setEnablement(aLocalExtension('pub.b'), EnablementState.WorkspaceEnabled)) + .then(() => assert.ok(target.calledWithExactly({ id: 'pub.b', uuid: void 0 }))); }); test('test enable an extension for workspace when already enabled return truthy promise', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled) .then(value => assert.ok(value)); }); test('test enable an extension for workspace when disabled in workspace and gloablly', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceEnabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceEnabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([], extensions)); }); test('test enable an extension globally when disabled in workspace and gloablly', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Enabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Enabled)) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([], extensions)); }); test('test remove an extension from disablement list when uninstalled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled)) .then(() => didUninstallEvent.fire({ identifier: { id: 'pub.a-1.0.0' } })) .then(() => testObject.getDisabledExtensions()) .then(extensions => assert.deepEqual([], extensions)); }); test('test isEnabled return false extension is disabled globally', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.Disabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.Disabled) .then(() => assert.ok(!testObject.isEnabled({ id: 'pub.a' }))); }); test('test isEnabled return false extension is disabled in workspace', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) .then(() => assert.ok(!testObject.isEnabled({ id: 'pub.a' }))); }); test('test isEnabled return true extension is not disabled', () => { - return testObject.setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled) - .then(() => testObject.setEnablement({ id: 'pub.c' }, EnablementState.Disabled)) + return testObject.setEnablement(aLocalExtension('pub.a'), EnablementState.WorkspaceDisabled) + .then(() => testObject.setEnablement(aLocalExtension('pub.c'), EnablementState.Disabled)) .then(() => assert.ok(testObject.isEnabled({ id: 'pub.b' }))); }); -}); \ No newline at end of file + + test('test canChangeEnablement return false for language packs', () => { + assert.equal(testObject.canChangeEnablement(aLocalExtension('pub.a', { localizations: [{ languageId: 'gr', translations: 'somepath' }] })), false); + }); +}); + +function aLocalExtension(id: string, contributes?: IExtensionContributions): ILocalExtension { + const [publisher, name] = id.split('.'); + return Object.create({ + identifier: { id }, + manifest: { + name, + publisher, + contributes + } + }); +} diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index fe757879b07..ec5d37cfa9f 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -168,6 +168,11 @@ export interface IExtensionService { */ getExtensionsStatus(): { [id: string]: IExtensionsStatus }; + /** + * Check if the extension host can be profiled. + */ + canProfileExtensionHost(): boolean; + /** * Begin an extension host process profile session. */ diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index ef95e1af1ec..0fe4bf63718 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -83,7 +83,7 @@ export interface IFileService { /** * Updates the content replacing its previous value. */ - updateContent(resource: URI, value: string, options?: IUpdateContentOptions): TPromise; + updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): TPromise; /** * Moves the file to a new path identified by the resource. @@ -459,6 +459,28 @@ export interface IStringStream { on(event: string, callback: any): void; } +/** + * Text snapshot that works like an iterator. + * Will try to return chunks of roughly ~64KB size. + * Will return null when finished. + */ +export interface ITextSnapshot { + read(): string; +} + +/** + * Helper method to convert a snapshot into its full string form. + */ +export function snapshotToString(snapshot: ITextSnapshot): string { + const chunks: string[] = []; + let chunk: string; + while (typeof (chunk = snapshot.read()) === 'string') { + chunks.push(chunk); + } + + return chunks.join(''); +} + /** * Streamable content and meta information of a file. */ diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts new file mode 100644 index 00000000000..1f80ba156b7 --- /dev/null +++ b/src/vs/platform/issue/common/issue.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { TPromise } from 'vs/base/common/winjs.base'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; + +export const ID = 'issueService'; +export const IIssueService = createDecorator(ID); + +export interface IssueReporterStyles { + backgroundColor: string; + color: string; + textLinkColor: string; + inputBackground: string; + inputForeground: string; + inputBorder: string; + inputErrorBorder: string; + inputActiveBorder: string; + buttonBackground: string; + buttonForeground: string; + buttonHoverBackground: string; +} + +export interface IssueReporterData { + styles: IssueReporterStyles; + zoomLevel: number; + enabledExtensions: ILocalExtension[]; +} + +export interface IIssueService { + _serviceBrand: any; + openReporter(data: IssueReporterData): TPromise; +} \ No newline at end of file diff --git a/src/vs/platform/issue/common/issueIpc.ts b/src/vs/platform/issue/common/issueIpc.ts new file mode 100644 index 00000000000..99d73534b5e --- /dev/null +++ b/src/vs/platform/issue/common/issueIpc.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { TPromise } from 'vs/base/common/winjs.base'; +import { IChannel } from 'vs/base/parts/ipc/common/ipc'; +import { IIssueService, IssueReporterData } from './issue'; + +export interface IIssueChannel extends IChannel { + call(command: 'openIssueReporter', arg: IssueReporterData): TPromise; + call(command: 'getStatusInfo'): TPromise; + call(command: string, arg?: any): TPromise; +} + +export class IssueChannel implements IIssueChannel { + + constructor(private service: IIssueService) { } + + call(command: string, arg?: any): TPromise { + switch (command) { + case 'openIssueReporter': + return this.service.openReporter(arg); + } + return undefined; + } +} + +export class IssueChannelClient implements IIssueService { + + _serviceBrand: any; + + constructor(private channel: IIssueChannel) { } + + openReporter(data: IssueReporterData): TPromise { + return this.channel.call('openIssueReporter', data); + } +} \ No newline at end of file diff --git a/src/vs/platform/issue/electron-main/issueService.ts b/src/vs/platform/issue/electron-main/issueService.ts new file mode 100644 index 00000000000..f103065344f --- /dev/null +++ b/src/vs/platform/issue/electron-main/issueService.ts @@ -0,0 +1,85 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { TPromise, Promise } from 'vs/base/common/winjs.base'; +import { localize } from 'vs/nls'; +import * as objects from 'vs/base/common/objects'; +import { parseArgs } from 'vs/platform/environment/node/argv'; +import { IIssueService, IssueReporterData } from 'vs/platform/issue/common/issue'; +import { BrowserWindow, ipcMain } from 'electron'; +import { ILaunchService } from 'vs/code/electron-main/launch'; +import { buildDiagnostics, DiagnosticInfo } from 'vs/code/electron-main/diagnostics'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + +const DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; + +export class IssueService implements IIssueService { + _serviceBrand: any; + _issueWindow: BrowserWindow; + + constructor( + private machineId: string, + @IEnvironmentService private environmentService: IEnvironmentService, + @ILaunchService private launchService: ILaunchService + ) { } + + openReporter(data: IssueReporterData): TPromise { + ipcMain.on('issueInfoRequest', event => { + this.getStatusInfo().then(msg => { + event.sender.send('issueInfoResponse', msg); + }); + }); + + this._issueWindow = new BrowserWindow({ + width: 800, + height: 1000, + title: localize('issueReporter', "Issue Reporter"), + parent: BrowserWindow.getFocusedWindow(), + backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR + }); + + this._issueWindow.setMenuBarVisibility(false); // workaround for now, until a menu is implemented + + this._issueWindow.loadURL(this.getIssueReporterPath(data)); + + return TPromise.as(null); + } + + private getStatusInfo(): TPromise { + return new Promise((resolve, reject) => { + this.launchService.getMainProcessInfo().then(info => { + buildDiagnostics(info) + .then(diagnosticInfo => { + resolve(diagnosticInfo); + }) + .catch(err => { + reject(err); + }); + }); + }); + } + + private getIssueReporterPath(data: IssueReporterData) { + const windowConfiguration = { + appRoot: this.environmentService.appRoot, + nodeCachedDataDir: this.environmentService.nodeCachedDataDir, + windowId: this._issueWindow.id, + machineId: this.machineId, + data + }; + + const environment = parseArgs(process.argv); + const config = objects.assign(environment, windowConfiguration); + for (let key in config) { + if (config[key] === void 0 || config[key] === null || config[key] === '') { + delete config[key]; // only send over properties that have a true value + } + } + + return `${require.toUrl('vs/code/electron-browser/issue/issueReporter.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; + } +} diff --git a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts index b9c921d4505..94fcaf68949 100644 --- a/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts +++ b/src/vs/platform/jsonschemas/common/jsonContributionRegistry.ts @@ -25,6 +25,13 @@ export interface IJSONContributionRegistry { */ registerSchema(uri: string, unresolvedSchemaContent: IJSONSchema): void; + + /** + * Notifies all listeneres that the content of the given schema has changed. + * @param uri The id of the schema + */ + notifySchemaChanged(uri: string): void; + /** * Get all schemas */ @@ -60,6 +67,10 @@ class JSONContributionRegistry implements IJSONContributionRegistry { this._onDidChangeSchema.fire(uri); } + public notifySchemaChanged(uri: string): void { + this._onDidChangeSchema.fire(uri); + } + public getSchemaContributions(): ISchemaContributions { return { schemas: this.schemasById, diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index 05dc85f8165..d283b200549 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -5,16 +5,21 @@ 'use strict'; import { ITree, ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree'; -import { List, IListOptions } from 'vs/base/browser/ui/list/listWidget'; +import { List, IListOptions, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, IMultipleSelectionController } from 'vs/base/browser/ui/list/listWidget'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, toDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { PagedList, IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; -import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; +import { IDelegate, IRenderer, IListMouseEvent, IListTouchEvent } from 'vs/base/browser/ui/list/list'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { attachListStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { InputFocusedContextKey } from 'vs/platform/workbench/common/contextkeys'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { mixin } from 'vs/base/common/objects'; +import { localize } from 'vs/nls'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; export type ListWidget = List | PagedList | ITree; @@ -89,6 +94,29 @@ function createScopedContextKeyService(contextKeyService: IContextKeyService, wi return result; } +export const multiSelectModifierSettingKey = 'workbench.multiSelectModifier'; + +export function useAltAsMultipleSelectionModifier(configurationService: IConfigurationService): boolean { + return configurationService.getValue(multiSelectModifierSettingKey) === 'alt'; +} + +class MultipleSelectionController implements IMultipleSelectionController { + + constructor(private configurationService: IConfigurationService) { } + + isSelectionSingleChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + if (useAltAsMultipleSelectionModifier(this.configurationService)) { + return event.browserEvent.altKey; + } + + return isSelectionSingleChangeEvent(event); + } + + isSelectionRangeChangeEvent(event: IListMouseEvent | IListTouchEvent): boolean { + return isSelectionRangeChangeEvent(event); + } +} + export class WorkbenchList extends List { readonly contextKeyService: IContextKeyService; @@ -101,21 +129,25 @@ export class WorkbenchList extends List { options: IListOptions, @IContextKeyService contextKeyService: IContextKeyService, @IListService listService: IListService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService ) { - super(container, delegate, renderers, options); - this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(contextKeyService); + const multipleSelectionSupport = !(options.multipleSelectionSupport === false); + + if (multipleSelectionSupport && !options.multipleSelectionController) { + options.multipleSelectionController = new MultipleSelectionController(configurationService); + } + + super(container, delegate, renderers, mixin(options, useAltAsMultipleSelectionModifier(configurationService))); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); + this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService); this.disposables.push(combinedDisposable([ this.contextKeyService, (listService as ListService).register(this), - attachListStyler(this, themeService) + attachListStyler(this, themeService), + this.onSelectionChange(() => this.listDoubleSelection.set(this.getSelection().length === 2)) ])); - this.disposables.push(this.onSelectionChange(() => { - const selection = this.getSelection(); - this.listDoubleSelection.set(selection && selection.length === 2); - })); } } @@ -131,9 +163,16 @@ export class WorkbenchPagedList extends PagedList { options: IListOptions, @IContextKeyService contextKeyService: IContextKeyService, @IListService listService: IListService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService ) { - super(container, delegate, renderers, options); + const multipleSelectionSupport = !(options.multipleSelectionSupport === false); + + if (multipleSelectionSupport && !options.multipleSelectionController) { + options.multipleSelectionController = new MultipleSelectionController(configurationService); + } + + super(container, delegate, renderers, mixin(options, useAltAsMultipleSelectionModifier(configurationService))); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); this.disposable = combinedDisposable([ @@ -164,8 +203,8 @@ export class WorkbenchTree extends Tree { ) { super(container, configuration, options); - this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(contextKeyService); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); + this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService); this.disposables.push( this.contextKeyService, @@ -182,3 +221,30 @@ export class WorkbenchTree extends Tree { this.disposables = dispose(this.disposables); } } + +const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + +configurationRegistry.registerConfiguration({ + 'id': 'workbench', + 'order': 7, + 'title': localize('workbenchConfigurationTitle', "Workbench"), + 'type': 'object', + 'properties': { + 'workbench.multiSelectModifier': { + 'type': 'string', + 'enum': ['ctrlCmd', 'alt'], + 'enumDescriptions': [ + localize('multiSelectModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on macOS."), + localize('multiSelectModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on macOS.") + ], + 'default': 'ctrlCmd', + 'description': localize({ + key: 'multiSelectModifier', + comment: [ + '- `ctrlCmd` refers to a value the setting can take and should not be localized.', + '- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.' + ] + }, "The modifier to be used to add an item to a multi-selection with the mouse (for example in trees and lists, if supported). `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on macOS. The 'Open to Side' mouse gestures - if supported - will adapt such that they do not conflict with the multiselect modifier.") + } + } +}); \ No newline at end of file diff --git a/src/vs/platform/log/common/bufferLog.ts b/src/vs/platform/log/common/bufferLog.ts index caa628e51da..65fa32adb0e 100644 --- a/src/vs/platform/log/common/bufferLog.ts +++ b/src/vs/platform/log/common/bufferLog.ts @@ -5,7 +5,7 @@ 'use strict'; -import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel, AbstractLogService } from 'vs/platform/log/common/log'; interface ILog { level: LogLevel; @@ -24,17 +24,12 @@ function getLogFunction(logger: ILogService, level: LogLevel): Function { } } -export class BufferLogService implements ILogService { +export class BufferLogService extends AbstractLogService implements ILogService { _serviceBrand: any; private buffer: ILog[] = []; private _logger: ILogService | undefined = undefined; - constructor( - private level: LogLevel = LogLevel.Error - ) { - } - set logger(logger: ILogService) { this._logger = logger; @@ -46,19 +41,11 @@ export class BufferLogService implements ILogService { this.buffer = []; } - setLevel(logLevel: LogLevel): void { - this.level = logLevel; - } - - getLevel(): LogLevel { - return this.level; - } - private _log(level: LogLevel, args: IArguments): void { if (this._logger) { const fn = getLogFunction(this._logger, level); fn.apply(this._logger, args); - } else if (this.level <= level) { + } else if (this.getLevel() <= level) { this.buffer.push({ level, args }); } } diff --git a/src/vs/platform/log/common/log.ts b/src/vs/platform/log/common/log.ts index 823ec1cd2e0..915e59c0df7 100644 --- a/src/vs/platform/log/common/log.ts +++ b/src/vs/platform/log/common/log.ts @@ -5,10 +5,11 @@ 'use strict'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { createDecorator as createServiceDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { isWindows } from 'vs/base/common/platform'; +import Event, { Emitter } from 'vs/base/common/event'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; export const ILogService = createServiceDecorator('logService'); @@ -22,11 +23,14 @@ export enum LogLevel { Off } +export const DEFAULT_LOG_LEVEL: LogLevel = LogLevel.Info; + export interface ILogService extends IDisposable { _serviceBrand: any; + onDidChangeLogLevel: Event; - setLevel(level: LogLevel): void; getLevel(): LogLevel; + setLevel(level: LogLevel): void; trace(message: string, ...args: any[]): void; debug(message: string, ...args: any[]): void; info(message: string, ...args: any[]): void; @@ -35,27 +39,37 @@ export interface ILogService extends IDisposable { critical(message: string | Error, ...args: any[]): void; } -export class ConsoleLogMainService implements ILogService { +export abstract class AbstractLogService extends Disposable { - _serviceBrand: any; - private level: LogLevel = LogLevel.Error; - private useColors: boolean; - - constructor( @IEnvironmentService environmentService: IEnvironmentService) { - this.setLevel(environmentService.logLevel); - this.useColors = !isWindows; - } + private level: LogLevel = DEFAULT_LOG_LEVEL; + private readonly _onDidChangeLogLevel: Emitter = this._register(new Emitter()); + readonly onDidChangeLogLevel: Event = this._onDidChangeLogLevel.event; setLevel(level: LogLevel): void { - this.level = level; + if (this.level !== level) { + this.level = level; + this._onDidChangeLogLevel.fire(this.level); + } } getLevel(): LogLevel { return this.level; } +} + +export class ConsoleLogMainService extends AbstractLogService implements ILogService { + + _serviceBrand: any; + private useColors: boolean; + + constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) { + super(); + this.setLevel(logLevel); + this.useColors = !isWindows; + } trace(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Trace) { + if (this.getLevel() <= LogLevel.Trace) { if (this.useColors) { console.log(`\x1b[90m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -65,7 +79,7 @@ export class ConsoleLogMainService implements ILogService { } debug(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Debug) { + if (this.getLevel() <= LogLevel.Debug) { if (this.useColors) { console.log(`\x1b[90m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -75,7 +89,7 @@ export class ConsoleLogMainService implements ILogService { } info(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Info) { + if (this.getLevel() <= LogLevel.Info) { if (this.useColors) { console.log(`\x1b[90m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -85,7 +99,7 @@ export class ConsoleLogMainService implements ILogService { } warn(message: string | Error, ...args: any[]): void { - if (this.level <= LogLevel.Warning) { + if (this.getLevel() <= LogLevel.Warning) { if (this.useColors) { console.warn(`\x1b[93m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -95,7 +109,7 @@ export class ConsoleLogMainService implements ILogService { } error(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Error) { + if (this.getLevel() <= LogLevel.Error) { if (this.useColors) { console.error(`\x1b[91m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -105,7 +119,7 @@ export class ConsoleLogMainService implements ILogService { } critical(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Critical) { + if (this.getLevel() <= LogLevel.Critical) { if (this.useColors) { console.error(`\x1b[90m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, message, ...args); } else { @@ -119,55 +133,47 @@ export class ConsoleLogMainService implements ILogService { } } -export class ConsoleLogService implements ILogService { +export class ConsoleLogService extends AbstractLogService implements ILogService { _serviceBrand: any; - private level: LogLevel = LogLevel.Error; - constructor( @IEnvironmentService environmentService: IEnvironmentService) { - this.setLevel(environmentService.logLevel); - } - - setLevel(level: LogLevel): void { - this.level = level; - } - - getLevel(): LogLevel { - return this.level; + constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) { + super(); + this.setLevel(logLevel); } trace(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Trace) { + if (this.getLevel() <= LogLevel.Trace) { console.log('%cTRACE', 'color: #888', message, ...args); } } debug(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Debug) { + if (this.getLevel() <= LogLevel.Debug) { console.log('%cDEBUG', 'background: #eee; color: #888', message, ...args); } } info(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Info) { + if (this.getLevel() <= LogLevel.Info) { console.log('%c INFO', 'color: #33f', message, ...args); } } warn(message: string | Error, ...args: any[]): void { - if (this.level <= LogLevel.Warning) { + if (this.getLevel() <= LogLevel.Warning) { console.log('%c WARN', 'color: #993', message, ...args); } } error(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Error) { + if (this.getLevel() <= LogLevel.Error) { console.log('%c ERR', 'color: #f33', message, ...args); } } critical(message: string, ...args: any[]): void { - if (this.level <= LogLevel.Critical) { + if (this.getLevel() <= LogLevel.Critical) { console.log('%cCRITI', 'background: #f33; color: white', message, ...args); } } @@ -175,22 +181,21 @@ export class ConsoleLogService implements ILogService { dispose(): void { } } -export class MultiplexLogService implements ILogService { +export class MultiplexLogService extends AbstractLogService implements ILogService { _serviceBrand: any; - constructor(private logServices: ILogService[]) { } + constructor(private logServices: ILogService[]) { + super(); + if (logServices.length) { + this.setLevel(logServices[0].getLevel()); + } + } setLevel(level: LogLevel): void { for (const logService of this.logServices) { logService.setLevel(level); } - } - - getLevel(): LogLevel { - for (const logService of this.logServices) { - return logService.getLevel(); - } - return LogLevel.Info; + super.setLevel(level); } trace(message: string, ...args: any[]): void { @@ -236,8 +241,54 @@ export class MultiplexLogService implements ILogService { } } +export class DelegatedLogService extends Disposable implements ILogService { + _serviceBrand: any; + + constructor(private logService: ILogService) { + super(); + this._register(logService); + } + + get onDidChangeLogLevel(): Event { + return this.logService.onDidChangeLogLevel; + } + + setLevel(level: LogLevel): void { + this.logService.setLevel(level); + } + + getLevel(): LogLevel { + return this.logService.getLevel(); + } + + trace(message: string, ...args: any[]): void { + this.logService.trace(message, ...args); + } + + debug(message: string, ...args: any[]): void { + this.logService.debug(message, ...args); + } + + info(message: string, ...args: any[]): void { + this.logService.info(message, ...args); + } + + warn(message: string, ...args: any[]): void { + this.logService.warn(message, ...args); + } + + error(message: string | Error, ...args: any[]): void { + this.logService.error(message, ...args); + } + + critical(message: string | Error, ...args: any[]): void { + this.logService.critical(message, ...args); + } +} + export class NullLogService implements ILogService { _serviceBrand: any; + readonly onDidChangeLogLevel: Event = new Emitter().event; setLevel(level: LogLevel): void { } getLevel(): LogLevel { return LogLevel.Info; } trace(message: string, ...args: any[]): void { } @@ -248,3 +299,30 @@ export class NullLogService implements ILogService { critical(message: string | Error, ...args: any[]): void { } dispose(): void { } } + + +export function getLogLevel(environmentService: IEnvironmentService): LogLevel { + if (environmentService.verbose) { + return LogLevel.Trace; + } + if (typeof environmentService.args.log === 'string') { + const logLevel = environmentService.args.log.toLowerCase(); + switch (logLevel) { + case 'trace': + return LogLevel.Trace; + case 'debug': + return LogLevel.Debug; + case 'info': + return LogLevel.Info; + case 'warn': + return LogLevel.Warning; + case 'error': + return LogLevel.Error; + case 'critical': + return LogLevel.Critical; + case 'off': + return LogLevel.Off; + } + } + return DEFAULT_LOG_LEVEL; +} \ No newline at end of file diff --git a/src/vs/platform/log/common/logIpc.ts b/src/vs/platform/log/common/logIpc.ts new file mode 100644 index 00000000000..b792dc83329 --- /dev/null +++ b/src/vs/platform/log/common/logIpc.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { LogLevel, ILogService, DelegatedLogService } from 'vs/platform/log/common/log'; +import Event, { buffer } from 'vs/base/common/event'; + +export interface ILogLevelSetterChannel extends IChannel { + call(command: 'event:onDidChangeLogLevel'): TPromise; + call(command: 'setLevel', logLevel: LogLevel): TPromise; +} + +export class LogLevelSetterChannel implements ILogLevelSetterChannel { + + onDidChangeLogLevel: Event; + + constructor(private service: ILogService) { + this.onDidChangeLogLevel = buffer(service.onDidChangeLogLevel, true); + } + + call(command: string, arg?: any): TPromise { + switch (command) { + case 'event:onDidChangeLogLevel': return eventToCall(this.onDidChangeLogLevel); + case 'setLevel': this.service.setLevel(arg); return TPromise.as(null); + } + return undefined; + } +} + +export class LogLevelSetterChannelClient { + + constructor(private channel: ILogLevelSetterChannel) { } + + private _onDidChangeLogLevel = eventFromCall(this.channel, 'event:onDidChangeLogLevel'); + get onDidChangeLogLevel(): Event { return this._onDidChangeLogLevel; } + + setLevel(level: LogLevel): TPromise { + return this.channel.call('setLevel', level); + } +} + +export class FollowerLogService extends DelegatedLogService implements ILogService { + _serviceBrand: any; + + constructor(private master: LogLevelSetterChannelClient, logService: ILogService) { + super(logService); + this._register(master.onDidChangeLogLevel(level => logService.setLevel(level))); + } + + setLevel(level: LogLevel): void { + this.master.setLevel(level); + } +} \ No newline at end of file diff --git a/src/vs/platform/log/node/spdlogService.ts b/src/vs/platform/log/node/spdlogService.ts index 6493d6e1c8d..4f096a1c70c 100644 --- a/src/vs/platform/log/node/spdlogService.ts +++ b/src/vs/platform/log/node/spdlogService.ts @@ -6,69 +6,61 @@ 'use strict'; import * as path from 'path'; -import { ILogService, LogLevel, NullLogService } from 'vs/platform/log/common/log'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILogService, LogLevel, NullLogService, AbstractLogService } from 'vs/platform/log/common/log'; import { RotatingLogger, setAsyncMode } from 'spdlog'; -export function createSpdLogService(processName: string, environmentService: IEnvironmentService, logsSubfolder?: string): ILogService { +export function createSpdLogService(processName: string, logLevel: LogLevel, logsFolder: string): ILogService { try { setAsyncMode(8192, 2000); - const logsDirPath = logsSubfolder ? path.join(environmentService.logsPath, logsSubfolder) : environmentService.logsPath; - const logfilePath = path.join(logsDirPath, `${processName}.log`); + const logfilePath = path.join(logsFolder, `${processName}.log`); const logger = new RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6); logger.setLevel(0); - return new SpdLogService(logger, environmentService.logLevel); + return new SpdLogService(logger, logLevel); } catch (e) { console.error(e); } return new NullLogService(); } -class SpdLogService implements ILogService { +class SpdLogService extends AbstractLogService implements ILogService { _serviceBrand: any; constructor( private readonly logger: RotatingLogger, - private level: LogLevel = LogLevel.Error + level: LogLevel = LogLevel.Error ) { - } - - setLevel(logLevel: LogLevel): void { - this.level = logLevel; - } - - getLevel(): LogLevel { - return this.level; + super(); + this.setLevel(level); } trace(): void { - if (this.level <= LogLevel.Trace) { + if (this.getLevel() <= LogLevel.Trace) { this.logger.trace(this.format(arguments)); } } debug(): void { - if (this.level <= LogLevel.Debug) { + if (this.getLevel() <= LogLevel.Debug) { this.logger.debug(this.format(arguments)); } } info(): void { - if (this.level <= LogLevel.Info) { + if (this.getLevel() <= LogLevel.Info) { this.logger.info(this.format(arguments)); } } warn(): void { - if (this.level <= LogLevel.Warning) { + if (this.getLevel() <= LogLevel.Warning) { this.logger.warn(this.format(arguments)); } } error(): void { - if (this.level <= LogLevel.Error) { + if (this.getLevel() <= LogLevel.Error) { const arg = arguments[0]; if (arg instanceof Error) { @@ -82,7 +74,7 @@ class SpdLogService implements ILogService { } critical(): void { - if (this.level <= LogLevel.Critical) { + if (this.getLevel() <= LogLevel.Critical) { this.logger.critical(this.format(arguments)); } } diff --git a/src/vs/platform/markers/common/problemMatcher.ts b/src/vs/platform/markers/common/problemMatcher.ts index 7268756d769..e6dd0d5bdbe 100644 --- a/src/vs/platform/markers/common/problemMatcher.ts +++ b/src/vs/platform/markers/common/problemMatcher.ts @@ -245,24 +245,28 @@ abstract class AbstractLineMatcher implements ILineMatcher { } protected getMarkerMatch(data: ProblemData): ProblemMatch { - let location = this.getLocation(data); - if (data.file && location && data.message) { - let marker: IMarkerData = { - severity: this.getSeverity(data), - startLineNumber: location.startLineNumber, - startColumn: location.startCharacter, - endLineNumber: location.startLineNumber, - endColumn: location.endCharacter, - message: data.message - }; - if (!Types.isUndefined(data.code)) { - marker.code = data.code; + try { + let location = this.getLocation(data); + if (data.file && location && data.message) { + let marker: IMarkerData = { + severity: this.getSeverity(data), + startLineNumber: location.startLineNumber, + startColumn: location.startCharacter, + endLineNumber: location.startLineNumber, + endColumn: location.endCharacter, + message: data.message + }; + if (!Types.isUndefined(data.code)) { + marker.code = data.code; + } + return { + description: this.matcher, + resource: this.getResource(data.file), + marker: marker + }; } - return { - description: this.matcher, - resource: this.getResource(data.file), - marker: marker - }; + } catch (err) { + console.error(`Failed to convert problem data into match: ${JSON.stringify(data)}`); } return undefined; } diff --git a/src/vs/platform/node/product.ts b/src/vs/platform/node/product.ts index 00a76d6fc38..ebd1d8e22a4 100644 --- a/src/vs/platform/node/product.ts +++ b/src/vs/platform/node/product.ts @@ -25,6 +25,7 @@ export interface IProductConfiguration { extensionsGallery: { serviceUrl: string; itemUrl: string; + controlUrl: string; }; extensionTips: { [id: string]: string; }; extensionImportantTips: { [id: string]: { name: string; pattern: string; }; }; diff --git a/src/vs/platform/progress/common/progress.ts b/src/vs/platform/progress/common/progress.ts index 75addbff74d..100276698ea 100644 --- a/src/vs/platform/progress/common/progress.ts +++ b/src/vs/platform/progress/common/progress.ts @@ -31,6 +31,12 @@ export interface IProgressRunner { done(): void; } +export const emptyProgressRunner: IProgressRunner = Object.freeze({ + total() { }, + worked() { }, + done() { } +}); + export interface IProgress { report(item: T): void; } @@ -58,7 +64,8 @@ export class Progress implements IProgress { export enum ProgressLocation { Scm = 1, - Window = 10, + Extensions = 2, + Window = 10 } export interface IProgressOptions { diff --git a/src/vs/platform/request/electron-browser/requestService.ts b/src/vs/platform/request/electron-browser/requestService.ts index 513ab815132..27bb2bba0c2 100644 --- a/src/vs/platform/request/electron-browser/requestService.ts +++ b/src/vs/platform/request/electron-browser/requestService.ts @@ -51,7 +51,7 @@ export const xhrRequest: IRequestFunction = (options: IRequestOptions): TPromise setRequestHeaders(xhr, options); xhr.responseType = 'arraybuffer'; - xhr.onerror = e => reject(new Error('XHR failed: ' + xhr.statusText)); + xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText))); xhr.onload = (e) => { resolve({ res: { diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts index 3090197c532..7fb3992feb1 100644 --- a/src/vs/platform/search/common/search.ts +++ b/src/vs/platform/search/common/search.ts @@ -112,13 +112,10 @@ export interface ILineMatch { export interface IProgress { total?: number; worked?: number; -} - -export interface ISearchLog { message?: string; } -export interface ISearchProgressItem extends IFileMatch, IProgress, ISearchLog { +export interface ISearchProgressItem extends IFileMatch, IProgress { // Marker interface to indicate the possible values for progress calls from the engine } diff --git a/src/vs/platform/storage/common/storageService.ts b/src/vs/platform/storage/common/storageService.ts index f891309651f..7cf9aa4f4ba 100644 --- a/src/vs/platform/storage/common/storageService.ts +++ b/src/vs/platform/storage/common/storageService.ts @@ -8,6 +8,7 @@ import types = require('vs/base/common/types'); import errors = require('vs/base/common/errors'); import strings = require('vs/base/common/strings'); import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import * as perf from 'vs/base/common/performance'; // Browser localStorage interface export interface IStorage { @@ -89,7 +90,9 @@ export class StorageService implements IStorageService { private cleanupWorkspaceScope(workspaceUid: number): void { // Get stored identifier from storage + perf.mark('willReadWorkspaceIdentifier'); const id = this.getInteger(StorageService.WORKSPACE_IDENTIFIER, StorageScope.WORKSPACE); + perf.mark('didReadWorkspaceIdentifier'); // If identifier differs, assume the workspace got recreated and thus clean all storage for this workspace if (types.isNumber(id) && workspaceUid !== id) { diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 41c3db8d63f..73b4bcf93cb 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -75,6 +75,7 @@ const configurationValueWhitelist = [ 'editor.roundedSelection', 'editor.scrollBeyondLastLine', 'editor.minimap.enabled', + 'editor.minimap.side', 'editor.minimap.renderCharacters', 'editor.minimap.maxColumn', 'editor.find.seedSearchStringFromSelection', @@ -97,6 +98,7 @@ const configurationValueWhitelist = [ 'editor.snippetSuggestions', 'editor.emptySelectionClipboard', 'editor.wordBasedSuggestions', + 'editor.selectSuggestions', 'editor.suggestFontSize', 'editor.suggestLineHeight', 'editor.selectionHighlight', diff --git a/src/vs/platform/telemetry/node/commonProperties.ts b/src/vs/platform/telemetry/node/commonProperties.ts index 0d232325091..c0e152aa53c 100644 --- a/src/vs/platform/telemetry/node/commonProperties.ts +++ b/src/vs/platform/telemetry/node/commonProperties.ts @@ -19,8 +19,10 @@ export function resolveCommonProperties(commit: string, version: string, machine result['commitHash'] = commit; // __GDPR__COMMON__ "version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } result['version'] = version; + // __GDPR__COMMON__ "common.platformVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + result['common.platformVersion'] = (os.release() || '').replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, '$1$2$3'); // __GDPR__COMMON__ "common.osVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - result['common.osVersion'] = os.release(); + result['common.osVersion'] = result['common.platformVersion']; // TODO: Drop this after the move to Nova // __GDPR__COMMON__ "common.platform" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } result['common.platform'] = Platform.Platform[Platform.platform]; // __GDPR__COMMON__ "common.nodePlatform" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } diff --git a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts index 41a7901dffb..a7688ef16ba 100644 --- a/src/vs/platform/telemetry/node/workbenchCommonProperties.ts +++ b/src/vs/platform/telemetry/node/workbenchCommonProperties.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as os from 'os'; import { TPromise } from 'vs/base/common/winjs.base'; import * as uuid from 'vs/base/common/uuid'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -15,8 +14,6 @@ export function resolveWorkbenchCommonProperties(storageService: IStorageService result['common.version.shell'] = process.versions && (process).versions['electron']; // __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } result['common.version.renderer'] = process.versions && (process).versions['chrome']; - // __GDPR__COMMON__ "common.osVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - result['common.osVersion'] = os.release(); const lastSessionDate = storageService.get('telemetry.lastSessionDate'); const firstSessionDate = storageService.get('telemetry.firstSessionDate') || new Date().toUTCString(); diff --git a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts index 725718f20bc..fb89055b500 100644 --- a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts @@ -49,6 +49,7 @@ suite('Telemetry - common properties', function () { // assert.ok('common.version.shell' in first.data); // only when running on electron // assert.ok('common.version.renderer' in first.data); assert.ok('common.osVersion' in props, 'osVersion'); + assert.ok('common.platformVersion' in props, 'platformVersion'); assert.ok('version' in props); assert.equal(props['common.source'], 'my.install.source'); diff --git a/src/vs/platform/update/common/update.ts b/src/vs/platform/update/common/update.ts index 13928e33f17..8ce018cb411 100644 --- a/src/vs/platform/update/common/update.ts +++ b/src/vs/platform/update/common/update.ts @@ -9,35 +9,71 @@ import Event, { NodeEventEmitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; -export enum State { - Uninitialized, - Idle, - CheckingForUpdate, - UpdateAvailable, - UpdateDownloaded -} - -export enum ExplicitState { - Implicit, - Explicit -} - -export interface IRawUpdate { - releaseNotes: string; - version: string; - date: Date; -} - export interface IUpdate { version: string; + productVersion: string; date?: Date; releaseNotes?: string; + supportsFastUpdate?: boolean; url?: string; + hash?: string; } +/** + * Updates are run as a state machine: + * + * Uninitialized + * ↓ + * Idle + * ↓ ↑ + * Checking for Updates → Available for Download + * ↓ + * Downloading → Ready + * ↓ ↑ + * Downloaded → Updating + * + * Available: There is an update available for download (linux). + * Ready: Code will be updated as soon as it restarts (win32, darwin). + * Donwloaded: There is an update ready to be installed in the background (win32). + */ + +export enum StateType { + Uninitialized = 'uninitialized', + Idle = 'idle', + CheckingForUpdates = 'checking for updates', + AvailableForDownload = 'available for download', + Downloading = 'downloading', + Downloaded = 'downloaded', + Updating = 'updating', + Ready = 'ready', +} + +export type Uninitialized = { type: StateType.Uninitialized }; +export type Idle = { type: StateType.Idle }; +export type CheckingForUpdates = { type: StateType.CheckingForUpdates, explicit: boolean }; +export type AvailableForDownload = { type: StateType.AvailableForDownload, update: IUpdate }; +export type Downloading = { type: StateType.Downloading, update: IUpdate }; +export type Downloaded = { type: StateType.Downloaded, update: IUpdate }; +export type Updating = { type: StateType.Updating, update: IUpdate }; +export type Ready = { type: StateType.Ready, update: IUpdate }; + +export type State = Uninitialized | Idle | CheckingForUpdates | AvailableForDownload | Downloading | Downloaded | Updating | Ready; + +export const State = { + Uninitialized: { type: StateType.Uninitialized } as Uninitialized, + Idle: { type: StateType.Idle } as Idle, + CheckingForUpdates: (explicit: boolean) => ({ type: StateType.CheckingForUpdates, explicit } as CheckingForUpdates), + AvailableForDownload: (update: IUpdate) => ({ type: StateType.AvailableForDownload, update } as AvailableForDownload), + Downloading: (update: IUpdate) => ({ type: StateType.Downloading, update } as Downloading), + Downloaded: (update: IUpdate) => ({ type: StateType.Downloaded, update } as Downloaded), + Updating: (update: IUpdate) => ({ type: StateType.Updating, update } as Updating), + Ready: (update: IUpdate) => ({ type: StateType.Ready, update } as Ready), +}; + export interface IAutoUpdater extends NodeEventEmitter { setFeedURL(url: string): void; checkForUpdates(): void; + applyUpdate?(): TPromise; quitAndInstall(): void; } @@ -46,13 +82,11 @@ export const IUpdateService = createDecorator('updateService'); export interface IUpdateService { _serviceBrand: any; - readonly onError: Event; - readonly onUpdateAvailable: Event<{ url: string; version: string; }>; - readonly onUpdateNotAvailable: Event; - readonly onUpdateReady: Event; readonly onStateChange: Event; readonly state: State; - checkForUpdates(explicit: boolean): TPromise; + checkForUpdates(explicit: boolean): TPromise; + downloadUpdate(): TPromise; + applyUpdate(): TPromise; quitAndInstall(): TPromise; } \ No newline at end of file diff --git a/src/vs/platform/update/common/updateIpc.ts b/src/vs/platform/update/common/updateIpc.ts index bd42c38e018..441bdd138e1 100644 --- a/src/vs/platform/update/common/updateIpc.ts +++ b/src/vs/platform/update/common/updateIpc.ts @@ -9,15 +9,12 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; import Event, { Emitter } from 'vs/base/common/event'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { IUpdateService, IRawUpdate, State, IUpdate } from './update'; +import { IUpdateService, State } from './update'; export interface IUpdateChannel extends IChannel { - call(command: 'event:onError'): TPromise; - call(command: 'event:onUpdateAvailable'): TPromise; - call(command: 'event:onUpdateNotAvailable'): TPromise; - call(command: 'event:onUpdateReady'): TPromise; - call(command: 'event:onStateChange'): TPromise; - call(command: 'checkForUpdates', arg: boolean): TPromise; + call(command: 'checkForUpdates', arg: boolean): TPromise; + call(command: 'downloadUpdate'): TPromise; + call(command: 'applyUpdate'): TPromise; call(command: 'quitAndInstall'): TPromise; call(command: '_getInitialState'): TPromise; call(command: string, arg?: any): TPromise; @@ -29,12 +26,10 @@ export class UpdateChannel implements IUpdateChannel { call(command: string, arg?: any): TPromise { switch (command) { - case 'event:onError': return eventToCall(this.service.onError); - case 'event:onUpdateAvailable': return eventToCall(this.service.onUpdateAvailable); - case 'event:onUpdateNotAvailable': return eventToCall(this.service.onUpdateNotAvailable); - case 'event:onUpdateReady': return eventToCall(this.service.onUpdateReady); case 'event:onStateChange': return eventToCall(this.service.onStateChange); case 'checkForUpdates': return this.service.checkForUpdates(arg); + case 'downloadUpdate': return this.service.downloadUpdate(); + case 'applyUpdate': return this.service.applyUpdate(); case 'quitAndInstall': return this.service.quitAndInstall(); case '_getInitialState': return TPromise.as(this.service.state); } @@ -46,19 +41,8 @@ export class UpdateChannelClient implements IUpdateService { _serviceBrand: any; - private _onError = eventFromCall(this.channel, 'event:onError'); - get onError(): Event { return this._onError; } - - private _onUpdateAvailable = eventFromCall<{ url: string; version: string; }>(this.channel, 'event:onUpdateAvailable'); - get onUpdateAvailable(): Event<{ url: string; version: string; }> { return this._onUpdateAvailable; } - - private _onUpdateNotAvailable = eventFromCall(this.channel, 'event:onUpdateNotAvailable'); - get onUpdateNotAvailable(): Event { return this._onUpdateNotAvailable; } - - private _onUpdateReady = eventFromCall(this.channel, 'event:onUpdateReady'); - get onUpdateReady(): Event { return this._onUpdateReady; } - private _onRemoteStateChange = eventFromCall(this.channel, 'event:onStateChange'); + private _onStateChange = new Emitter(); get onStateChange(): Event { return this._onStateChange.event; } @@ -78,10 +62,18 @@ export class UpdateChannelClient implements IUpdateService { }, onUnexpectedError); } - checkForUpdates(explicit: boolean): TPromise { + checkForUpdates(explicit: boolean): TPromise { return this.channel.call('checkForUpdates', explicit); } + downloadUpdate(): TPromise { + return this.channel.call('downloadUpdate'); + } + + applyUpdate(): TPromise { + return this.channel.call('applyUpdate'); + } + quitAndInstall(): TPromise { return this.channel.call('quitAndInstall'); } diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts new file mode 100644 index 00000000000..04e3ccdfeb3 --- /dev/null +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -0,0 +1,162 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import Event, { Emitter } from 'vs/base/common/event'; +import { Throttler } from 'vs/base/common/async'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; +import product from 'vs/platform/node/product'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IUpdateService, State, StateType, AvailableForDownload } from 'vs/platform/update/common/update'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILogService } from 'vs/platform/log/common/log'; + +export function createUpdateURL(platform: string, quality: string): string { + return `${product.updateUrl}/api/update/${platform}/${quality}/${product.commit}`; +} + +export abstract class AbstractUpdateService implements IUpdateService { + + _serviceBrand: any; + + private _state: State = State.Uninitialized; + private throttler: Throttler = new Throttler(); + + private _onStateChange = new Emitter(); + get onStateChange(): Event { return this._onStateChange.event; } + + get state(): State { + return this._state; + } + + protected setState(state: State): void { + this.logService.info('update#setState', state.type); + this._state = state; + this._onStateChange.fire(state); + } + + constructor( + @ILifecycleService private lifecycleService: ILifecycleService, + @IConfigurationService protected configurationService: IConfigurationService, + @IEnvironmentService private environmentService: IEnvironmentService, + @ILogService protected logService: ILogService + ) { + if (this.environmentService.disableUpdates) { + this.logService.info('update#ctor - updates are disabled'); + return; + } + + if (!product.updateUrl || !product.commit) { + this.logService.info('update#ctor - updates are disabled'); + return; + } + + const quality = this.getProductQuality(); + + if (!quality) { + this.logService.info('update#ctor - updates are disabled'); + return; + } + + if (!this.setUpdateFeedUrl(quality)) { + this.logService.info('update#ctor - updates are disabled'); + return; + } + + this.setState({ type: StateType.Idle }); + + // Start checking for updates after 30 seconds + this.scheduleCheckForUpdates(30 * 1000) + .done(null, err => this.logService.error(err)); + } + + private getProductQuality(): string { + const quality = this.configurationService.getValue('update.channel'); + return quality === 'none' ? null : product.quality; + } + + private scheduleCheckForUpdates(delay = 60 * 60 * 1000): TPromise { + return TPromise.timeout(delay) + .then(() => this.checkForUpdates()) + .then(update => { + if (update) { + // Update found, no need to check more + return TPromise.as(null); + } + + // Check again after 1 hour + return this.scheduleCheckForUpdates(60 * 60 * 1000); + }); + } + + checkForUpdates(explicit = false): TPromise { + this.logService.trace('update#checkForUpdates, state = ', this.state.type); + + if (this.state.type !== StateType.Idle) { + return TPromise.as(null); + } + + return this.throttler.queue(() => TPromise.as(this.doCheckForUpdates(explicit))); + } + + downloadUpdate(): TPromise { + this.logService.trace('update#downloadUpdate, state = ', this.state.type); + + if (this.state.type !== StateType.AvailableForDownload) { + return TPromise.as(null); + } + + return this.doDownloadUpdate(this.state); + } + + protected doDownloadUpdate(state: AvailableForDownload): TPromise { + return TPromise.as(null); + } + + applyUpdate(): TPromise { + this.logService.trace('update#applyUpdate, state = ', this.state.type); + + if (this.state.type !== StateType.Downloaded) { + return TPromise.as(null); + } + + return this.doApplyUpdate(); + } + + protected doApplyUpdate(): TPromise { + return TPromise.as(null); + } + + quitAndInstall(): TPromise { + this.logService.trace('update#quitAndInstall, state = ', this.state.type); + + if (this.state.type !== StateType.Ready) { + return TPromise.as(null); + } + + this.logService.trace('update#quitAndInstall(): before lifecycle quit()'); + + this.lifecycleService.quit(true /* from update */).done(vetod => { + this.logService.trace(`update#quitAndInstall(): after lifecycle quit() with veto: ${vetod}`); + if (vetod) { + return; + } + + this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); + this.doQuitAndInstall(); + }); + + return TPromise.as(null); + } + + protected doQuitAndInstall(): void { + // noop + } + + protected abstract setUpdateFeedUrl(quality: string): boolean; + protected abstract doCheckForUpdates(explicit: boolean): void; +} diff --git a/src/vs/platform/update/electron-main/auto-updater.linux.ts b/src/vs/platform/update/electron-main/auto-updater.linux.ts deleted file mode 100644 index bdc9c183329..00000000000 --- a/src/vs/platform/update/electron-main/auto-updater.linux.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import { EventEmitter } from 'events'; -import { isString } from 'vs/base/common/types'; -import { Promise } from 'vs/base/common/winjs.base'; -import { asJson } from 'vs/base/node/request'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { IAutoUpdater } from 'vs/platform/update/common/update'; -import product from 'vs/platform/node/product'; - -interface IUpdate { - url: string; - name: string; - releaseNotes?: string; - version: string; - productVersion: string; - hash: string; -} - -export class LinuxAutoUpdaterImpl extends EventEmitter implements IAutoUpdater { - - private url: string; - private currentRequest: Promise; - - constructor( - @IRequestService private requestService: IRequestService - ) { - super(); - - this.url = null; - this.currentRequest = null; - } - - setFeedURL(url: string): void { - this.url = url; - } - - checkForUpdates(): void { - if (!this.url) { - throw new Error('No feed url set.'); - } - - if (this.currentRequest) { - return; - } - - this.emit('checking-for-update'); - - this.currentRequest = this.requestService.request({ url: this.url }) - .then(asJson) - .then(update => { - if (!update || !update.url || !update.version || !update.productVersion) { - this.emit('update-not-available'); - } else { - this.emit('update-available', null, product.downloadUrl, update.productVersion); - } - }) - .then(null, e => { - if (isString(e) && /^Server returned/.test(e)) { - return; - } - - this.emit('update-not-available'); - this.emit('error', e); - }) - .then(() => this.currentRequest = null); - } - - quitAndInstall(): void { - // noop - } -} diff --git a/src/vs/platform/update/electron-main/auto-updater.win32.ts b/src/vs/platform/update/electron-main/auto-updater.win32.ts deleted file mode 100644 index c88880617f3..00000000000 --- a/src/vs/platform/update/electron-main/auto-updater.win32.ts +++ /dev/null @@ -1,139 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as path from 'path'; -import * as pfs from 'vs/base/node/pfs'; -import { checksum } from 'vs/base/node/crypto'; -import { EventEmitter } from 'events'; -import { tmpdir } from 'os'; -import { spawn } from 'child_process'; -import { isString } from 'vs/base/common/types'; -import { Promise, TPromise } from 'vs/base/common/winjs.base'; -import { download, asJson } from 'vs/base/node/request'; -import { IRequestService } from 'vs/platform/request/node/request'; -import { IAutoUpdater } from 'vs/platform/update/common/update'; -import product from 'vs/platform/node/product'; - -interface IUpdate { - url: string; - name: string; - releaseNotes?: string; - version: string; - productVersion: string; - hash: string; -} - -export class Win32AutoUpdaterImpl extends EventEmitter implements IAutoUpdater { - - private url: string = null; - private currentRequest: Promise = null; - private updatePackagePath: string = null; - - constructor( - @IRequestService private requestService: IRequestService - ) { - super(); - } - - get cachePath(): TPromise { - const result = path.join(tmpdir(), `vscode-update-${process.arch}`); - return pfs.mkdirp(result, null).then(() => result); - } - - setFeedURL(url: string): void { - this.url = url; - } - - checkForUpdates(): void { - if (!this.url) { - throw new Error('No feed url set.'); - } - - if (this.currentRequest) { - return; - } - - this.emit('checking-for-update'); - - this.currentRequest = this.requestService.request({ url: this.url }) - .then(asJson) - .then(update => { - if (!update || !update.url || !update.version) { - this.emit('update-not-available'); - return this.cleanup(); - } - - this.emit('update-available'); - - return this.cleanup(update.version).then(() => { - return this.getUpdatePackagePath(update.version).then(updatePackagePath => { - return pfs.exists(updatePackagePath).then(exists => { - if (exists) { - return TPromise.as(updatePackagePath); - } - - const url = update.url; - const hash = update.hash; - const downloadPath = `${updatePackagePath}.tmp`; - - return this.requestService.request({ url }) - .then(context => download(downloadPath, context)) - .then(hash ? () => checksum(downloadPath, update.hash) : () => null) - .then(() => pfs.rename(downloadPath, updatePackagePath)) - .then(() => updatePackagePath); - }); - }).then(updatePackagePath => { - this.updatePackagePath = updatePackagePath; - - this.emit('update-downloaded', - {}, - update.releaseNotes, - update.productVersion, - new Date(), - this.url - ); - }); - }); - }) - .then(null, e => { - if (isString(e) && /^Server returned/.test(e)) { - return; - } - - this.emit('update-not-available'); - this.emit('error', e); - }) - .then(() => this.currentRequest = null); - } - - private getUpdatePackagePath(version: string): TPromise { - return this.cachePath.then(cachePath => path.join(cachePath, `CodeSetup-${product.quality}-${version}.exe`)); - } - - private cleanup(exceptVersion: string = null): Promise { - const filter = exceptVersion ? one => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true; - - return this.cachePath - .then(cachePath => pfs.readdir(cachePath) - .then(all => Promise.join(all - .filter(filter) - .map(one => pfs.unlink(path.join(cachePath, one)).then(null, () => null)) - )) - ); - } - - quitAndInstall(): void { - if (!this.updatePackagePath) { - return; - } - - spawn(this.updatePackagePath, ['/silent', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], { - detached: true, - stdio: ['ignore', 'ignore', 'ignore'] - }); - } -} diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts new file mode 100644 index 00000000000..25d9cf28beb --- /dev/null +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as electron from 'electron'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import Event, { fromNodeEventEmitter } from 'vs/base/common/event'; +import { memoize } from 'vs/base/common/decorators'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; +import { State, IUpdate, StateType } from 'vs/platform/update/common/update'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILogService } from 'vs/platform/log/common/log'; +import { AbstractUpdateService, createUpdateURL } from 'vs/platform/update/electron-main/abstractUpdateService'; + +export class DarwinUpdateService extends AbstractUpdateService { + + _serviceBrand: any; + + private disposables: IDisposable[] = []; + + @memoize private get onRawError(): Event { return fromNodeEventEmitter(electron.autoUpdater, 'error', (_, message) => message); } + @memoize private get onRawUpdateNotAvailable(): Event { return fromNodeEventEmitter(electron.autoUpdater, 'update-not-available'); } + @memoize private get onRawUpdateAvailable(): Event { return fromNodeEventEmitter(electron.autoUpdater, 'update-available', (_, url, version) => ({ url, version, productVersion: version })); } + @memoize private get onRawUpdateDownloaded(): Event { return fromNodeEventEmitter(electron.autoUpdater, 'update-downloaded', (_, releaseNotes, version, date) => ({ releaseNotes, version, productVersion: version, date })); } + + constructor( + @ILifecycleService lifecycleService: ILifecycleService, + @IConfigurationService configurationService: IConfigurationService, + @ITelemetryService private telemetryService: ITelemetryService, + @IEnvironmentService environmentService: IEnvironmentService, + @ILogService logService: ILogService + ) { + super(lifecycleService, configurationService, environmentService, logService); + this.onRawError(this.onError, this, this.disposables); + this.onRawUpdateAvailable(this.onUpdateAvailable, this, this.disposables); + this.onRawUpdateDownloaded(this.onUpdateDownloaded, this, this.disposables); + this.onRawUpdateNotAvailable(this.onUpdateNotAvailable, this, this.disposables); + } + + private onError(err: string): void { + this.logService.error('UpdateService error: ', err); + this.setState(State.Idle); + } + + protected setUpdateFeedUrl(quality: string): boolean { + try { + electron.autoUpdater.setFeedURL(createUpdateURL('darwin', quality)); + } catch (e) { + // application is very likely not signed + this.logService.error('Failed to set update feed URL'); + return false; + } + + return true; + } + + protected doCheckForUpdates(explicit: boolean): void { + this.setState(State.CheckingForUpdates(explicit)); + electron.autoUpdater.checkForUpdates(); + } + + private onUpdateAvailable(update: IUpdate): void { + if (this.state.type !== StateType.CheckingForUpdates) { + return; + } + + this.setState(State.Downloading(update)); + } + + private onUpdateDownloaded(update: IUpdate): void { + if (this.state.type !== StateType.Downloading) { + return; + } + + /* __GDPR__ + "update:downloaded" : { + "version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:downloaded', { version: update.version }); + + this.setState(State.Ready(update)); + } + + private onUpdateNotAvailable(): void { + if (this.state.type !== StateType.CheckingForUpdates) { + return; + } + + /* __GDPR__ + "update:notAvailable" : { + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:notAvailable', { explicit: this.state.explicit }); + + this.setState(State.Idle); + } + + protected doQuitAndInstall(): void { + // for some reason updating on Mac causes the local storage not to be flushed. + // we workaround this issue by forcing an explicit flush of the storage data. + // see also https://github.com/Microsoft/vscode/issues/172 + this.logService.trace('update#quitAndInstall(): calling flushStorageData()'); + electron.session.defaultSession.flushStorageData(); + + this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); + electron.autoUpdater.quitAndInstall(); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} diff --git a/src/vs/platform/update/electron-main/updateService.linux.ts b/src/vs/platform/update/electron-main/updateService.linux.ts new file mode 100644 index 00000000000..cb36c658585 --- /dev/null +++ b/src/vs/platform/update/electron-main/updateService.linux.ts @@ -0,0 +1,84 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; +import { IRequestService } from 'vs/platform/request/node/request'; +import { State, IUpdate, AvailableForDownload } from 'vs/platform/update/common/update'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILogService } from 'vs/platform/log/common/log'; +import { createUpdateURL, AbstractUpdateService } from 'vs/platform/update/electron-main/abstractUpdateService'; +import { asJson } from 'vs/base/node/request'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { shell } from 'electron'; + +export class LinuxUpdateService extends AbstractUpdateService { + + _serviceBrand: any; + + private url: string | undefined; + + constructor( + @ILifecycleService lifecycleService: ILifecycleService, + @IConfigurationService configurationService: IConfigurationService, + @ITelemetryService private telemetryService: ITelemetryService, + @IEnvironmentService environmentService: IEnvironmentService, + @IRequestService private requestService: IRequestService, + @ILogService logService: ILogService + ) { + super(lifecycleService, configurationService, environmentService, logService); + } + + protected setUpdateFeedUrl(quality: string): boolean { + this.url = createUpdateURL(`linux-${process.arch}`, quality); + return true; + } + + protected doCheckForUpdates(explicit: boolean): void { + if (!this.url) { + return; + } + + this.setState(State.CheckingForUpdates(explicit)); + + this.requestService.request({ url: this.url }) + .then(asJson) + .then(update => { + if (!update || !update.url || !update.version || !update.productVersion) { + /* __GDPR__ + "update:notAvailable" : { + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:notAvailable', { explicit }); + + this.setState(State.Idle); + } else { + this.setState(State.AvailableForDownload(update)); + } + }) + .then(null, err => { + this.logService.error(err); + + /* __GDPR__ + "update:notAvailable" : { + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:notAvailable', { explicit }); + this.setState(State.Idle); + }); + } + + protected doDownloadUpdate(state: AvailableForDownload): TPromise { + shell.openExternal(state.update.url); + this.setState(State.Idle); + + return TPromise.as(null); + } +} diff --git a/src/vs/platform/update/electron-main/updateService.ts b/src/vs/platform/update/electron-main/updateService.ts deleted file mode 100644 index b7f8f5edf69..00000000000 --- a/src/vs/platform/update/electron-main/updateService.ts +++ /dev/null @@ -1,295 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as fs from 'original-fs'; -import * as path from 'path'; -import * as electron from 'electron'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import Event, { Emitter, once, filterEvent, fromNodeEventEmitter } from 'vs/base/common/event'; -import { always, Throttler } from 'vs/base/common/async'; -import { memoize } from 'vs/base/common/decorators'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { Win32AutoUpdaterImpl } from './auto-updater.win32'; -import { LinuxAutoUpdaterImpl } from './auto-updater.linux'; -import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; -import { IRequestService } from 'vs/platform/request/node/request'; -import product from 'vs/platform/node/product'; -import { TPromise } from 'vs/base/common/winjs.base'; -import { IUpdateService, State, IAutoUpdater, IUpdate, IRawUpdate } from 'vs/platform/update/common/update'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ILogService } from 'vs/platform/log/common/log'; - -export class UpdateService implements IUpdateService { - - _serviceBrand: any; - - private _state: State = State.Uninitialized; - private _availableUpdate: IUpdate = null; - private raw: IAutoUpdater; - private throttler: Throttler = new Throttler(); - - private _onError = new Emitter(); - get onError(): Event { return this._onError.event; } - - private _onCheckForUpdate = new Emitter(); - get onCheckForUpdate(): Event { return this._onCheckForUpdate.event; } - - private _onUpdateAvailable = new Emitter<{ url: string; version: string; }>(); - get onUpdateAvailable(): Event<{ url: string; version: string; }> { return this._onUpdateAvailable.event; } - - private _onUpdateNotAvailable = new Emitter(); - get onUpdateNotAvailable(): Event { return this._onUpdateNotAvailable.event; } - - private _onUpdateReady = new Emitter(); - get onUpdateReady(): Event { return this._onUpdateReady.event; } - - private _onStateChange = new Emitter(); - get onStateChange(): Event { return this._onStateChange.event; } - - @memoize - private get onRawError(): Event { - return fromNodeEventEmitter(this.raw, 'error', (_, message) => message); - } - - @memoize - private get onRawUpdateNotAvailable(): Event { - return fromNodeEventEmitter(this.raw, 'update-not-available'); - } - - @memoize - private get onRawUpdateAvailable(): Event<{ url: string; version: string; }> { - return filterEvent(fromNodeEventEmitter(this.raw, 'update-available', (_, url, version) => ({ url, version })), ({ url }) => !!url); - } - - @memoize - private get onRawUpdateDownloaded(): Event { - return fromNodeEventEmitter(this.raw, 'update-downloaded', (_, releaseNotes, version, date, url) => ({ releaseNotes, version, date })); - } - - get state(): State { - return this._state; - } - - set state(state: State) { - this._state = state; - this._onStateChange.fire(state); - } - - get availableUpdate(): IUpdate { - return this._availableUpdate; - } - - constructor( - @IRequestService requestService: IRequestService, - @ILifecycleService private lifecycleService: ILifecycleService, - @IConfigurationService private configurationService: IConfigurationService, - @ITelemetryService private telemetryService: ITelemetryService, - @IEnvironmentService private environmentService: IEnvironmentService, - @ILogService private logService: ILogService - ) { - if (process.platform === 'win32') { - this.raw = new Win32AutoUpdaterImpl(requestService); - } else if (process.platform === 'linux') { - this.raw = new LinuxAutoUpdaterImpl(requestService); - } else if (process.platform === 'darwin') { - this.raw = electron.autoUpdater; - } else { - return; - } - - if (this.environmentService.disableUpdates) { - return; - } - - const channel = this.getUpdateChannel(); - const feedUrl = this.getUpdateFeedUrl(channel); - - if (!feedUrl) { - return; // updates not available - } - - try { - this.raw.setFeedURL(feedUrl); - } catch (e) { - return; // application not signed - } - - this.state = State.Idle; - - // Start checking for updates after 30 seconds - this.scheduleCheckForUpdates(30 * 1000) - .done(null, err => this.logService.error(err)); - } - - private scheduleCheckForUpdates(delay = 60 * 60 * 1000): TPromise { - return TPromise.timeout(delay) - .then(() => this.checkForUpdates()) - .then(update => { - if (update) { - // Update found, no need to check more - return TPromise.as(null); - } - - // Check again after 1 hour - return this.scheduleCheckForUpdates(60 * 60 * 1000); - }); - } - - checkForUpdates(explicit = false): TPromise { - return this.throttler.queue(() => this._checkForUpdates(explicit)) - .then(null, err => { - if (explicit) { - this._onError.fire(err); - } - - return null; - }); - } - - private _checkForUpdates(explicit: boolean): TPromise { - if (this.state !== State.Idle) { - return TPromise.as(null); - } - - this._onCheckForUpdate.fire(); - this.state = State.CheckingForUpdate; - - const listeners: IDisposable[] = []; - const result = new TPromise((c, e) => { - once(this.onRawError)(e, null, listeners); - once(this.onRawUpdateNotAvailable)(() => c(null), null, listeners); - once(this.onRawUpdateAvailable)(({ url, version }) => url && c({ url, version }), null, listeners); - once(this.onRawUpdateDownloaded)(({ version, date, releaseNotes }) => c({ version, date, releaseNotes }), null, listeners); - - this.raw.checkForUpdates(); - }).then(update => { - if (!update) { - this._onUpdateNotAvailable.fire(explicit); - this.state = State.Idle; - /* __GDPR__ - "update:notAvailable" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('update:notAvailable', { explicit }); - - } else if (update.url) { - const data: IUpdate = { - url: update.url, - releaseNotes: '', - version: update.version, - date: new Date() - }; - - this._availableUpdate = data; - this._onUpdateAvailable.fire({ url: update.url, version: update.version }); - this.state = State.UpdateAvailable; - /* __GDPR__ - "update:available" : { - "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "version": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "currentVersion": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('update:available', { explicit, version: update.version, currentVersion: product.commit }); - - } else { - const data: IRawUpdate = { - releaseNotes: update.releaseNotes, - version: update.version, - date: update.date - }; - - this._availableUpdate = data; - this._onUpdateReady.fire(data); - this.state = State.UpdateDownloaded; - /* __GDPR__ - "update:downloaded" : { - "version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('update:downloaded', { version: update.version }); - } - - return update; - }, err => { - this.state = State.Idle; - return TPromise.wrapError(err); - }); - - return always(result, () => dispose(listeners)); - } - - private getUpdateChannel(): string { - const channel = this.configurationService.getValue('update.channel'); - return channel === 'none' ? null : product.quality; - } - - private getUpdateFeedUrl(channel: string): string { - if (!channel) { - return null; - } - - if (process.platform === 'win32' && !fs.existsSync(path.join(path.dirname(process.execPath), 'unins000.exe'))) { - return null; - } - - if (!product.updateUrl || !product.commit) { - return null; - } - - const platform = this.getUpdatePlatform(); - - return `${product.updateUrl}/api/update/${platform}/${channel}/${product.commit}`; - } - - private getUpdatePlatform(): string { - if (process.platform === 'linux') { - return `linux-${process.arch}`; - } - - if (process.platform === 'win32' && process.arch === 'x64') { - return 'win32-x64'; - } - - return process.platform; - } - - quitAndInstall(): TPromise { - if (!this._availableUpdate) { - return TPromise.as(null); - } - - if (this._availableUpdate.url) { - electron.shell.openExternal(this._availableUpdate.url); - return TPromise.as(null); - } - - this.logService.trace('update#quitAndInstall(): before lifecycle quit()'); - - this.lifecycleService.quit(true /* from update */).done(vetod => { - this.logService.trace(`update#quitAndInstall(): after lifecycle quit() with veto: ${vetod}`); - if (vetod) { - return; - } - - // for some reason updating on Mac causes the local storage not to be flushed. - // we workaround this issue by forcing an explicit flush of the storage data. - // see also https://github.com/Microsoft/vscode/issues/172 - if (process.platform === 'darwin') { - this.logService.trace('update#quitAndInstall(): calling flushStorageData()'); - electron.session.defaultSession.flushStorageData(); - } - - this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); - this.raw.quitAndInstall(); - }); - - return TPromise.as(null); - } -} diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts new file mode 100644 index 00000000000..ef20367626c --- /dev/null +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -0,0 +1,210 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as fs from 'original-fs'; +import * as path from 'path'; +import * as pfs from 'vs/base/node/pfs'; +import { memoize } from 'vs/base/common/decorators'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; +import { IRequestService } from 'vs/platform/request/node/request'; +import product from 'vs/platform/node/product'; +import { TPromise, Promise } from 'vs/base/common/winjs.base'; +import { State, IUpdate, StateType } from 'vs/platform/update/common/update'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ILogService } from 'vs/platform/log/common/log'; +import { createUpdateURL, AbstractUpdateService } from 'vs/platform/update/electron-main/abstractUpdateService'; +import { download, asJson } from 'vs/base/node/request'; +import { checksum } from 'vs/base/node/crypto'; +import { tmpdir } from 'os'; +import { spawn } from 'child_process'; + +function pollUntil(fn: () => boolean, timeout = 1000): TPromise { + return new TPromise(c => { + const poll = () => { + if (fn()) { + c(null); + } else { + setTimeout(poll, timeout); + } + }; + + poll(); + }); +} + +interface IAvailableUpdate { + packagePath: string; + updateFilePath?: string; +} + +export class Win32UpdateService extends AbstractUpdateService { + + _serviceBrand: any; + + private url: string | undefined; + private availableUpdate: IAvailableUpdate | undefined; + + @memoize + get cachePath(): TPromise { + const result = path.join(tmpdir(), `vscode-update-${process.arch}`); + return pfs.mkdirp(result, null).then(() => result); + } + + constructor( + @ILifecycleService lifecycleService: ILifecycleService, + @IConfigurationService configurationService: IConfigurationService, + @ITelemetryService private telemetryService: ITelemetryService, + @IEnvironmentService environmentService: IEnvironmentService, + @IRequestService private requestService: IRequestService, + @ILogService logService: ILogService + ) { + super(lifecycleService, configurationService, environmentService, logService); + } + + protected setUpdateFeedUrl(quality: string): boolean { + if (!fs.existsSync(path.join(path.dirname(process.execPath), 'unins000.exe'))) { + return false; + } + + this.url = createUpdateURL(process.arch === 'x64' ? 'win32-x64' : 'win32', quality); + return true; + } + + protected doCheckForUpdates(explicit: boolean): void { + if (!this.url) { + return; + } + + this.setState(State.CheckingForUpdates(explicit)); + + this.requestService.request({ url: this.url }) + .then(asJson) + .then(update => { + if (!update || !update.url || !update.version) { + /* __GDPR__ + "update:notAvailable" : { + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:notAvailable', { explicit }); + + this.setState(State.Idle); + return TPromise.as(null); + } + + this.setState(State.Downloading(update)); + + return this.cleanup(update.version).then(() => { + return this.getUpdatePackagePath(update.version).then(updatePackagePath => { + return pfs.exists(updatePackagePath).then(exists => { + if (exists) { + return TPromise.as(updatePackagePath); + } + + const url = update.url; + const hash = update.hash; + const downloadPath = `${updatePackagePath}.tmp`; + + return this.requestService.request({ url }) + .then(context => download(downloadPath, context)) + .then(hash ? () => checksum(downloadPath, update.hash) : () => null) + .then(() => pfs.rename(downloadPath, updatePackagePath)) + .then(() => updatePackagePath); + }); + }).then(packagePath => { + const fastUpdatesEnabled = this.configurationService.getValue('update.enableWindowsBackgroundUpdates'); + + this.availableUpdate = { packagePath }; + + if (fastUpdatesEnabled && update.supportsFastUpdate) { + this.setState(State.Downloaded(update)); + } else { + this.setState(State.Ready(update)); + } + }); + }); + }) + .then(null, err => { + this.logService.error(err); + /* __GDPR__ + "update:notAvailable" : { + "explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('update:notAvailable', { explicit }); + this.setState(State.Idle); + }); + } + + private getUpdatePackagePath(version: string): TPromise { + return this.cachePath.then(cachePath => path.join(cachePath, `CodeSetup-${product.quality}-${version}.exe`)); + } + + private cleanup(exceptVersion: string = null): Promise { + const filter = exceptVersion ? one => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true; + + return this.cachePath + .then(cachePath => pfs.readdir(cachePath) + .then(all => Promise.join(all + .filter(filter) + .map(one => pfs.unlink(path.join(cachePath, one)).then(null, () => null)) + )) + ); + } + + protected doApplyUpdate(): TPromise { + if (this.state.type !== StateType.Downloaded || !this.availableUpdate) { + return TPromise.as(null); + } + + const update = this.state.update; + this.setState(State.Updating(update)); + + return this.cachePath.then(cachePath => { + this.availableUpdate.updateFilePath = path.join(cachePath, `CodeSetup-${product.quality}-${update.version}.flag`); + + return pfs.writeFile(this.availableUpdate.updateFilePath, 'flag').then(() => { + const child = spawn(this.availableUpdate.packagePath, ['/verysilent', `/update="${this.availableUpdate.updateFilePath}"`, '/nocloseapplications', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], { + detached: true, + stdio: ['ignore', 'ignore', 'ignore'], + windowsVerbatimArguments: true + }); + + child.once('exit', () => { + this.availableUpdate = undefined; + this.setState(State.Idle); + }); + + const readyMutexName = `${product.win32MutexName}-ready`; + const isActive = (require.__$__nodeRequire('windows-mutex') as any).isActive; + + // poll for mutex-ready + pollUntil(() => isActive(readyMutexName)) + .then(() => this.setState(State.Ready(update))); + }); + }); + } + + protected doQuitAndInstall(): void { + if (this.state.type !== StateType.Ready) { + return; + } + + this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); + + if (this.state.update.supportsFastUpdate && this.availableUpdate.updateFilePath) { + fs.unlinkSync(this.availableUpdate.updateFilePath); + } else { + spawn(this.availableUpdate.packagePath, ['/silent', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], { + detached: true, + stdio: ['ignore', 'ignore', 'ignore'] + }); + } + } +} diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index c20b1900988..3a2cabf156a 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -15,6 +15,7 @@ import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/ import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ICommandAction } from 'vs/platform/actions/common/actions'; import { PerformanceEntry } from 'vs/base/common/performance'; +import { LogLevel } from 'vs/platform/log/common/log'; export const IWindowsService = createDecorator('windowsService'); @@ -297,6 +298,7 @@ export interface IAddFoldersRequest { export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest { machineId: string; windowId: number; + logLevel: LogLevel; appRoot: string; execPath: string; diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index af594644bae..9ba87d62535 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -198,15 +198,15 @@ export class Workspace implements IWorkspace { } public toJSON(): IWorkspace { - return { id: this.id, folders: this.folders, name: this.name }; + return { id: this.id, folders: this.folders, name: this.name, configuration: this.configuration }; } } export class WorkspaceFolder implements IWorkspaceFolder { readonly uri: URI; - readonly name: string; - readonly index: number; + name: string; + index: number; constructor(data: IWorkspaceFolderData, readonly raw?: IStoredWorkspaceFolder) { diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 7031cb06470..ff060086c77 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -48,7 +48,7 @@ suite('WorkspacesMainService', () => { } const environmentService = new TestEnvironmentService(parseArgs(process.argv), process.execPath); - const logService = new ConsoleLogMainService(environmentService); + const logService = new ConsoleLogMainService(); let service: TestWorkspacesMainService; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 8e575269fae..b1ca5266c4f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1812,6 +1812,66 @@ declare module 'vscode' { */ export type ProviderResult = T | undefined | null | Thenable; + /** + * Kind of a code action. + * + * Kinds are a hierarchical list of identifiers separated by `.`, e.g. `"refactor.extract.function"`. + */ + export class CodeActionKind { + /** + * Empty kind. + */ + static readonly Empty: CodeActionKind; + + /** + * Base kind for quickfix actions. + */ + static readonly QuickFix: CodeActionKind; + + /** + * Base kind for refactoring actions. + */ + static readonly Refactor: CodeActionKind; + + /** + * Base kind for refactoring extraction actions. + */ + static readonly RefactorExtract: CodeActionKind; + + /** + * Base kind for refactoring inline actions. + */ + static readonly RefactorInline: CodeActionKind; + + /** + * Base kind for refactoring rewite actions. + */ + static readonly RefactorRewrite: CodeActionKind; + + private constructor(value: string); + + /** + * String value of the kind, e.g. `"refactor.extract.function"`. + */ + readonly value?: string; + + /** + * Create a new kind by appending a more specific selector to the current kind. + * + * Does not modify the current kind. + */ + append(parts: string): CodeActionKind; + + /** + * Does this kind contain `other`? + * + * The kind `"refactor"` for example contains `"refactor.extract"` and ``"refactor.extract.function"`, but not `"unicorn.refactor.extract"` or `"refactory.extract"` + * + * @param other Kind to check. + */ + contains(other: CodeActionKind): boolean; + } + /** * Contains additional diagnostic information about the context in which * a [code action](#CodeActionProvider.provideCodeActions) is run. @@ -1821,6 +1881,13 @@ declare module 'vscode' { * An array of diagnostics. */ readonly diagnostics: Diagnostic[]; + + /** + * Requested kind of actions to return. + * + * Actions not of this kind are filtered out before being shown by the lightbulb. + */ + readonly only?: CodeActionKind; } /** @@ -1830,7 +1897,7 @@ declare module 'vscode' { export class CodeAction { /** - * A short, human-readanle, title for this code action. + * A short, human-readable, title for this code action. */ title: string; @@ -1853,6 +1920,13 @@ declare module 'vscode' { */ command?: Command; + /** + * Kind of the code action. + * + * Used to filter code actions. + */ + kind?: CodeActionKind; + /** * Creates a new code action. * @@ -1860,9 +1934,9 @@ declare module 'vscode' { * or a [command](#CodeAction.command). * * @param title The title of the code action. - * @param edits The edit of the code action. + * @param kind The kind of the code action. */ - constructor(title: string, edit?: WorkspaceEdit); + constructor(title: string, kind?: CodeActionKind); } /** @@ -2421,7 +2495,8 @@ declare module 'vscode' { } /** - * A workspace edit represents textual changes for many documents. + * A workspace edit represents textual and files changes for + * multiple resources and documents. */ export class WorkspaceEdit { @@ -2482,9 +2557,49 @@ declare module 'vscode' { /** * Get all text edits grouped by resource. * - * @return An array of `[Uri, TextEdit[]]`-tuples. + * @return A shallow copy of `[Uri, TextEdit[]]`-tuples. */ entries(): [Uri, TextEdit[]][]; + + /** + * Renames a given resource in the workspace. + * + * @param from Uri of current resource. + * @param to Uri of renamed resource. + */ + renameResource(from: Uri, to: Uri): void; + + /** + * Create a new resource in the workspace. + * + * @param uri Uri of resource to create. + */ + createResource(uri: Uri): void; + + /** + * Delete a given resource in the workspace. + * + * @param uri Uri of resource to delete. + */ + deleteResource(uri: Uri): void; + + /** + * Get the resource edits for this workspace edit. + * + * @returns A shallow copy of uri-tuples in which a rename-edit + * is represented as `[from, to]`, a delete-operation as `[from, null]`, + * and a create-operation as `[null, to]`; + */ + resourceEdits(): [Uri, Uri][]; + + /** + * Get all edits, textual changes and file changes. The order is the order + * in which edits have been added to this workspace edits. Textuals edits + * are grouped and the first textual edit for a resource matters. + * + * @returns A shallow copy of all changes. + */ + allEntries(): ([Uri, TextEdit[]] | [Uri, Uri])[]; } /** diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 51f8b8f5e5d..ef2c05f37c6 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -90,6 +90,11 @@ declare module 'vscode' { isWordMatch?: boolean; } + export interface TextSearchOptions { + includes: GlobPattern[]; + excludes: GlobPattern[]; + } + export interface TextSearchResult { uri: Uri; range: Range; @@ -147,11 +152,51 @@ declare module 'vscode' { // find files by names // todo@joh, move into its own provider findFiles?(query: string, progress: Progress, token: CancellationToken): Thenable; - provideTextSearchResults?(query: TextSearchQuery, include: GlobPattern, exclude: GlobPattern, progress: Progress, token: CancellationToken): Thenable; + provideTextSearchResults?(query: TextSearchQuery, options: TextSearchOptions, progress: Progress, token: CancellationToken): Thenable; } export namespace workspace { export function registerFileSystemProvider(scheme: string, provider: FileSystemProvider): Disposable; + + /** + * Updates the workspace folders of the currently opened workspace. This method allows to add, remove + * and change workspace folders a the same time. Use the [onDidChangeWorkspaceFolders()](#onDidChangeWorkspaceFolders) + * event to get notified when the workspace folders have been updated. + * + * **Example:** adding a new workspace folder at the end of workspace folders + * ```typescript + * workspace.updateWorkspaceFolders(workspace.workspaceFolders ? workspace.workspaceFolders.length : 0, null, { uri: ...}); + * ``` + * + * **Example:** removing the first workspace folder + * ```typescript + * workspace.updateWorkspaceFolders(0, 1); + * ``` + * + * **Example:** replacing an existing workspace folder with a new one + * ```typescript + * workspace.updateWorkspaceFolders(0, 1, { uri: ...}); + * ``` + * + * It is valid to remove an existing workspace folder and add it again with a different name + * to rename that folder. + * + * Note: if the first workspace folder is added, removed or changed, all extensions will be restarted + * so that the (deprecated) `rootPath` property is updated to point to the first workspace + * folder. + * + * Note: it is not valid to call [updateWorkspaceFolders()](#updateWorkspaceFolders) multiple times + * without waiting for the [onDidChangeWorkspaceFolders()](#onDidChangeWorkspaceFolders) to fire. + * + * @param start the zero-based location in the list of currently opened [workspace folders](#WorkspaceFolder) + * from which to start deleting workspace folders. + * @param deleteCount the optional number of workspace folders to remove. + * @param workspaceFoldersToAdd the optional variable set of workspace folders to add in place of the deleted ones. + * Each workspace is identified with a mandatory URI and an optional name. + * @return true if the operation was successfully started and false otherwise if arguments were used that would result + * in invalid workspace folder state (e.g. 2 folders with the same URI). + */ + export function updateWorkspaceFolders(start: number, deleteCount: number, ...workspaceFoldersToAdd: { uri: Uri, name?: string }[]): boolean; } export namespace window { @@ -230,6 +275,18 @@ declare module 'vscode' { * An event that is emitted when a breakpoint is added, removed, or changed. */ export const onDidChangeBreakpoints: Event; + + /** + * Add breakpoints. + * @param breakpoints The breakpoints to add. + */ + export function addBreakpoints(breakpoints: Breakpoint[]): void; + + /** + * Remove breakpoints. + * @param breakpoints The breakpoints to remove. + */ + export function removeBreakpoints(breakpoints: Breakpoint[]): void; } /** @@ -269,7 +326,7 @@ declare module 'vscode' { */ readonly hitCondition?: string; - protected constructor(enabled: boolean, condition: string, hitCondition: string); + protected constructor(enabled?: boolean, condition?: string, hitCondition?: string); } /** @@ -281,7 +338,10 @@ declare module 'vscode' { */ readonly location: Location; - private constructor(enabled: boolean, condition: string, hitCondition: string, location: Location); + /** + * Create a new breakpoint for a source location. + */ + constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string); } /** @@ -293,7 +353,10 @@ declare module 'vscode' { */ readonly functionName: string; - private constructor(enabled: boolean, condition: string, hitCondition: string, functionName: string); + /** + * Create a new function breakpoint. + */ + constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string); } /** diff --git a/src/vs/workbench/api/browser/localizationsExtensionPoint.ts b/src/vs/workbench/api/browser/localizationsExtensionPoint.ts new file mode 100644 index 00000000000..cd92ed0e803 --- /dev/null +++ b/src/vs/workbench/api/browser/localizationsExtensionPoint.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { localize } from 'vs/nls'; +import { IJSONSchema } from 'vs/base/common/jsonSchema'; +import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; + +namespace schema { + + // --localizations contribution point + + export interface ILocalizationDescriptor { + languageId: string; + languageName: string; + translations: string; + } + + export function validateLocalizationDescriptors(localizationDescriptors: ILocalizationDescriptor[], collector: ExtensionMessageCollector): boolean { + if (!Array.isArray(localizationDescriptors)) { + collector.error(localize('requirearray', "localizations must be an array")); + return false; + } + + for (let descriptor of localizationDescriptors) { + if (typeof descriptor.languageId !== 'string') { + collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'languageId')); + return false; + } + if (typeof descriptor.languageName !== 'string') { + collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'languageName')); + return false; + } + if (descriptor.translations && typeof descriptor.translations !== 'string') { + collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'translations')); + return false; + } + } + + return true; + } + + export const localizationsContribution: IJSONSchema = { + description: localize('vscode.extension.contributes.localizations', "Contributes localizations to the editor"), + type: 'array', + items: { + type: 'object', + properties: { + id: { + description: localize('vscode.extension.contributes.localizations.languageId', 'Id of the language into which the display strings are translated.'), + type: 'string' + }, + name: { + description: localize('vscode.extension.contributes.localizations.languageName', 'Name of the language into which the display strings are translated.'), + type: 'string' + }, + translations: { + description: localize('vscode.extension.contributes.localizations.translations', 'A relative path to the folder containing all translation files for the contributed language.'), + type: 'string', + default: 'translations' + } + } + } + }; +} + +ExtensionsRegistry.registerExtensionPoint('localizations', [], schema.localizationsContribution) + .setHandler((extensions) => extensions.forEach(extension => schema.validateLocalizationDescriptors(extension.value, extension.collector))); \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts index 6217b1dadcd..d610ada2b88 100644 --- a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts @@ -46,6 +46,7 @@ import './mainThreadTask'; import './mainThreadTelemetry'; import './mainThreadTerminalService'; import './mainThreadTreeViews'; +import './mainThreadLogService'; import './mainThreadWindow'; import './mainThreadWorkspace'; diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index f43810a894f..46140b8f54b 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -6,10 +6,13 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import uri from 'vs/base/common/uri'; -import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IRawBreakpoint } from 'vs/workbench/parts/debug/common/debug'; import { TPromise } from 'vs/base/common/winjs.base'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, IExtHostContext, IBreakpointsDelta, ISourceBreakpointData, IFunctionBreakpointData } from '../node/extHost.protocol'; +import { + ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, + IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto +} from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import severity from 'vs/base/common/severity'; @@ -59,15 +62,15 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { // set up a handler to send more this._toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(e => { if (e) { - const delta: IBreakpointsDelta = {}; + const delta: IBreakpointsDeltaDto = {}; if (e.added) { - delta.added = this.toWire(e.added); + delta.added = this.convertToDto(e.added); } if (e.removed) { delta.removed = e.removed.map(x => x.getId()); } if (e.changed) { - delta.changed = this.toWire(e.changed); + delta.changed = this.convertToDto(e.changed); } if (delta.added || delta.removed || delta.changed) { @@ -81,7 +84,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { const fbps = this.debugService.getModel().getFunctionBreakpoints(); if (bps.length > 0 || fbps.length > 0) { this._proxy.$acceptBreakpointsDelta({ - added: this.toWire(bps).concat(this.toWire(fbps)) + added: this.convertToDto(bps).concat(this.convertToDto(fbps)) }); } } @@ -89,30 +92,57 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape { return TPromise.wrap(undefined); } - private toWire(bps: (IBreakpoint | IFunctionBreakpoint)[]): (ISourceBreakpointData | IFunctionBreakpointData)[] { + public $registerBreakpoints(DTOs: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[]): TPromise { + for (let dto of DTOs) { + if (dto.type === 'sourceMulti') { + const rawbps = dto.lines.map(l => + { + id: l.id, + enabled: l.enabled, + lineNumber: l.line + 1, + column: l.character > 0 ? l.character + 1 : 0, + condition: l.condition, + hitCondition: l.hitCondition + } + ); + this.debugService.addBreakpoints(uri.revive(dto.uri), rawbps); + } else if (dto.type === 'function') { + this.debugService.addFunctionBreakpoint(dto.functionName, dto.id); + } + } + return void 0; + } + + public $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): TPromise { + breakpointIds.forEach(id => this.debugService.removeBreakpoints(id)); + functionBreakpointIds.forEach(id => this.debugService.removeFunctionBreakpoints(id)); + return void 0; + } + + private convertToDto(bps: (IBreakpoint | IFunctionBreakpoint)[]): (ISourceBreakpointDto | IFunctionBreakpointDto)[] { return bps.map(bp => { if ('name' in bp) { const fbp = bp; - return { + return { type: 'function', - id: bp.getId(), - enabled: bp.enabled, + id: fbp.getId(), + enabled: fbp.enabled, functionName: fbp.name, - hitCondition: bp.hitCondition, - /* condition: bp.condition */ + hitCondition: fbp.hitCondition, + /* condition: fbp.condition */ }; } else { const sbp = bp; - return { + return { type: 'source', - id: bp.getId(), - enabled: bp.enabled, + id: sbp.getId(), + enabled: sbp.enabled, condition: sbp.condition, - hitCondition: bp.hitCondition, + hitCondition: sbp.hitCondition, uri: sbp.uri, line: sbp.lineNumber > 0 ? sbp.lineNumber - 1 : 0, - character: (typeof sbp.column === 'number' && sbp.column > 0) ? sbp.column - 1 : 0 + character: (typeof sbp.column === 'number' && sbp.column > 0) ? sbp.column - 1 : 0, }; } }); diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts index 0952ff3985f..409e9df963d 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditors.ts @@ -15,17 +15,18 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { MainThreadTextEditor } from './mainThreadEditor'; -import { ITextEditorConfigurationUpdate, TextEditorRevealType, IApplyEditsOptions, IUndoStopOptions } from 'vs/workbench/api/node/extHost.protocol'; +import { ITextEditorConfigurationUpdate, TextEditorRevealType, IApplyEditsOptions, IUndoStopOptions, WorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/node/extHost.protocol'; import { MainThreadDocumentsAndEditors } from './mainThreadDocumentsAndEditors'; import { equals as objectEquals } from 'vs/base/common/objects'; -import { ExtHostContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IExtHostContext, IWorkspaceResourceEdit } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IExtHostContext } from '../node/extHost.protocol'; import { IRange } from 'vs/editor/common/core/range'; import { ISelection } from 'vs/editor/common/core/selection'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IFileService } from 'vs/platform/files/common/files'; -import { bulkEdit, IResourceEdit } from 'vs/editor/browser/services/bulkEdit'; +import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; import { IModelService } from 'vs/editor/common/services/modelService'; import { isCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { isResourceFileEdit } from 'vs/editor/common/modes'; export class MainThreadEditors implements MainThreadEditorsShape { @@ -210,40 +211,22 @@ export class MainThreadEditors implements MainThreadEditorsShape { return TPromise.as(this._documentsAndEditors.getEditor(id).applyEdits(modelVersionId, edits, opts)); } - $tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise { + $tryApplyWorkspaceEdit(dto: WorkspaceEditDto): TPromise { + + const { edits } = reviveWorkspaceEditDto(dto); // First check if loaded models were not changed in the meantime - for (let i = 0, len = workspaceResourceEdits.length; i < len; i++) { - const workspaceResourceEdit = workspaceResourceEdits[i]; - if (workspaceResourceEdit.modelVersionId) { - const uri = URI.revive(workspaceResourceEdit.resource); - let model = this._modelService.getModel(uri); - if (model && model.getVersionId() !== workspaceResourceEdit.modelVersionId) { + for (let i = 0, len = edits.length; i < len; i++) { + const edit = edits[i]; + if (!isResourceFileEdit(edit) && edit.modelVersionId) { + let model = this._modelService.getModel(edit.resource); + if (model && model.getVersionId() !== edit.modelVersionId) { // model changed in the meantime return TPromise.as(false); } } } - // Convert to shape expected by bulkEdit below - let resourceEdits: IResourceEdit[] = []; - for (let i = 0, len = workspaceResourceEdits.length; i < len; i++) { - const workspaceResourceEdit = workspaceResourceEdits[i]; - const uri = URI.revive(workspaceResourceEdit.resource); - const edits = workspaceResourceEdit.edits; - - for (let j = 0, lenJ = edits.length; j < lenJ; j++) { - const edit = edits[j]; - - resourceEdits.push({ - resource: uri, - newText: edit.newText, - newEol: edit.newEol, - range: edit.range - }); - } - } - let codeEditor: ICodeEditor; let editor = this._workbenchEditorService.getActiveEditor(); if (editor) { @@ -253,8 +236,7 @@ export class MainThreadEditors implements MainThreadEditorsShape { } } - return bulkEdit(this._textModelResolverService, codeEditor, resourceEdits, this._fileService) - .then(() => true); + return BulkEdit.perform(edits, this._textModelResolverService, this._fileService, codeEditor).then(() => true); } $tryInsertSnippet(id: string, template: string, ranges: IRange[], opts: IUndoStopOptions): TPromise { diff --git a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts index c2dc6e8aa81..7778851490a 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts @@ -16,6 +16,7 @@ import { ISearchResultProvider, ISearchQuery, ISearchComplete, ISearchProgressIt import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { onUnexpectedError } from 'vs/base/common/errors'; import { values } from 'vs/base/common/map'; +import { isFalsyOrEmpty } from 'vs/base/common/arrays'; @extHostNamedCustomer(MainContext.MainThreadFileSystem) export class MainThreadFileSystem implements MainThreadFileSystemShape { @@ -103,12 +104,12 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv constructor( fileService: IFileService, searchService: ISearchService, - scheme: string, + private readonly _scheme: string, private readonly _handle: number, private readonly _proxy: ExtHostFileSystemShape ) { this._registrations = [ - fileService.registerProvider(scheme, this), + fileService.registerProvider(_scheme, this), searchService.registerSearchResultProvider(this), ]; } @@ -170,6 +171,20 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv search(query: ISearchQuery): PPromise { + if (isFalsyOrEmpty(query.folderQueries)) { + return PPromise.as(undefined); + } + + let includes = { ...query.includePattern }; + let excludes = { ...query.excludePattern }; + + for (const folderQuery of query.folderQueries) { + if (folderQuery.folder.scheme === this._scheme) { + includes = { ...includes, ...folderQuery.includePattern }; + excludes = { ...excludes, ...folderQuery.excludePattern }; + } + } + return new PPromise((resolve, reject, report) => { const search = new SearchOperation(report); @@ -177,7 +192,7 @@ class RemoteFileSystemProvider implements IFileSystemProvider, ISearchResultProv const promise = query.type === QueryType.File ? this._proxy.$findFiles(this._handle, search.id, query.filePattern) - : this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, undefined, undefined); + : this._proxy.$provideTextSearchResults(this._handle, search.id, query.contentPattern, { excludes: Object.keys(excludes), includes: Object.keys(includes) }); promise.then(() => { this._searches.delete(search.id); diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index 3fbe9db8299..df18b3837a5 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -15,7 +15,7 @@ import { wireCancellationToken } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Position as EditorPosition } from 'vs/editor/common/core/position'; import { Range as EditorRange } from 'vs/editor/common/core/range'; -import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, WorkspaceEditDto, ResourceEditDto, CodeActionDto } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto } from '../node/extHost.protocol'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { IHeapService } from './mainThreadHeapService'; @@ -86,21 +86,9 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } } - private static _reviveResourceEditDto(data: ResourceEditDto): modes.IResourceEdit { - data.resource = URI.revive(data.resource); - return data; - } - - private static _reviveWorkspaceEditDto(data: WorkspaceEditDto): modes.WorkspaceEdit { - if (data && data.edits) { - data.edits.forEach(MainThreadLanguageFeatures._reviveResourceEditDto); - } - return data; - } - private static _reviveCodeActionDto(data: CodeActionDto[]): modes.CodeAction[] { if (data) { - data.forEach(code => MainThreadLanguageFeatures._reviveWorkspaceEditDto(code.edit)); + data.forEach(code => reviveWorkspaceEditDto(code.edit)); } return data; } @@ -206,8 +194,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void { this._registrations[handle] = modes.CodeActionProviderRegistry.register(toLanguageSelector(selector), { - provideCodeActions: (model: ITextModel, range: EditorRange, token: CancellationToken): Thenable => { - return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range))).then(MainThreadLanguageFeatures._reviveCodeActionDto); + provideCodeActions: (model: ITextModel, range: EditorRange, context: modes.CodeActionContext, token: CancellationToken): Thenable => { + return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCodeActions(handle, model.uri, range, context))).then(MainThreadLanguageFeatures._reviveCodeActionDto); } }); } @@ -266,11 +254,12 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void { this._registrations[handle] = modes.RenameProviderRegistry.register(toLanguageSelector(selector), { provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable => { - return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)).then(MainThreadLanguageFeatures._reviveWorkspaceEditDto); + return wireCancellationToken(token, this._proxy.$provideRenameEdits(handle, model.uri, position, newName)).then(reviveWorkspaceEditDto); }, resolveInitialRenameValue: supportsResolveInitialValues ? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable => wireCancellationToken(token, this._proxy.$resolveInitialRenameValue(handle, model.uri, position)) - : undefined + : undefined + } }); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadLogService.ts b/src/vs/workbench/api/electron-browser/mainThreadLogService.ts new file mode 100644 index 00000000000..213ad68da8b --- /dev/null +++ b/src/vs/workbench/api/electron-browser/mainThreadLogService.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { ILogService } from 'vs/platform/log/common/log'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IExtHostContext, ExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; + +@extHostCustomer +export class MainThreadLogService extends Disposable { + + constructor( + extHostContext: IExtHostContext, + @ILogService logService: ILogService, + ) { + super(); + this._register(logService.onDidChangeLogLevel(level => extHostContext.getProxy(ExtHostContext.ExtHostLogService).$setLevel(level))); + } + +} \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 5d0a02c34e3..8bd469c9f82 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -26,6 +26,8 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; import { localize } from 'vs/nls'; +import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { ILogService } from 'vs/platform/log/common/log'; export interface ISaveParticipantParticipant extends ISaveParticipant { // progressMessage: string; @@ -144,7 +146,7 @@ export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant const lineCount = model.getLineCount(); // Do not insert new line if file does not end with new line - if (!lineCount) { + if (lineCount === 1) { return; } @@ -208,7 +210,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant { }); }).then(edits => { - if (edits && versionNow === model.getVersionId()) { + if (!isFalsyOrEmpty(edits) && versionNow === model.getVersionId()) { const editor = findEditor(model, this._editorService); if (editor) { this._editsWithEditor(editor, edits); @@ -278,8 +280,9 @@ export class SaveParticipant implements ISaveParticipant { constructor( extHostContext: IExtHostContext, + @IInstantiationService instantiationService: IInstantiationService, @IProgressService2 private _progressService: IProgressService2, - @IInstantiationService instantiationService: IInstantiationService + @ILogService private _logService: ILogService ) { this._saveParticipants = [ instantiationService.createInstance(TrimWhitespaceParticipant), @@ -302,7 +305,7 @@ export class SaveParticipant implements ISaveParticipant { const promiseFactory = this._saveParticipants.map(p => () => { return Promise.resolve(p.participate(model, env)); }); - return sequence(promiseFactory).then(() => { }); + return sequence(promiseFactory).then(() => { }, err => this._logService.error(err)); }); } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index f85ee2a039a..9980e755deb 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -13,6 +13,7 @@ import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService'; import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import URI from 'vs/base/common/uri'; @extHostNamedCustomer(MainContext.MainThreadTask) export class MainThreadTask implements MainThreadTaskShape { @@ -45,7 +46,7 @@ export class MainThreadTask implements MainThreadTaskShape { let uri = (task._source as any as ExtensionTaskSourceTransfer).__workspaceFolder; if (uri) { delete (task._source as any as ExtensionTaskSourceTransfer).__workspaceFolder; - (task._source as any).workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(uri); + (task._source as any).workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(uri)); } } } @@ -57,7 +58,7 @@ export class MainThreadTask implements MainThreadTaskShape { return TPromise.wrap(undefined); } - public $unregisterTaskProvider(handle: number): TPromise { + public $unregisterTaskProvider(handle: number): TPromise { this._taskService.unregisterTaskProvider(handle); delete this._activeHandles[handle]; return TPromise.wrap(undefined); diff --git a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts index 67bd6438fe5..b2970e5f093 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTreeViews.ts @@ -67,7 +67,7 @@ class TreeViewDataProvider implements ITreeViewDataProvider { return this.postGetElements(elements); }, err => { this.messageService.show(Severity.Error, err); - return null; + return []; }); } @@ -80,7 +80,7 @@ class TreeViewDataProvider implements ITreeViewDataProvider { return this.postGetElements(children); }, err => { this.messageService.show(Severity.Error, err); - return null; + return []; }); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 08382f85d1a..b1cd93ae038 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -5,7 +5,7 @@ 'use strict'; import { isPromiseCanceledError } from 'vs/base/common/errors'; -import URI from 'vs/base/common/uri'; +import URI, { UriComponents } from 'vs/base/common/uri'; import { ISearchService, QueryType, ISearchQuery, IFolderQuery, ISearchConfiguration } from 'vs/platform/search/common/search'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -14,6 +14,9 @@ import { MainThreadWorkspaceShape, ExtHostWorkspaceShape, ExtHostContext, MainCo import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; +import { localize } from 'vs/nls'; +import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; @extHostNamedCustomer(MainContext.MainThreadWorkspace) export class MainThreadWorkspace implements MainThreadWorkspaceShape { @@ -27,7 +30,9 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { @ISearchService private readonly _searchService: ISearchService, @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @ITextFileService private readonly _textFileService: ITextFileService, - @IConfigurationService private _configurationService: IConfigurationService + @IConfigurationService private _configurationService: IConfigurationService, + @IWorkspaceEditingService private _workspaceEditingService: IWorkspaceEditingService, + @IStatusbarService private _statusbarService: IStatusbarService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostWorkspace); this._contextService.onDidChangeWorkspaceFolders(this._onDidChangeWorkspace, this, this._toDispose); @@ -45,6 +50,47 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- workspace --- + $updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, foldersToAdd: { uri: UriComponents, name?: string }[]): Thenable { + const workspaceFoldersToAdd = foldersToAdd.map(f => ({ uri: URI.revive(f.uri), name: f.name })); + + // Indicate in status message + this._statusbarService.setStatusMessage(this.getStatusMessage(extensionName, workspaceFoldersToAdd.length, deleteCount), 10 * 1000 /* 10s */); + + return this._workspaceEditingService.updateFolders(index, deleteCount, workspaceFoldersToAdd, true); + } + + private getStatusMessage(extensionName, addCount: number, removeCount: number): string { + let message: string; + + const wantsToAdd = addCount > 0; + const wantsToDelete = removeCount > 0; + + // Add Folders + if (wantsToAdd && !wantsToDelete) { + if (addCount === 1) { + message = localize('folderStatusMessageAddSingleFolder', "Extension '{0}' added 1 folder to the workspace", extensionName); + } else { + message = localize('folderStatusMessageAddMultipleFolders', "Extension '{0}' added {1} folders to the workspace", extensionName, addCount); + } + } + + // Delete Folders + else if (wantsToDelete && !wantsToAdd) { + if (removeCount === 1) { + message = localize('folderStatusMessageRemoveSingleFolder', "Extension '{0}' removed 1 folder from the workspace", extensionName); + } else { + message = localize('folderStatusMessageRemoveMultipleFolders', "Extension '{0}' removed {1} folders from the workspace", extensionName, removeCount); + } + } + + // Change Folders + else { + message = localize('folderStatusChangeFolder', "Extension '{0}' changed folders of the workspace", extensionName); + } + + return message; + } + private _onDidChangeWorkspace(): void { this._proxy.$acceptWorkspaceData(this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace()); } @@ -122,4 +168,4 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { return result.results.every(each => each.success === true); }); } -} +} \ No newline at end of file diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 4d6eb312357..2336cf37321 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -55,8 +55,8 @@ import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations'; import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters'; import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionActivator'; import { isFalsyOrEmpty } from 'vs/base/common/arrays'; -import { ILogService } from 'vs/platform/log/common/log'; import { OverviewRulerLane } from 'vs/editor/common/model'; +import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; export interface IExtensionApiFactory { (extension: IExtensionDescription): typeof vscode; @@ -89,18 +89,19 @@ export function createApiFactory( extHostWorkspace: ExtHostWorkspace, extHostConfiguration: ExtHostConfiguration, extensionService: ExtHostExtensionService, - logService: ILogService + extHostLogService: ExtHostLogService ): IExtensionApiFactory { // Addressable instances + rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService); const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService()); const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol)); const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol)); const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors)); const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors)); - const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(logService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadEditors))); + const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadEditors))); const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors)); - const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, logService)); + const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService)); const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands)); rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace); const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace)); @@ -111,7 +112,7 @@ export function createApiFactory( const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService()); const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands)); const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol)); - const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, logService)); + const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService)); const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace)); const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol)); rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService); @@ -418,6 +419,9 @@ export function createApiFactory( set name(value) { throw errors.readonly(); }, + updateWorkspaceFolders: proposedApiFunction(extension, (index, deleteCount, ...workspaceFoldersToAdd) => { + return extHostWorkspace.updateWorkspaceFolders(extension, index, deleteCount, ...workspaceFoldersToAdd); + }), onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) { return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables); }, @@ -537,7 +541,13 @@ export function createApiFactory( }, registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider) { return extHostDebugService.registerDebugConfigurationProvider(debugType, provider); - } + }, + addBreakpoints: proposedApiFunction(extension, (breakpoints: vscode.Breakpoint[]) => { + return extHostDebugService.addBreakpoints(breakpoints); + }), + removeBreakpoints: proposedApiFunction(extension, (breakpoints: vscode.Breakpoint[]) => { + return extHostDebugService.removeBreakpoints(breakpoints); + }) }; @@ -556,6 +566,7 @@ export function createApiFactory( Breakpoint: extHostTypes.Breakpoint, CancellationTokenSource: CancellationTokenSource, CodeAction: extHostTypes.CodeAction, + CodeActionKind: extHostTypes.CodeActionKind, CodeLens: extHostTypes.CodeLens, Color: extHostTypes.Color, ColorPresentation: extHostTypes.ColorPresentation, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 5c85df1a88c..e289cf18c82 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -4,17 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { - createMainContextProxyIdentifier as createMainId, - createExtHostContextProxyIdentifier as createExtId, - ProxyIdentifier, - IRPCProtocol, - ProxyType -} from 'vs/workbench/services/extensions/node/proxyIdentifier'; +import { createMainContextProxyIdentifier as createMainId, createExtHostContextProxyIdentifier as createExtId, ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import * as vscode from 'vscode'; -import { UriComponents } from 'vs/base/common/uri'; +import URI, { UriComponents } from 'vs/base/common/uri'; import Severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -52,8 +46,9 @@ import { IStat, FileChangeType } from 'vs/platform/files/common/files'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/languageConfiguration'; -import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model'; +import { ISingleEditOperation } from 'vs/editor/common/model'; import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search'; +import { LogLevel } from 'vs/platform/log/common/log'; export interface IEnvironment { isExtensionDevelopmentDebug: boolean; @@ -71,6 +66,7 @@ export interface IWorkspaceData { id: string; name: string; folders: { uri: UriComponents, name: string, index: number }[]; + configuration?: UriComponents; } export interface IInitData { @@ -83,6 +79,7 @@ export interface IInitData { windowId: number; args: ParsedArgs; execPath: string; + logLevel: LogLevel; } export interface IConfigurationInitData extends IConfigurationData { @@ -192,8 +189,6 @@ export interface IApplyEditsOptions extends IUndoStopOptions { setEndOfLine: EndOfLine; } - - export interface ITextDocumentShowOptions { position?: EditorPosition; preserveFocus?: boolean; @@ -201,16 +196,6 @@ export interface ITextDocumentShowOptions { selection?: IRange; } -export interface IWorkspaceResourceEdit { - resource: UriComponents; - modelVersionId?: number; - edits: { - range?: IRange; - newText: string; - newEol?: EndOfLineSequence; - }[]; -} - export interface MainThreadEditorsShape extends IDisposable { $tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): TPromise; $registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void; @@ -223,7 +208,7 @@ export interface MainThreadEditorsShape extends IDisposable { $tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise; $trySetSelections(id: string, selections: ISelection[]): TPromise; $tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): TPromise; - $tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise; + $tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): TPromise; $tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise; $getDiffInformation(id: string): TPromise; } @@ -364,6 +349,7 @@ export interface MainThreadWorkspaceShape extends IDisposable { $startSearch(includePattern: string, includeFolder: string, excludePattern: string, maxResults: number, requestId: number): Thenable; $cancelSearch(requestId: number): Thenable; $saveAll(includeUntitled?: boolean): Thenable; + $updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Thenable; } export interface IFileChangeDto { @@ -383,8 +369,8 @@ export interface MainThreadFileSystemShape extends IDisposable { } export interface MainThreadTaskShape extends IDisposable { - $registerTaskProvider(handle: number): TPromise; - $unregisterTaskProvider(handle: number): TPromise; + $registerTaskProvider(handle: number): TPromise; + $unregisterTaskProvider(handle: number): TPromise; } export interface MainThreadExtensionServiceShape extends IDisposable { @@ -457,6 +443,8 @@ export interface MainThreadDebugServiceShape extends IDisposable { $customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise; $appendDebugConsole(value: string): TPromise; $startBreakpointEvents(): TPromise; + $registerBreakpoints(breakpoints: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[]): TPromise; + $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): TPromise; } export interface MainThreadWindowShape extends IDisposable { @@ -549,7 +537,7 @@ export interface ExtHostFileSystemShape { $readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][]>; $rmdir(handle: number, resource: UriComponents): TPromise; $findFiles(handle: number, session: number, query: string): TPromise; - $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, include: string, exclude: string): TPromise; + $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise; } export interface ExtHostExtensionServiceShape { @@ -623,22 +611,44 @@ export interface WorkspaceSymbolsDto extends IdObject { symbols: SymbolInformationDto[]; } -export interface ResourceEditDto { +export interface ResourceFileEditDto { + oldUri: UriComponents; + newUri: UriComponents; +} + +export interface ResourceTextEditDto { resource: UriComponents; - range: IRange; - newText: string; + modelVersionId?: number; + edits: modes.TextEdit[]; } export interface WorkspaceEditDto { - edits: ResourceEditDto[]; + edits: (ResourceFileEditDto | ResourceTextEditDto)[]; + + // todo@joh reject should go into rename rejectReason?: string; } +export function reviveWorkspaceEditDto(data: WorkspaceEditDto): modes.WorkspaceEdit { + if (data && data.edits) { + for (const edit of data.edits) { + if (typeof (edit).resource === 'object') { + (edit).resource = URI.revive((edit).resource); + } else { + (edit).newUri = URI.revive((edit).newUri); + (edit).oldUri = URI.revive((edit).oldUri); + } + } + } + return data; +} + export interface CodeActionDto { title: string; edit?: WorkspaceEditDto; diagnostics?: IMarkerData[]; command?: modes.Command; + kind?: string; } export interface ExtHostLanguageFeaturesShape { @@ -651,7 +661,7 @@ export interface ExtHostLanguageFeaturesShape { $provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise; - $provideCodeActions(handle: number, resource: UriComponents, range: IRange): TPromise; + $provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise; $provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise; $provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions): TPromise; $provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise; @@ -690,30 +700,43 @@ export interface ExtHostTaskShape { $provideTasks(handle: number): TPromise; } -export interface IBreakpointData { - type: 'source' | 'function'; - id: string; +export interface IFunctionBreakpointDto { + type: 'function'; + id?: string; enabled: boolean; condition?: string; hitCondition?: string; + functionName: string; } -export interface ISourceBreakpointData extends IBreakpointData { +export interface ISourceBreakpointDto { type: 'source'; + id?: string; + enabled: boolean; + condition?: string; + hitCondition?: string; uri: UriComponents; line: number; character: number; } -export interface IFunctionBreakpointData extends IBreakpointData { - type: 'function'; - functionName: string; +export interface IBreakpointsDeltaDto { + added?: (ISourceBreakpointDto | IFunctionBreakpointDto)[]; + removed?: string[]; + changed?: (ISourceBreakpointDto | IFunctionBreakpointDto)[]; } -export interface IBreakpointsDelta { - added?: (ISourceBreakpointData | IFunctionBreakpointData)[]; - removed?: string[]; - changed?: (ISourceBreakpointData | IFunctionBreakpointData)[]; +export interface ISourceMultiBreakpointDto { + type: 'sourceMulti'; + uri: UriComponents; + lines: { + id: string; + enabled: boolean; + condition?: string; + hitCondition?: string; + line: number; + character: number; + }[]; } export interface ExtHostDebugServiceShape { @@ -723,7 +746,7 @@ export interface ExtHostDebugServiceShape { $acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void; $acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void; $acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void; - $acceptBreakpointsDelta(delat: IBreakpointsDelta): void; + $acceptBreakpointsDelta(delat: IBreakpointsDeltaDto): void; } @@ -744,6 +767,10 @@ export interface ExtHostWindowShape { $onDidChangeWindowFocus(value: boolean): void; } +export interface ExtHostLogServiceShape { + $setLevel(level: LogLevel); +} + // --- proxy identifiers export const MainContext = { @@ -772,7 +799,7 @@ export const MainContext = { MainThreadFileSystem: createMainId('MainThreadFileSystem'), MainThreadExtensionService: createMainId('MainThreadExtensionService'), MainThreadSCM: createMainId('MainThreadSCM'), - MainThreadTask: createMainId('MainThreadTask', ProxyType.CustomMarshaller), + MainThreadTask: createMainId('MainThreadTask'), MainThreadWindow: createMainId('MainThreadWindow'), }; @@ -794,10 +821,10 @@ export const ExtHostContext = { ExtHostLanguageFeatures: createExtId('ExtHostLanguageFeatures'), ExtHostQuickOpen: createExtId('ExtHostQuickOpen'), ExtHostExtensionService: createExtId('ExtHostExtensionService'), - // ExtHostLogService: createExtId('ExtHostLogService'), + ExtHostLogService: createExtId('ExtHostLogService'), ExtHostTerminalService: createExtId('ExtHostTerminalService'), ExtHostSCM: createExtId('ExtHostSCM'), - ExtHostTask: createExtId('ExtHostTask', ProxyType.CustomMarshaller), + ExtHostTask: createExtId('ExtHostTask'), ExtHostWorkspace: createExtId('ExtHostWorkspace'), ExtHostWindow: createExtId('ExtHostWindow'), }; diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index bf16fdb2c52..17a987c549f 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -353,11 +353,7 @@ export class ExtHostApiCommands { if (value.rejectReason) { return TPromise.wrapError(new Error(value.rejectReason)); } - let workspaceEdit = new types.WorkspaceEdit(); - for (let edit of value.edits) { - workspaceEdit.replace(edit.resource, typeConverters.toRange(edit.range), edit.newText); - } - return workspaceEdit; + return typeConverters.WorkspaceEdit.to(value); }); } @@ -417,8 +413,11 @@ export class ExtHostApiCommands { } else { const ret = new types.CodeAction( codeAction.title, - typeConverters.WorkspaceEdit.to(codeAction.edit) + codeAction.kind ? new types.CodeActionKind(codeAction.kind) : undefined ); + if (codeAction.edit) { + ret.edit = typeConverters.WorkspaceEdit.to(codeAction.edit); + } return ret; } }); diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 3276d4348ea..7b1cba6a42c 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -7,12 +7,16 @@ import { TPromise } from 'vs/base/common/winjs.base'; import Event, { Emitter } from 'vs/base/common/event'; import { asWinJsPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext, IBreakpointsDelta, ISourceBreakpointData, IFunctionBreakpointData } from 'vs/workbench/api/node/extHost.protocol'; +import { + MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, + IMainContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto +} from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import * as vscode from 'vscode'; import URI, { UriComponents } from 'vs/base/common/uri'; import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint } from 'vs/workbench/api/node/extHostTypes'; +import { generateUuid } from 'vs/base/common/uuid'; export class ExtHostDebugService implements ExtHostDebugServiceShape { @@ -95,51 +99,161 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { return result; } - public $acceptBreakpointsDelta(delta: IBreakpointsDelta): void { + public $acceptBreakpointsDelta(delta: IBreakpointsDeltaDto): void { let a: vscode.Breakpoint[] = []; let r: vscode.Breakpoint[] = []; let c: vscode.Breakpoint[] = []; if (delta.added) { - a = delta.added.map(bpd => { - const bp = this.fromWire(bpd); - this._breakpoints.set(bpd.id, bp); - return bp; - }); + for (const bpd of delta.added) { + + if (!this._breakpoints.has(bpd.id)) { + let bp: vscode.Breakpoint; + if (bpd.type === 'function') { + bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition); + } else { + const uri = URI.revive(bpd.uri); + bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition); + } + bp['_id'] = bpd.id; + this._breakpoints.set(bpd.id, bp); + a.push(bp); + + } + + + } } if (delta.removed) { - r = delta.removed.map(id => { + for (const id of delta.removed) { const bp = this._breakpoints.get(id); if (bp) { this._breakpoints.delete(id); + r.push(bp); } - return bp; - }); + } } if (delta.changed) { - c = delta.changed.map(bpd => { - const bp = this.fromWire(bpd); - this._breakpoints.set(bpd.id, bp); - return bp; - }); + for (const bpd of delta.changed) { + let bp = this._breakpoints.get(bpd.id); + if (bp) { + if (bpd.type === 'function') { + const fbp = bp; + fbp.enabled = bpd.enabled; + fbp.condition = bpd.condition; + fbp.hitCondition = bpd.hitCondition; + fbp.functionName = bpd.functionName; + } else { + const sbp = bp; + sbp.enabled = bpd.enabled; + sbp.condition = bpd.condition; + sbp.hitCondition = bpd.hitCondition; + } + c.push(bp); + } + } } - this._onDidChangeBreakpoints.fire(Object.freeze({ - added: Object.freeze(a || []), - removed: Object.freeze(r || []), - changed: Object.freeze(c || []) - })); + this.fireBreakpointChanges(a, r, c); } - private fromWire(bp: ISourceBreakpointData | IFunctionBreakpointData): vscode.Breakpoint { - if (bp.type === 'function') { - return new FunctionBreakpoint(bp.enabled, bp.condition, bp.hitCondition, bp.functionName); + public addBreakpoints(breakpoints0: vscode.Breakpoint[]): TPromise { + + this.startBreakpoints(); + + // assign uuids for brand new breakpoints + const breakpoints: vscode.Breakpoint[] = []; + for (const bp of breakpoints0) { + let id = bp['_id']; + if (id) { // has already id + if (this._breakpoints.has(id)) { + // already there + } else { + breakpoints.push(bp); + } + } else { + id = generateUuid(); + bp['_id'] = id; + this._breakpoints.set(id, bp); + breakpoints.push(bp); + } + } + + // send notification for added breakpoints + this.fireBreakpointChanges(breakpoints, [], []); + + // convert added breakpoints to DTOs + const dtos: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[] = []; + const map = new Map(); + for (const bp of breakpoints) { + if (bp instanceof SourceBreakpoint) { + let dto = map.get(bp.location.uri.toString()); + if (!dto) { + dto = { + type: 'sourceMulti', + uri: bp.location.uri, + lines: [] + }; + map.set(bp.location.uri.toString(), dto); + dtos.push(dto); + } + dto.lines.push({ + id: bp['_id'], + enabled: bp.enabled, + condition: bp.condition, + hitCondition: bp.hitCondition, + line: bp.location.range.start.line, + character: bp.location.range.start.character + }); + } else if (bp instanceof FunctionBreakpoint) { + dtos.push({ + type: 'function', + id: bp['_id'], + enabled: bp.enabled, + functionName: bp.functionName, + hitCondition: bp.hitCondition, + condition: bp.condition + }); + } + } + + // send DTOs to VS Code + return this._debugServiceProxy.$registerBreakpoints(dtos); + } + + public removeBreakpoints(breakpoints0: vscode.Breakpoint[]): TPromise { + + this.startBreakpoints(); + + // remove from array + const breakpoints: vscode.Breakpoint[] = []; + for (const b of breakpoints0) { + let id = b['_id']; + if (id && this._breakpoints.delete(id)) { + breakpoints.push(b); + } + } + + // send notification + this.fireBreakpointChanges([], breakpoints, []); + + // unregister with VS Code + const ids = breakpoints.filter(bp => bp instanceof SourceBreakpoint).map(bp => bp['_id']); + const fids = breakpoints.filter(bp => bp instanceof FunctionBreakpoint).map(bp => bp['_id']); + return this._debugServiceProxy.$unregisterBreakpoints(ids, fids); + } + + private fireBreakpointChanges(added: vscode.Breakpoint[], removed: vscode.Breakpoint[], changed: vscode.Breakpoint[]) { + if (added.length > 0 || removed.length > 0 || changed.length > 0) { + this._onDidChangeBreakpoints.fire(Object.freeze({ + added: Object.freeze(added), + removed: Object.freeze(removed), + changed: Object.freeze(changed) + })); } - const uri = URI.revive(bp.uri); - return new SourceBreakpoint(bp.enabled, bp.condition, bp.hitCondition, new Location(uri, new Position(bp.line, bp.character))); } public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable { diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index 3733a20adbc..d6edc95eb20 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -8,7 +8,7 @@ import Event from 'vs/base/common/event'; import URI, { UriComponents } from 'vs/base/common/uri'; import { sequence, always } from 'vs/base/common/async'; import { illegalState } from 'vs/base/common/errors'; -import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol'; +import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol'; import { TextEdit } from 'vs/workbench/api/node/extHostTypes'; import { fromRange, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverters'; import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; @@ -142,7 +142,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic }).then(values => { - let workspaceResourceEdit: IWorkspaceResourceEdit = { + const resourceEdit: ResourceTextEditDto = { resource: document.uri, edits: [] }; @@ -150,10 +150,10 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic for (const value of values) { if (Array.isArray(value) && (value).every(e => e instanceof TextEdit)) { for (const { newText, newEol, range } of value) { - workspaceResourceEdit.edits.push({ + resourceEdit.edits.push({ range: range && fromRange(range), - newText, - newEol: EndOfLine.from(newEol) + text: newText, + eol: EndOfLine.from(newEol) }); } } @@ -161,12 +161,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic // apply edits if any and if document // didn't change somehow in the meantime - if (workspaceResourceEdit.edits.length === 0) { + if (resourceEdit.edits.length === 0) { return undefined; } if (version === document.version) { - return this._mainThreadEditors.$tryApplyWorkspaceEdit([workspaceResourceEdit]); + return this._mainThreadEditors.$tryApplyWorkspaceEdit({ edits: [resourceEdit] }); } // TODO@joh bubble this to listener? diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index d16146a5e0d..c3972702415 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -22,6 +22,7 @@ import { Barrier } from 'vs/base/common/async'; import { ILogService } from 'vs/platform/log/common/log'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; +import URI from 'vs/base/common/uri'; class ExtensionMemento implements IExtensionMemento { @@ -106,7 +107,11 @@ class ExtensionStoragePath { await mkdirp(storagePath); await writeFile( join(storagePath, 'meta.json'), - JSON.stringify({ id: this._workspace.id }) + JSON.stringify({ + id: this._workspace.id, + configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(), + name: this._workspace.name + }, undefined, 2) ); return storagePath; @@ -125,7 +130,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { private readonly _storage: ExtHostStorage; private readonly _storagePath: ExtensionStoragePath; private readonly _proxy: MainThreadExtensionServiceShape; - private readonly _logService: ILogService; private readonly _extHostLogService: ExtHostLogService; private _activator: ExtensionsActivator; private _extensionPathIndex: TPromise>; @@ -136,21 +140,20 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { extHostContext: IExtHostContext, extHostWorkspace: ExtHostWorkspace, extHostConfiguration: ExtHostConfiguration, - logService: ILogService, + extHostLogService: ExtHostLogService, environmentService: IEnvironmentService ) { this._barrier = new Barrier(); this._registry = new ExtensionDescriptionRegistry(initData.extensions); - this._logService = logService; + this._extHostLogService = extHostLogService; this._mainThreadTelemetry = extHostContext.getProxy(MainContext.MainThreadTelemetry); this._storage = new ExtHostStorage(extHostContext); this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment); this._proxy = extHostContext.getProxy(MainContext.MainThreadExtensionService); this._activator = null; - this._extHostLogService = new ExtHostLogService(environmentService); // initialize API first (i.e. do not release barrier until the API is initialized) - const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, logService); + const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, this._extHostLogService); initializeExtensionApi(this, apiFactory).then(() => { @@ -311,14 +314,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE)); } - this._logService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`); + this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`); const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup); return TPromise.join([ - loadCommonJSModule(this._logService, extensionDescription.main, activationTimesBuilder), + loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder), this._loadExtensionContext(extensionDescription) ]).then(values => { - return ExtHostExtensionService._callActivate(this._logService, extensionDescription.id, values[0], values[1], activationTimesBuilder); + return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, values[0], values[1], activationTimesBuilder); }, (errors: any[]) => { // Avoid failing with an array of errors, fail with a single error if (errors[0]) { @@ -336,7 +339,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage); let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage); - this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`); + this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`); return TPromise.join([ globalState.whenReady, workspaceState.whenReady, diff --git a/src/vs/workbench/api/node/extHostFileSystem.ts b/src/vs/workbench/api/node/extHostFileSystem.ts index 62dbf9b67fe..7a8b780fcc4 100644 --- a/src/vs/workbench/api/node/extHostFileSystem.ts +++ b/src/vs/workbench/api/node/extHostFileSystem.ts @@ -137,7 +137,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { }; return asWinJsPromise(token => provider.findFiles(query, progress, token)); } - $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, include: string, exclude: string): TPromise { + $provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise { const provider = this._provider.get(handle); if (!provider.provideTextSearchResults) { return TPromise.as(undefined); @@ -151,6 +151,6 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { }]); } }; - return asWinJsPromise(token => provider.provideTextSearchResults(pattern, include, exclude, progress, token)); + return asWinJsPromise(token => provider.provideTextSearchResults(pattern, options, progress, token)); } } diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 17584f1cb68..7bf9029a45e 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { mixin } from 'vs/base/common/objects'; import * as vscode from 'vscode'; import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters'; -import { Range, Disposable, CompletionList, SnippetString, Color } from 'vs/workbench/api/node/extHostTypes'; +import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } from 'vs/workbench/api/node/extHostTypes'; import { ISingleEditOperation } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService'; @@ -17,7 +17,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands'; import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics'; import { asWinJsPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto } from './extHost.protocol'; +import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } from './extHost.protocol'; import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange } from 'vs/editor/common/core/range'; @@ -255,7 +255,7 @@ class ReferenceAdapter { } } -export interface CustomCodeAction extends modes.CodeAction { +export interface CustomCodeAction extends CodeActionDto { _isSynthetic?: boolean; } @@ -273,7 +273,8 @@ class CodeActionAdapter { this._provider = provider; } - provideCodeActions(resource: URI, range: IRange): TPromise { + + provideCodeActions(resource: URI, range: IRange, context: modes.CodeActionContext): TPromise { const doc = this._documents.getDocumentData(resource).document; const ran = TypeConverters.toRange(range); @@ -289,8 +290,12 @@ class CodeActionAdapter { } }); + const codeActionContext: vscode.CodeActionContext = { + diagnostics: allDiagnostics, + only: context.only ? new CodeActionKind(context.only) : undefined + }; return asWinJsPromise(token => - this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token) + this._provider.provideCodeActions(doc, ran, codeActionContext, token) ).then(commandsOrActions => { if (isFalsyOrEmpty(commandsOrActions)) { return undefined; @@ -314,6 +319,7 @@ class CodeActionAdapter { command: candidate.command && this._commands.toInternal(candidate.command), diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData), edit: candidate.edit && TypeConverters.WorkspaceEdit.from(candidate.edit), + kind: candidate.kind && candidate.kind.value }); } } @@ -963,8 +969,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideCodeActions(handle: number, resource: UriComponents, range: IRange): TPromise { - return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range)); + + $provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise { + return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range, context)); } // --- formatting diff --git a/src/vs/workbench/api/node/extHostLogService.ts b/src/vs/workbench/api/node/extHostLogService.ts index fff0755018d..fbc0c9d308c 100644 --- a/src/vs/workbench/api/node/extHostLogService.ts +++ b/src/vs/workbench/api/node/extHostLogService.ts @@ -4,51 +4,65 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as path from 'path'; import * as vscode from 'vscode'; import { TPromise } from 'vs/base/common/winjs.base'; +import { join } from 'vs/base/common/paths'; import { mkdirp, dirExists } from 'vs/base/node/pfs'; -import Event, { Emitter } from 'vs/base/common/event'; +import Event from 'vs/base/common/event'; import { LogLevel } from 'vs/workbench/api/node/extHostTypes'; -import { ILogService } from 'vs/platform/log/common/log'; +import { ILogService, DelegatedLogService } from 'vs/platform/log/common/log'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { memoize } from 'vs/base/common/decorators'; +import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol'; + + +export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape { -export class ExtHostLogService { private _loggers: Map = new Map(); - constructor(private _environmentService: IEnvironmentService) { + constructor( + windowId: number, + logLevel: LogLevel, + private _environmentService: IEnvironmentService + ) { + super(createSpdLogService(`exthost${windowId}`, logLevel, _environmentService.logsPath)); + } + + $setLevel(level: LogLevel): void { + this.setLevel(level); } getExtLogger(extensionID: string): ExtHostLogger { - if (!this._loggers.has(extensionID)) { - const logService = createSpdLogService(extensionID, this._environmentService, extensionID); - const logsDirPath = path.join(this._environmentService.logsPath, extensionID); - this._loggers.set(extensionID, new ExtHostLogger(logService, logsDirPath)); + let logger = this._loggers.get(extensionID); + if (!logger) { + logger = this.createLogger(extensionID); + this._loggers.set(extensionID, logger); } + return logger; + } - return this._loggers.get(extensionID); + private createLogger(extensionID: string): ExtHostLogger { + const logsDirPath = join(this._environmentService.logsPath, extensionID); + const logService = createSpdLogService(extensionID, this.getLevel(), logsDirPath); + this._register(this.onDidChangeLogLevel(level => logService.setLevel(level))); + return new ExtHostLogger(logService, logsDirPath); } } export class ExtHostLogger implements vscode.Logger { - private _currentLevel: LogLevel; - private _onDidChangeLogLevel: Emitter; constructor( private readonly _logService: ILogService, private readonly _logDirectory: string ) { - this._currentLevel = this._logService.getLevel(); - this._onDidChangeLogLevel = new Emitter(); - this.onDidChangeLogLevel = this._onDidChangeLogLevel.event; } - // TODO - readonly onDidChangeLogLevel: Event; + get onDidChangeLogLevel(): Event { + return this._logService.onDidChangeLogLevel; + } - get currentLevel(): LogLevel { return this._currentLevel; } + get currentLevel(): LogLevel { return this._logService.getLevel(); } @memoize get logDirectory(): TPromise { diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 41cb0357367..58357c83862 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -294,11 +294,11 @@ namespace ShellConfiguration { namespace Tasks { - export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.Task[] { + export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask[] { if (tasks === void 0 || tasks === null) { return []; } - let result: TaskSystem.Task[] = []; + let result: TaskSystem.ContributedTask[] = []; for (let task of tasks) { let converted = fromSingle(task, rootFolder, extension); if (converted) { @@ -351,7 +351,7 @@ namespace Tasks { // We can't transfer a workspace folder object from the extension host to main since they differ // in shape and we don't have backwards converting function. So transfer the URI and resolve the // workspace folder on the main side. - (source as any).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined; + (source as any as TaskSystem.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined; let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); let key = (task as types.Task).definitionKey; let kind = (task as types.Task).definition; diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index 35ad03c3a49..ea973d68b22 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -12,7 +12,7 @@ import * as TypeConverters from './extHostTypeConverters'; import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor'; import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors'; import { Position as EditorPosition } from 'vs/platform/editor/common/editor'; -import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, IWorkspaceResourceEdit } from './extHost.protocol'; +import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, WorkspaceEditDto } from './extHost.protocol'; import * as vscode from 'vscode'; export class ExtHostEditors implements ExtHostEditorsShape { @@ -92,36 +92,23 @@ export class ExtHostEditors implements ExtHostEditorsShape { applyWorkspaceEdit(edit: vscode.WorkspaceEdit): TPromise { - let workspaceResourceEdits: IWorkspaceResourceEdit[] = []; + const dto: WorkspaceEditDto = { edits: [] }; - let entries = edit.entries(); - for (let entry of entries) { - let [uri, edits] = entry; - - let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString()); - let docVersion: number = undefined; - if (doc) { - docVersion = doc.version; - } - - let workspaceResourceEdit: IWorkspaceResourceEdit = { - resource: uri, - modelVersionId: docVersion, - edits: [] - }; - - for (let edit of edits) { - workspaceResourceEdit.edits.push({ - newText: edit.newText, - newEol: TypeConverters.EndOfLine.from(edit.newEol), - range: edit.range && TypeConverters.fromRange(edit.range) + for (let entry of edit.allEntries()) { + let [uri, uriOrEdits] = entry; + if (Array.isArray(uriOrEdits)) { + let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString()); + dto.edits.push({ + resource: uri, + modelVersionId: doc && doc.version, + edits: uriOrEdits.map(TypeConverters.TextEdit.from) }); + } else { + dto.edits.push({ oldUri: uri, newUri: uriOrEdits }); } - - workspaceResourceEdits.push(workspaceResourceEdit); } - return this._proxy.$tryApplyWorkspaceEdit(workspaceResourceEdits); + return this._proxy.$tryApplyWorkspaceEdit(dto); } // --- called from main thread diff --git a/src/vs/workbench/api/node/extHostTreeViews.ts b/src/vs/workbench/api/node/extHostTreeViews.ts index a1807377c88..effb25dd985 100644 --- a/src/vs/workbench/api/node/extHostTreeViews.ts +++ b/src/vs/workbench/api/node/extHostTreeViews.ts @@ -114,7 +114,7 @@ class ExtHostTreeView extends Disposable { } return null; }) - ))).then(extTreeItems => extTreeItems.map((({ element, extTreeItem }) => this.createTreeItem(element, extTreeItem, parentHandle)))); + ))).then(extTreeItems => coalesce(extTreeItems).map((({ element, extTreeItem }) => this.createTreeItem(element, extTreeItem, parentHandle)))); } getExtensionElement(treeItemHandle: TreeItemHandle): T { diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index a25d0430ff9..38ce5b91889 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -20,6 +20,7 @@ import { ISelection } from 'vs/editor/common/core/selection'; import * as htmlContent from 'vs/base/common/htmlContent'; import { IRelativePattern } from 'vs/base/common/glob'; import { LanguageSelector, LanguageFilter } from 'vs/editor/common/modes/languageSelector'; +import { WorkspaceEditDto, ResourceTextEditDto, ResourceFileEditDto } from 'vs/workbench/api/node/extHost.protocol'; export interface PositionLike { line: number; @@ -228,24 +229,36 @@ export const TextEdit = { export namespace WorkspaceEdit { export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit { - const result: modes.WorkspaceEdit = { edits: [] }; - for (let entry of value.entries()) { - let [uri, textEdits] = entry; - for (let textEdit of textEdits) { - result.edits.push({ - resource: uri, - newText: textEdit.newText, - range: fromRange(textEdit.range) - }); + const result: modes.WorkspaceEdit = { + edits: [] + }; + for (const entry of value.allEntries()) { + const [uri, uriOrEdits] = entry; + if (Array.isArray(uriOrEdits)) { + // text edits + result.edits.push({ resource: uri, edits: uriOrEdits.map(TextEdit.from) }); + } else { + // resource edits + result.edits.push({ oldUri: uri, newUri: uriOrEdits }); } } return result; } - export function to(value: modes.WorkspaceEdit) { + export function to(value: WorkspaceEditDto) { const result = new types.WorkspaceEdit(); for (const edit of value.edits) { - result.replace(edit.resource, toRange(edit.range), edit.newText); + if (Array.isArray((edit).edits)) { + result.set( + URI.revive((edit).resource), + (edit).edits.map(TextEdit.to) + ); + } else { + result.renameResource( + URI.revive((edit).oldUri), + URI.revive((edit).newUri) + ); + } } return result; } diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 76c30af3a0f..ce9749e81fc 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -12,6 +12,7 @@ import * as vscode from 'vscode'; import { isMarkdownString } from 'vs/base/common/htmlContent'; import { IRelativePattern } from 'vs/base/common/glob'; import { relative } from 'path'; +import { startsWith } from 'vs/base/common/strings'; export class Disposable { @@ -491,10 +492,28 @@ export class TextEdit { } } -export class WorkspaceEdit { +export class WorkspaceEdit implements vscode.WorkspaceEdit { - private _values: [URI, TextEdit[]][] = []; - private _index = new Map(); + private _seqPool: number = 0; + + private _resourceEdits: { seq: number, from: URI, to: URI }[] = []; + private _textEdits = new Map(); + + createResource(uri: vscode.Uri): void { + this.renameResource(undefined, uri); + } + + deleteResource(uri: vscode.Uri): void { + this.renameResource(uri, undefined); + } + + renameResource(from: vscode.Uri, to: vscode.Uri): void { + this._resourceEdits.push({ seq: this._seqPool++, from, to }); + } + + resourceEdits(): [vscode.Uri, vscode.Uri][] { + return this._resourceEdits.map(({ from, to }) => (<[vscode.Uri, vscode.Uri]>[from, to])); + } replace(uri: URI, range: Range, newText: string): void { let edit = new TextEdit(range, newText); @@ -502,8 +521,9 @@ export class WorkspaceEdit { if (array) { array.push(edit); } else { - this.set(uri, [edit]); + array = [edit]; } + this.set(uri, array); } insert(resource: URI, position: Position, newText: string): void { @@ -515,34 +535,58 @@ export class WorkspaceEdit { } has(uri: URI): boolean { - return this._index.has(uri.toString()); + return this._textEdits.has(uri.toString()); } set(uri: URI, edits: TextEdit[]): void { - const idx = this._index.get(uri.toString()); - if (typeof idx === 'undefined') { - let newLen = this._values.push([uri, edits]); - this._index.set(uri.toString(), newLen - 1); + let data = this._textEdits.get(uri.toString()); + if (!data) { + data = { seq: this._seqPool++, uri, edits: [] }; + this._textEdits.set(uri.toString(), data); + } + if (!edits) { + data.edits = undefined; } else { - this._values[idx][1] = edits; + data.edits = edits.slice(0); } } get(uri: URI): TextEdit[] { - let idx = this._index.get(uri.toString()); - return typeof idx !== 'undefined' && this._values[idx][1]; + if (!this._textEdits.has(uri.toString())) { + return undefined; + } + const { edits } = this._textEdits.get(uri.toString()); + return edits ? edits.slice() : undefined; } entries(): [URI, TextEdit[]][] { - return this._values; + const res: [URI, TextEdit[]][] = []; + this._textEdits.forEach(value => res.push([value.uri, value.edits])); + return res.slice(); + } + + allEntries(): ([URI, TextEdit[]] | [URI, URI])[] { + // use the 'seq' the we have assigned when inserting + // the operation and use that order in the resulting + // array + const res: ([URI, TextEdit[]] | [URI, URI])[] = []; + this._textEdits.forEach(value => { + const { seq, uri, edits } = value; + res[seq] = [uri, edits]; + }); + this._resourceEdits.forEach(value => { + const { seq, from, to } = value; + res[seq] = [from, to]; + }); + return res; } get size(): number { - return this._values.length; + return this._textEdits.size + this._resourceEdits.length; } toJSON(): any { - return this._values; + return this.entries(); } } @@ -818,12 +862,39 @@ export class CodeAction { dianostics?: Diagnostic[]; - constructor(title: string, edit?: WorkspaceEdit) { + kind?: CodeActionKind; + + constructor(title: string, kind?: CodeActionKind) { this.title = title; - this.edit = edit; + this.kind = kind; } } + +export class CodeActionKind { + private static readonly sep = '.'; + + public static readonly Empty = new CodeActionKind(''); + public static readonly QuickFix = CodeActionKind.Empty.append('quickfix'); + public static readonly Refactor = CodeActionKind.Empty.append('refactor'); + public static readonly RefactorExtract = CodeActionKind.Refactor.append('extract'); + public static readonly RefactorInline = CodeActionKind.Refactor.append('inline'); + public static readonly RefactorRewrite = CodeActionKind.Refactor.append('rewrite'); + + constructor( + public readonly value: string + ) { } + + public append(parts: string): CodeActionKind { + return new CodeActionKind(this.value ? this.value + CodeActionKind.sep + parts : parts); + } + + public contains(other: CodeActionKind): boolean { + return this.value === other.value || startsWith(other.value, this.value + CodeActionKind.sep); + } +} + + export class CodeLens { range: Range; @@ -1510,19 +1581,21 @@ export class Breakpoint { readonly condition?: string; readonly hitCondition?: string; - protected constructor(enabled: boolean, condition: string, hitCondition: string) { - this.enabled = enabled; - this.condition = condition; - this.hitCondition = hitCondition; - this.condition = condition; - this.hitCondition = hitCondition; + protected constructor(enabled?: boolean, condition?: string, hitCondition?: string) { + this.enabled = typeof enabled === 'boolean' ? enabled : true; + if (typeof condition === 'string') { + this.condition = condition; + } + if (typeof hitCondition === 'string') { + this.hitCondition = hitCondition; + } } } export class SourceBreakpoint extends Breakpoint { readonly location: Location; - constructor(enabled: boolean, condition: string, hitCondition: string, location: Location) { + constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string) { super(enabled, condition, hitCondition); this.location = location; } @@ -1531,7 +1604,7 @@ export class SourceBreakpoint extends Breakpoint { export class FunctionBreakpoint extends Breakpoint { readonly functionName: string; - constructor(enabled: boolean, condition: string, hitCondition: string, functionName: string) { + constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string) { super(enabled, condition, hitCondition); this.functionName = functionName; } diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index 2152866058e..5ead32afa25 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -7,40 +7,109 @@ import URI from 'vs/base/common/uri'; import Event, { Emitter } from 'vs/base/common/event'; import { normalize } from 'vs/base/common/paths'; -import { delta } from 'vs/base/common/arrays'; +import { delta as arrayDelta } from 'vs/base/common/arrays'; import { relative, dirname } from 'path'; import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext } from './extHost.protocol'; +import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext, MainThreadMessageServiceShape } from './extHost.protocol'; import * as vscode from 'vscode'; import { compare } from 'vs/base/common/strings'; import { TernarySearchTree } from 'vs/base/common/map'; +import { basenameOrAuthority, isEqual } from 'vs/base/common/resources'; +import { isLinux } from 'vs/base/common/platform'; +import { Severity } from 'vs/platform/message/common/message'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { localize } from 'vs/nls'; -class Workspace2 extends Workspace { +function isFolderEqual(folderA: URI, folderB: URI): boolean { + return isEqual(folderA, folderB, !isLinux); +} - static fromData(data: IWorkspaceData) { +function compareWorkspaceFolderByUri(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number { + return isFolderEqual(a.uri, b.uri) ? 0 : compare(a.uri.toString(), b.uri.toString()); +} + +function compareWorkspaceFolderByUriAndNameAndIndex(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number { + if (a.index !== b.index) { + return a.index < b.index ? -1 : 1; + } + + return isFolderEqual(a.uri, b.uri) ? compare(a.name, b.name) : compare(a.uri.toString(), b.uri.toString()); +} + +function delta(oldFolders: vscode.WorkspaceFolder[], newFolders: vscode.WorkspaceFolder[], compare: (a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder) => number): { removed: vscode.WorkspaceFolder[], added: vscode.WorkspaceFolder[] } { + const oldSortedFolders = oldFolders.slice(0).sort(compare); + const newSortedFolders = newFolders.slice(0).sort(compare); + + return arrayDelta(oldSortedFolders, newSortedFolders, compare); +} + +interface MutableWorkspaceFolder extends vscode.WorkspaceFolder { + name: string; + index: number; +} + +class ExtHostWorkspaceImpl extends Workspace { + + static toExtHostWorkspace(data: IWorkspaceData, previousConfirmedWorkspace?: ExtHostWorkspaceImpl, previousUnconfirmedWorkspace?: ExtHostWorkspaceImpl): { workspace: ExtHostWorkspaceImpl, added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[] } { if (!data) { - return null; - } else { - const { id, name, folders } = data; - return new Workspace2( - id, - name, - folders.map(({ uri, name, index }) => new WorkspaceFolder({ name, index, uri: URI.revive(uri) })) - ); + return { workspace: null, added: [], removed: [] }; } + + const { id, name, folders } = data; + const newWorkspaceFolders: vscode.WorkspaceFolder[] = []; + + // If we have an existing workspace, we try to find the folders that match our + // data and update their properties. It could be that an extension stored them + // for later use and we want to keep them "live" if they are still present. + const oldWorkspace = previousConfirmedWorkspace; + if (oldWorkspace) { + folders.forEach((folderData, index) => { + const folderUri = URI.revive(folderData.uri); + const existingFolder = ExtHostWorkspaceImpl._findFolder(previousUnconfirmedWorkspace || previousConfirmedWorkspace, folderUri); + + if (existingFolder) { + existingFolder.name = folderData.name; + existingFolder.index = folderData.index; + + newWorkspaceFolders.push(existingFolder); + } else { + newWorkspaceFolders.push({ uri: folderUri, name: folderData.name, index }); + } + }); + } else { + newWorkspaceFolders.push(...folders.map(({ uri, name, index }) => ({ uri: URI.revive(uri), name, index }))); + } + + // make sure to restore sort order based on index + newWorkspaceFolders.sort((f1, f2) => f1.index < f2.index ? -1 : 1); + + const workspace = new ExtHostWorkspaceImpl(id, name, newWorkspaceFolders); + const { added, removed } = delta(oldWorkspace ? oldWorkspace.workspaceFolders : [], workspace.workspaceFolders, compareWorkspaceFolderByUri); + + return { workspace, added, removed }; + } + + private static _findFolder(workspace: ExtHostWorkspaceImpl, folderUriToFind: URI): MutableWorkspaceFolder { + for (let i = 0; i < workspace.folders.length; i++) { + const folder = workspace.workspaceFolders[i]; + if (isFolderEqual(folder.uri, folderUriToFind)) { + return folder; + } + } + + return undefined; } private readonly _workspaceFolders: vscode.WorkspaceFolder[] = []; private readonly _structure = TernarySearchTree.forPaths(); - private constructor(id: string, name: string, folders: WorkspaceFolder[]) { - super(id, name, folders); + private constructor(id: string, name: string, folders: vscode.WorkspaceFolder[]) { + super(id, name, folders.map(f => new WorkspaceFolder(f))); // setup the workspace folder data structure - this.folders.forEach(({ name, uri, index }) => { - const workspaceFolder = { name, uri, index }; - this._workspaceFolders.push(workspaceFolder); - this._structure.set(workspaceFolder.uri.toString(), workspaceFolder); + folders.forEach(folder => { + this._workspaceFolders.push(folder); + this._structure.set(folder.uri.toString(), folder); }); } @@ -63,44 +132,116 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { private readonly _onDidChangeWorkspace = new Emitter(); private readonly _proxy: MainThreadWorkspaceShape; - private _workspace: Workspace2; + + private _confirmedWorkspace: ExtHostWorkspaceImpl; + private _unconfirmedWorkspace: ExtHostWorkspaceImpl; + + private _messageService: MainThreadMessageServiceShape; readonly onDidChangeWorkspace: Event = this._onDidChangeWorkspace.event; constructor(mainContext: IMainContext, data: IWorkspaceData) { this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace); - this._workspace = Workspace2.fromData(data); + this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService); + this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace; } // --- workspace --- get workspace(): Workspace { - return this._workspace; + return this._actualWorkspace; + } + + private get _actualWorkspace(): ExtHostWorkspaceImpl { + return this._unconfirmedWorkspace || this._confirmedWorkspace; } getWorkspaceFolders(): vscode.WorkspaceFolder[] { - if (!this._workspace) { + if (!this._actualWorkspace) { return undefined; - } else { - return this._workspace.workspaceFolders.slice(0); } + return this._actualWorkspace.workspaceFolders.slice(0); + } + + updateWorkspaceFolders(extension: IExtensionDescription, index: number, deleteCount: number, ...workspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[]): boolean { + const validatedDistinctWorkspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[] = []; + if (Array.isArray(workspaceFoldersToAdd)) { + workspaceFoldersToAdd.forEach(folderToAdd => { + if (URI.isUri(folderToAdd.uri) && !validatedDistinctWorkspaceFoldersToAdd.some(f => isFolderEqual(f.uri, folderToAdd.uri))) { + validatedDistinctWorkspaceFoldersToAdd.push({ uri: folderToAdd.uri, name: folderToAdd.name || basenameOrAuthority(folderToAdd.uri) }); + } + }); + } + + if (!!this._unconfirmedWorkspace) { + return false; // prevent accumulated calls without a confirmed workspace + } + + if ([index, deleteCount].some(i => typeof i !== 'number' || i < 0)) { + return false; // validate numbers + } + + if (deleteCount === 0 && validatedDistinctWorkspaceFoldersToAdd.length === 0) { + return false; // nothing to delete or add + } + + const currentWorkspaceFolders: MutableWorkspaceFolder[] = this._actualWorkspace ? this._actualWorkspace.workspaceFolders : []; + if (index + deleteCount > currentWorkspaceFolders.length) { + return false; // cannot delete more than we have + } + + // Simulate the updateWorkspaceFolders method on our data to do more validation + const newWorkspaceFolders = currentWorkspaceFolders.slice(0); + newWorkspaceFolders.splice(index, deleteCount, ...validatedDistinctWorkspaceFoldersToAdd.map(f => ({ uri: f.uri, name: f.name || basenameOrAuthority(f.uri) }))); + + for (let i = 0; i < newWorkspaceFolders.length; i++) { + const folder = newWorkspaceFolders[i]; + if (newWorkspaceFolders.some((otherFolder, index) => index !== i && isFolderEqual(folder.uri, otherFolder.uri))) { + return false; // cannot add the same folder multiple times + } + } + + newWorkspaceFolders.forEach((f, index) => f.index = index); // fix index + const { added, removed } = delta(currentWorkspaceFolders, newWorkspaceFolders, compareWorkspaceFolderByUriAndNameAndIndex); + if (added.length === 0 && removed.length === 0) { + return false; // nothing actually changed + } + + // Trigger on main side + if (this._proxy) { + const extName = extension.displayName || extension.name; + this._proxy.$updateWorkspaceFolders(extName, index, deleteCount, validatedDistinctWorkspaceFoldersToAdd).then(null, error => { + + // in case of an error, make sure to clear out the unconfirmed workspace + // because we cannot expect the acknowledgement from the main side for this + this._unconfirmedWorkspace = undefined; + + // show error to user + this._messageService.$showMessage(Severity.Error, localize('updateerror', "Extension '{0}' failed to update workspace folders: {1}", extName, error.toString()), { extension }, []); + }); + } + + // Try to accept directly + return this.trySetWorkspaceFolders(newWorkspaceFolders); } getWorkspaceFolder(uri: vscode.Uri, resolveParent?: boolean): vscode.WorkspaceFolder { - if (!this._workspace) { + if (!this._actualWorkspace) { return undefined; } - return this._workspace.getWorkspaceFolder(uri, resolveParent); + return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent); } getPath(): string { + // this is legacy from the days before having // multi-root and we keep it only alive if there // is just one workspace folder. - if (!this._workspace) { + if (!this._actualWorkspace) { return undefined; } - const { folders } = this._workspace; + + const { folders } = this._actualWorkspace; if (folders.length === 0) { return undefined; } @@ -130,7 +271,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { } if (typeof includeWorkspace === 'undefined') { - includeWorkspace = this.workspace.folders.length > 1; + includeWorkspace = this._actualWorkspace.folders.length > 1; } let result = relative(folder.uri.fsPath, path); @@ -140,27 +281,40 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { return normalize(result, true); } + private trySetWorkspaceFolders(folders: vscode.WorkspaceFolder[]): boolean { + + // Update directly here. The workspace is unconfirmed as long as we did not get an + // acknowledgement from the main side (via $acceptWorkspaceData) + if (this._actualWorkspace) { + this._unconfirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace({ + id: this._actualWorkspace.id, + name: this._actualWorkspace.name, + configuration: this._actualWorkspace.configuration, + folders + } as IWorkspaceData, this._actualWorkspace).workspace; + + return true; + } + + return false; + } + $acceptWorkspaceData(data: IWorkspaceData): void { - // keep old workspace folder, build new workspace, and - // capture new workspace folders. Compute delta between - // them send that as event - const oldRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; + const { workspace, added, removed } = ExtHostWorkspaceImpl.toExtHostWorkspace(data, this._confirmedWorkspace, this._unconfirmedWorkspace); - this._workspace = Workspace2.fromData(data); - const newRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; + // Update our workspace object. We have a confirmed workspace, so we drop our + // unconfirmed workspace. + this._confirmedWorkspace = workspace; + this._unconfirmedWorkspace = undefined; - const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareWorkspaceFolder); + // Events this._onDidChangeWorkspace.fire(Object.freeze({ added: Object.freeze(added), removed: Object.freeze(removed) })); } - private static _compareWorkspaceFolder(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number { - return compare(a.uri.toString(), b.uri.toString()); - } - // --- search --- findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults?: number, token?: vscode.CancellationToken): Thenable { diff --git a/src/vs/workbench/browser/actions.ts b/src/vs/workbench/browser/actions.ts index 12ac79bfc78..e15e84abf60 100644 --- a/src/vs/workbench/browser/actions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -169,7 +169,7 @@ export function prepareActions(actions: IAction[]): IAction[] { for (let l = 0; l < actions.length; l++) { const a = actions[l]; if (types.isUndefinedOrNull(a.order)) { - a.order = lastOrder++; + a.order = ++lastOrder; orderOffset++; } else { a.order += orderOffset; diff --git a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts index 2dc5bab450f..d338760c2c3 100644 --- a/src/vs/workbench/browser/actions/toggleSidebarPosition.ts +++ b/src/vs/workbench/browser/actions/toggleSidebarPosition.ts @@ -16,7 +16,7 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur export class ToggleSidebarPositionAction extends Action { public static readonly ID = 'workbench.action.toggleSidebarPosition'; - public static readonly LABEL = nls.localize('toggleLocation', "Toggle Side Bar Location"); + public static readonly LABEL = nls.localize('toggleSidebarPosition', "Toggle Side Bar Position"); private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location'; @@ -40,4 +40,4 @@ export class ToggleSidebarPositionAction extends Action { } const registry = Registry.as(Extensions.WorkbenchActions); -registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Location', nls.localize('view', "View")); \ No newline at end of file +registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Position', nls.localize('view', "View")); diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 81b49fbed8d..371db68f7da 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -451,7 +451,6 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.statusbarHeight = isStatusbarHidden ? 0 : this.partLayoutInfo.statusbar.height; this.titlebarHeight = isTitlebarHidden ? 0 : this.partLayoutInfo.titlebar.height / getZoomFactor(); // adjust for zoom prevention - const previousMaxPanelHeight = this.sidebarHeight - this.partLayoutInfo.editor.minHeight; this.sidebarHeight = this.workbenchSize.height - this.statusbarHeight - this.titlebarHeight; let sidebarSize = new Dimension(this.sidebarWidth, this.sidebarHeight); @@ -468,9 +467,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal panelHeight = 0; panelWidth = 0; } else if (panelPosition === Position.BOTTOM) { - if (this.panelHeight === previousMaxPanelHeight) { - panelHeight = maxPanelHeight; - } else if (this.panelHeight > 0) { + if (this.panelHeight > 0) { panelHeight = Math.min(maxPanelHeight, Math.max(this.partLayoutInfo.panel.minHeight, this.panelHeight)); } else { panelHeight = sidebarSize.height * DEFAULT_PANEL_SIZE_COEFFICIENT; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 9d52f097832..122d34883f6 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -93,10 +93,10 @@ export class ActivitybarPart extends Part { return this.compositeBar.showActivity(viewletOrActionId, badge, clazz, priority); } - return this.showGlobalActivity(viewletOrActionId, badge); + return this.showGlobalActivity(viewletOrActionId, badge, clazz); } - private showGlobalActivity(globalActivityId: string, badge: IBadge): IDisposable { + private showGlobalActivity(globalActivityId: string, badge: IBadge, clazz?: string): IDisposable { if (!badge) { throw illegalArgument('badge'); } @@ -106,7 +106,7 @@ export class ActivitybarPart extends Part { throw illegalArgument('globalActivityId'); } - action.setBadge(badge); + action.setBadge(badge, clazz); return toDisposable(() => action.setBadge(undefined)); } @@ -217,12 +217,4 @@ export class ActivitybarPart extends Part { super.dispose(); } - - public shutdown(): void { - // Persist Hidden State - this.compositeBar.store(); - - // Pass to super - super.shutdown(); - } } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index 3cd5c0e3e77..b08ad7ef369 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -371,6 +371,7 @@ export class CompositeBar implements ICompositeBar { const visibleComposites = this.getVisibleComposites(); let unpinPromise: TPromise; + // remove from pinned const index = this.pinnedComposites.indexOf(compositeId); this.pinnedComposites.splice(index, 1); @@ -402,6 +403,9 @@ export class CompositeBar implements ICompositeBar { unpinPromise.then(() => { this.updateCompositeSwitcher(); }); + + // Persist + this.savePinnedComposites(); } public isPinned(compositeId: string): boolean { @@ -420,6 +424,9 @@ export class CompositeBar implements ICompositeBar { if (update) { this.updateCompositeSwitcher(); } + + // Persist + this.savePinnedComposites(); }); } @@ -449,6 +456,9 @@ export class CompositeBar implements ICompositeBar { setTimeout(() => { this.updateCompositeSwitcher(); }, 0); + + // Persist + this.savePinnedComposites(); } public layout(dimension: Dimension): void { @@ -472,7 +482,7 @@ export class CompositeBar implements ICompositeBar { this.updateCompositeSwitcher(); } - public store(): void { + private savePinnedComposites(): void { this.storageService.store(this.options.storageId, JSON.stringify(this.pinnedComposites), StorageScope.GLOBAL); } diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts index 6c4f3102f84..61b5c8d5697 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBarActions.ts @@ -12,7 +12,7 @@ import * as dom from 'vs/base/browser/dom'; import { Builder, $ } from 'vs/base/browser/builder'; import { BaseActionItem, IBaseActionItemOptions, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { dispose } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable, empty, toDisposable } from 'vs/base/common/lifecycle'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; import { TextBadge, NumberBadge, IBadge, IconBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; @@ -53,6 +53,7 @@ export interface ICompositeBar { export class ActivityAction extends Action { private badge: IBadge; + private clazz: string | undefined; private _onDidChangeBadge = new Emitter(); constructor(private _activity: IActivity) { @@ -85,8 +86,13 @@ export class ActivityAction extends Action { return this.badge; } - public setBadge(badge: IBadge): void { + public getClass(): string | undefined { + return this.clazz; + } + + public setBadge(badge: IBadge, clazz?: string): void { this.badge = badge; + this.clazz = clazz; this._onDidChangeBadge.fire(this); } } @@ -110,6 +116,7 @@ export class ActivityActionItem extends BaseActionItem { protected options: IActivityActionItemOptions; private $badgeContent: Builder; + private badgeDisposable: IDisposable = empty; private mouseUpTimeout: number; constructor( @@ -199,7 +206,10 @@ export class ActivityActionItem extends BaseActionItem { this.updateStyles(); } - protected updateBadge(badge: IBadge): void { + protected updateBadge(badge: IBadge, clazz?: string): void { + this.badgeDisposable.dispose(); + this.badgeDisposable = empty; + this.$badgeContent.empty(); this.$badge.hide(); @@ -234,6 +244,11 @@ export class ActivityActionItem extends BaseActionItem { else if (badge instanceof ProgressBadge) { this.$badge.show(); } + + if (clazz) { + this.$badge.addClass(clazz); + this.badgeDisposable = toDisposable(() => this.$badge.removeClass(clazz)); + } } // Title @@ -259,7 +274,7 @@ export class ActivityActionItem extends BaseActionItem { private handleBadgeChangeEvenet(): void { const action = this.getAction(); if (action instanceof ActivityAction) { - this.updateBadge(action.getBadge()); + this.updateBadge(action.getBadge(), action.getClass()); } } diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index 282705c8e74..b4cea8223f8 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -10,7 +10,6 @@ import Event, { Emitter } from 'vs/base/common/event'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { Dimension, Builder, $ } from 'vs/base/browser/builder'; -import { ResourceViewer } from 'vs/base/browser/ui/resourceviewer/resourceViewer'; import { EditorModel, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; @@ -19,6 +18,7 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { ResourceViewerContext, ResourceViewer } from 'vs/workbench/browser/parts/editor/resourceViewer'; /* * This class is only intended to be subclassed and not instantiated. @@ -29,6 +29,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { private binaryContainer: Builder; private scrollbar: DomScrollableElement; + private resourceViewerContext: ResourceViewerContext; constructor( id: string, @@ -87,7 +88,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { // Render Input const model = resolvedModel; - ResourceViewer.show( + this.resourceViewerContext = ResourceViewer.show( { name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag(), mime: model.getMime() }, this.binaryContainer, this.scrollbar, @@ -132,6 +133,9 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { // Pass on to Binary Container this.binaryContainer.size(dimension.width, dimension.height); this.scrollbar.scanDomNode(); + if (this.resourceViewerContext) { + this.resourceViewerContext.layout(dimension); + } } public focus(): void { @@ -146,4 +150,4 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { super.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 0601bf43044..5e459221828 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -403,12 +403,12 @@ editorCommands.setup(); // Touch Bar if (isMacintosh) { MenuRegistry.appendMenuItem(MenuId.TouchBarContext, { - command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, iconPath: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/back-tb.png')).fsPath }, + command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, iconPath: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/back-tb.png')).fsPath } }, group: 'navigation' }); MenuRegistry.appendMenuItem(MenuId.TouchBarContext, { - command: { id: NavigateForwardAction.ID, title: NavigateForwardAction.LABEL, iconPath: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/forward-tb.png')).fsPath }, + command: { id: NavigateForwardAction.ID, title: NavigateForwardAction.LABEL, iconPath: { dark: URI.parse(require.toUrl('vs/workbench/browser/parts/editor/media/forward-tb.png')).fsPath } }, group: 'navigation' }); } diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 81e001915bb..ae87fa3a82a 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -9,7 +9,7 @@ import nls = require('vs/nls'); import { Action } from 'vs/base/common/actions'; import { mixin } from 'vs/base/common/objects'; import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService'; -import { EditorInput, TextEditorOptions, EditorOptions, IEditorIdentifier, ActiveEditorMoveArguments, ActiveEditorMovePositioning, EditorCommands, ConfirmResult } from 'vs/workbench/common/editor'; +import { EditorInput, TextEditorOptions, EditorOptions, IEditorIdentifier, ActiveEditorMoveArguments, ActiveEditorMovePositioning, EditorCommands, ConfirmResult, IEditorCommandsContext } from 'vs/workbench/common/editor'; import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -38,10 +38,11 @@ export class SplitEditorAction extends Action { super(id, label, 'split-editor-action'); } - public run(context?: IEditorIdentifier): TPromise { + public run(context?: IEditorCommandsContext): TPromise { let editorToSplit: IEditor; if (context) { - editorToSplit = this.editorService.getVisibleEditors()[this.editorGroupService.getStacksModel().positionOfGroup(context.group)]; + const stacks = this.editorGroupService.getStacksModel(); + editorToSplit = this.editorService.getVisibleEditors()[stacks.positionOfGroup(stacks.getGroup(context.groupId))]; } else { editorToSplit = this.editorService.getActiveEditor(); } diff --git a/src/vs/workbench/browser/parts/editor/editorAreaDropHandler.ts b/src/vs/workbench/browser/parts/editor/editorAreaDropHandler.ts index 587ceeb9128..17920141664 100644 --- a/src/vs/workbench/browser/parts/editor/editorAreaDropHandler.ts +++ b/src/vs/workbench/browser/parts/editor/editorAreaDropHandler.ts @@ -12,7 +12,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import URI from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { BACKUP_FILE_RESOLVE_OPTIONS, IBackupFileService } from 'vs/workbench/services/backup/common/backup'; +import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { TPromise } from 'vs/base/common/winjs.base'; import { Schemas } from 'vs/base/common/network'; @@ -20,6 +20,8 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Position } from 'vs/platform/editor/common/editor'; import { onUnexpectedError } from 'vs/base/common/errors'; +import { DefaultEndOfLine } from 'vs/editor/common/model'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; /** * Shared function across some editor components to handle drag & drop of external resources. E.g. of folders and workspace files @@ -37,6 +39,7 @@ export class EditorAreaDropHandler { @IEditorGroupService private groupService: IEditorGroupService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IConfigurationService private configurationService: IConfigurationService ) { } @@ -107,13 +110,22 @@ export class EditorAreaDropHandler { } // Resolve the contents of the dropped dirty resource from source - return this.textFileService.resolveTextContent(droppedDirtyEditor.backupResource, BACKUP_FILE_RESOLVE_OPTIONS).then(content => { + return this.backupFileService.resolveBackupContent(droppedDirtyEditor.backupResource).then(content => { // Set the contents of to the resource to the target - return this.backupFileService.backupResource(droppedDirtyEditor.resource, this.backupFileService.parseBackupContent(content.value)); + return this.backupFileService.backupResource(droppedDirtyEditor.resource, content.create(this.getDefaultEOL()).createSnapshot(true)); }).then(() => false, () => false /* ignore any error */); } + private getDefaultEOL(): DefaultEndOfLine { + const eol = this.configurationService.getValue('files.eol'); + if (eol === '\r\n') { + return DefaultEndOfLine.CRLF; + } + + return DefaultEndOfLine.LF; + } + private handleWorkspaceFileDrop(resources: (IDraggedResource | IDraggedEditor)[]): TPromise { const externalResources = resources.filter(d => d.isExternal).map(d => d.resource); diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index a09a31f09cf..f31156a4099 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -8,12 +8,12 @@ import * as types from 'vs/base/common/types'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; -import { ActiveEditorMoveArguments, ActiveEditorMovePositioning, ActiveEditorMovePositioningBy, EditorCommands, TextCompareEditorVisible, EditorInput, IEditorIdentifier } from 'vs/workbench/common/editor'; +import { ActiveEditorMoveArguments, ActiveEditorMovePositioning, ActiveEditorMovePositioningBy, EditorCommands, TextCompareEditorVisible, EditorInput, IEditorIdentifier, IEditorCommandsContext } from 'vs/workbench/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditor, Position, POSITIONS, Direction, IEditorInput } from 'vs/platform/editor/common/editor'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor'; -import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel'; +import { EditorStacksModel, EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; @@ -190,10 +190,18 @@ function registerDiffEditorCommands(): void { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: void 0, - handler: (accessor) => { + handler: (accessor, resource, context: IEditorCommandsContext) => { const editorService = accessor.get(IWorkbenchEditorService); + const editorGroupService = accessor.get(IEditorGroupService); + + let editor: IEditor; + if (context) { + const position = positionAndInput(editorGroupService, editorService, context).position; + editor = editorService.getVisibleEditors()[position]; + } else { + editor = editorService.getActiveEditor(); + } - const editor = editorService.getActiveEditor(); if (editor instanceof TextDiffEditor) { const control = editor.getControl(); const isInlineMode = !control.renderSideBySide; @@ -262,14 +270,24 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U), - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); + const model = editorGroupService.getStacksModel(); const editorService = accessor.get(IWorkbenchEditorService); - const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService)); - const positions = contexts.map(context => positionAndInput(editorGroupService, editorService, context).position); + const contexts = getMultiSelectedEditorContexts(toEditorIdentifier(context, editorGroupService), accessor.get(IListService)); - return TPromise.join(distinct(positions.filter(p => typeof p === 'number')) - .map(position => editorService.closeEditors(position, { unmodifiedOnly: true }))); + let positionOne: { unmodifiedOnly: boolean } = void 0; + let positionTwo: { unmodifiedOnly: boolean } = void 0; + let positionThree: { unmodifiedOnly: boolean } = void 0; + contexts.forEach(c => { + switch (model.positionOfGroup(c.group)) { + case Position.ONE: positionOne = { unmodifiedOnly: true }; break; + case Position.TWO: positionTwo = { unmodifiedOnly: true }; break; + case Position.THREE: positionThree = { unmodifiedOnly: true }; break; + } + }); + + return editorService.closeEditors({ positionOne, positionTwo, positionThree }); } }); @@ -278,15 +296,18 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W), - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); - const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService)); - const positions = contexts.map(context => positionAndInput(editorGroupService, editorService, context).position); - const distinctPositions = distinct(positions.filter(p => typeof p === 'number')); + const contexts = getMultiSelectedEditorContexts(toEditorIdentifier(context, editorGroupService), accessor.get(IListService)); + const distinctGroups = distinct(contexts.map(c => c.group)); - if (distinctPositions.length) { - return editorService.closeEditors(distinctPositions); + if (distinctGroups.length) { + return editorService.closeEditors(distinctGroups.map(g => editorGroupService.getStacksModel().positionOfGroup(g))); + } + const activeEditor = editorService.getActiveEditor(); + if (activeEditor) { + return editorService.closeEditors(activeEditor.position); } return TPromise.as(false); @@ -299,43 +320,45 @@ function registerEditorCommands() { when: void 0, primary: KeyMod.CtrlCmd | KeyCode.KEY_W, win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] }, - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); - const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService)); + const contexts = getMultiSelectedEditorContexts(toEditorIdentifier(context, editorGroupService), accessor.get(IListService)); const groups = distinct(contexts.map(context => context.group)); const editorsToClose = new Map(); - if (groups.length === 0) { + groups.forEach(group => { + const position = editorGroupService.getStacksModel().positionOfGroup(group); + if (position >= 0) { + editorsToClose.set(position, contexts.map(c => { + if (group === c.group) { + let input = c ? c.editor : void 0; + if (!input) { + + // Get Top Editor at Position + const visibleEditors = editorService.getVisibleEditors(); + if (visibleEditors[position]) { + input = visibleEditors[position].input; + } + } + + return input; + } + + return void 0; + }).filter(input => !!input)); + } + }); + + if (editorsToClose.size === 0) { const activeEditor = editorService.getActiveEditor(); if (activeEditor) { return editorService.closeEditor(activeEditor.position, activeEditor.input); } } - groups.forEach(group => { - const position = editorGroupService.getStacksModel().positionOfGroup(group); - editorsToClose.set(position, contexts.map(c => { - if (group === c.group) { - let input = c ? c.editor : undefined; - if (!input) { - - // Get Top Editor at Position - const visibleEditors = editorService.getVisibleEditors(); - if (visibleEditors[position]) { - input = visibleEditors[position].input; - } - } - - return input; - } - - return undefined; - }).filter(input => !!input)); - }); - return editorService.closeEditors({ positionOne: editorsToClose.get(Position.ONE), positionTwo: editorsToClose.get(Position.TWO), @@ -350,10 +373,10 @@ function registerEditorCommands() { when: void 0, primary: void 0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T }, - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); - const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService)); + const contexts = getMultiSelectedEditorContexts(toEditorIdentifier(context, editorGroupService), accessor.get(IListService)); const groups = distinct(contexts.map(context => context.group)); const editorsToClose = new Map(); @@ -363,7 +386,7 @@ function registerEditorCommands() { return c.editor; } - return undefined; + return void 0; }).filter(input => !!input); const toClose = group.getEditors().filter(input => inputsToSkip.indexOf(input) === -1); @@ -383,11 +406,11 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: void 0, - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); - const { position, input } = positionAndInput(editorGroupService, editorService, editorContext); + const { position, input } = positionAndInput(editorGroupService, editorService, context); if (typeof position === 'number' && input) { return editorService.closeEditors(position, { except: input, direction: Direction.RIGHT }); @@ -402,11 +425,11 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.Enter), - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorIdentifier | IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); - const { position, input } = positionAndInput(editorGroupService, editorService, editorContext); + const { position, input } = positionAndInput(editorGroupService, editorService, context); if (typeof position === 'number' && input) { return editorGroupService.pinEditor(position, input); @@ -421,7 +444,7 @@ function registerEditorCommands() { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: void 0, primary: void 0, - handler: (accessor, resource: URI, editorContext: IEditorIdentifier) => { + handler: (accessor, resource: URI, context: IEditorCommandsContext) => { const editorGroupService = accessor.get(IEditorGroupService); const editorService = accessor.get(IWorkbenchEditorService); const quickOpenService = accessor.get(IQuickOpenService); @@ -432,7 +455,7 @@ function registerEditorCommands() { return quickOpenService.show(NAVIGATE_ALL_EDITORS_GROUP_PREFIX); } - const { position } = positionAndInput(editorGroupService, editorService, editorContext); + const { position } = positionAndInput(editorGroupService, editorService, context); switch (position) { case Position.TWO: @@ -466,7 +489,10 @@ function registerEditorCommands() { }); } -function positionAndInput(editorGroupService: IEditorGroupService, editorService: IWorkbenchEditorService, editorContext?: IEditorIdentifier): { position: Position, input: IEditorInput } { +function positionAndInput(editorGroupService: IEditorGroupService, editorService: IWorkbenchEditorService, context?: IEditorIdentifier | IEditorCommandsContext): { position: Position, input: IEditorInput } { + + // Resolve from context + const editorContext = toEditorIdentifier(context, editorGroupService); let position = editorContext ? editorGroupService.getStacksModel().positionOfGroup(editorContext.group) : null; let input = editorContext ? editorContext.editor : null; @@ -481,23 +507,53 @@ function positionAndInput(editorGroupService: IEditorGroupService, editorService } export function getMultiSelectedEditorContexts(editorContext: IEditorIdentifier, listService: IListService): IEditorIdentifier[] { - // TODO@Isidor this method is not nice since it assumes it is working on open editors view and maps elements on top of that - const list = listService.lastFocusedList; - // Mapping for open editors view - const elementToContext = element => element && element.editorGroup && element.editorInput ? { group: element.editorGroup, editor: element.editorInput } : { group: element, editor: undefined }; + const elementToContext = (element: IEditorIdentifier | EditorGroup) => element instanceof EditorGroup ? { group: element, editor: void 0 } : element; + // First check for a focused list to return the selected items from + const list = listService.lastFocusedList; if (list instanceof List && list.isDOMFocused()) { const selection = list.getSelectedElements(); const focus = list.getFocusedElements(); + // Only respect selection if it contains focused element if (focus.length && selection && selection.indexOf(focus[0]) >= 0) { - return list.getSelectedElements().map(elementToContext); + return list.getSelectedElements().filter(e => e instanceof EditorGroup || isEditorIdentifier(e)).map(elementToContext); } - if (focus) { - return focus.map(elementToContext); + if (focus.length) { + return focus.filter(e => e instanceof EditorGroup || isEditorIdentifier(e)).map(elementToContext); } } + // Otherwise go with passed in context return !!editorContext ? [editorContext] : []; } + +function isEditorIdentifier(object: any): object is IEditorIdentifier { + const identifier = object as IEditorIdentifier; + + return identifier && !!identifier.group && !!identifier.editor; +} + +function isEditorGroupContext(object: any): object is IEditorCommandsContext { + const context = object as IEditorCommandsContext; + + return context && typeof context.groupId === 'number'; +} + +function toEditorIdentifier(object: IEditorIdentifier | IEditorCommandsContext, editorGroupService: IEditorGroupService): IEditorIdentifier { + if (isEditorIdentifier(object)) { + return object as IEditorIdentifier; + } + + if (isEditorGroupContext(object)) { + const stacks = editorGroupService.getStacksModel(); + const group = stacks.getGroup(object.groupId); + return { + group, + editor: typeof object.editorIndex === 'number' ? group.getEditor(object.editorIndex) : void 0 + }; + } + + return void 0; +} \ No newline at end of file diff --git a/src/vs/base/browser/ui/resourceviewer/resourceviewer.css b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css similarity index 83% rename from src/vs/base/browser/ui/resourceviewer/resourceviewer.css rename to src/vs/workbench/browser/parts/editor/media/resourceviewer.css index c4badd1d2c5..54dac885b18 100644 --- a/src/vs/base/browser/ui/resourceviewer/resourceviewer.css +++ b/src/vs/workbench/browser/parts/editor/media/resourceviewer.css @@ -16,10 +16,8 @@ padding: 10px 10px 0 10px; background-position: 0 0, 8px 8px; background-size: 16px 16px; -} - -.monaco-resource-viewer.image.full-size { - padding: 0; + display: flex; + box-sizing: border-box; } .vs .monaco-resource-viewer.image { @@ -34,18 +32,25 @@ linear-gradient(45deg, rgb(20, 20, 20) 25%, transparent 25%, transparent 75%, rgb(20, 20, 20) 75%, rgb(20, 20, 20)); } -.monaco-resource-viewer img { - max-width: 100%; - max-height: calc(100% - 10px); /* somehow this prevents scrollbars from showing up */ +.monaco-resource-viewer img.pixelated { + image-rendering: pixelated; } -.monaco-resource-viewer.oversized img { +.monaco-resource-viewer img.scale-to-fit { + max-width: 100%; + max-height: 100%; + object-fit: contain; +} + +.monaco-resource-viewer img { + margin: auto; +} + +.monaco-resource-viewer.zoom-in { cursor: zoom-in; } -.monaco-resource-viewer.full-size img { - max-width: initial; - max-height: initial; +.monaco-resource-viewer.zoom-out { cursor: zoom-out; } diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 34cae60469c..8d0c4ef497f 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/notabstitle'; import errors = require('vs/base/common/errors'); -import { IEditorGroup, toResource } from 'vs/workbench/common/editor'; +import { toResource } from 'vs/workbench/common/editor'; import DOM = require('vs/base/browser/dom'); import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { ResourceLabel } from 'vs/workbench/browser/labels'; @@ -19,12 +19,6 @@ export class NoTabsTitleControl extends TitleControl { private titleContainer: HTMLElement; private editorLabel: ResourceLabel; - public setContext(group: IEditorGroup): void { - super.setContext(group); - - this.editorActionsToolbar.context = { group }; - } - public create(parent: HTMLElement): void { super.create(parent); diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts new file mode 100644 index 00000000000..4e3d9571b6d --- /dev/null +++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts @@ -0,0 +1,546 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/css!./media/resourceviewer'; +import nls = require('vs/nls'); +import mimes = require('vs/base/common/mime'); +import URI from 'vs/base/common/uri'; +import paths = require('vs/base/common/paths'); +import { Builder, $, Dimension } from 'vs/base/browser/builder'; +import DOM = require('vs/base/browser/dom'); +import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { LRUCache } from 'vs/base/common/map'; +import { Schemas } from 'vs/base/common/network'; +import { clamp } from 'vs/base/common/numbers'; +import { Themable } from 'vs/workbench/common/theme'; +import { IStatusbarItem, StatusbarItemDescriptor, IStatusbarRegistry, Extensions, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { } from 'vs/platform/workspace/common/workspace'; +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { Action } from 'vs/base/common/actions'; +import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; +import { memoize } from 'vs/base/common/decorators'; + +interface MapExtToMediaMimes { + [index: string]: string; +} + +// Known media mimes that we can handle +const mapExtToMediaMimes: MapExtToMediaMimes = { + '.bmp': 'image/bmp', + '.gif': 'image/gif', + '.jpg': 'image/jpg', + '.jpeg': 'image/jpg', + '.jpe': 'image/jpg', + '.png': 'image/png', + '.tiff': 'image/tiff', + '.tif': 'image/tiff', + '.ico': 'image/x-icon', + '.tga': 'image/x-tga', + '.psd': 'image/vnd.adobe.photoshop', + '.webp': 'image/webp', + '.mid': 'audio/midi', + '.midi': 'audio/midi', + '.mp4a': 'audio/mp4', + '.mpga': 'audio/mpeg', + '.mp2': 'audio/mpeg', + '.mp2a': 'audio/mpeg', + '.mp3': 'audio/mpeg', + '.m2a': 'audio/mpeg', + '.m3a': 'audio/mpeg', + '.oga': 'audio/ogg', + '.ogg': 'audio/ogg', + '.spx': 'audio/ogg', + '.aac': 'audio/x-aac', + '.wav': 'audio/x-wav', + '.wma': 'audio/x-ms-wma', + '.mp4': 'video/mp4', + '.mp4v': 'video/mp4', + '.mpg4': 'video/mp4', + '.mpeg': 'video/mpeg', + '.mpg': 'video/mpeg', + '.mpe': 'video/mpeg', + '.m1v': 'video/mpeg', + '.m2v': 'video/mpeg', + '.ogv': 'video/ogg', + '.qt': 'video/quicktime', + '.mov': 'video/quicktime', + '.webm': 'video/webm', + '.mkv': 'video/x-matroska', + '.mk3d': 'video/x-matroska', + '.mks': 'video/x-matroska', + '.wmv': 'video/x-ms-wmv', + '.flv': 'video/x-flv', + '.avi': 'video/x-msvideo', + '.movie': 'video/x-sgi-movie' +}; + +export interface IResourceDescriptor { + resource: URI; + name: string; + size: number; + etag: string; + mime: string; +} + +enum ScaleDirection { + IN, OUT, +} + +class BinarySize { + public static readonly KB = 1024; + public static readonly MB = BinarySize.KB * BinarySize.KB; + public static readonly GB = BinarySize.MB * BinarySize.KB; + public static readonly TB = BinarySize.GB * BinarySize.KB; + + public static formatSize(size: number): string { + if (size < BinarySize.KB) { + return nls.localize('sizeB', "{0}B", size); + } + + if (size < BinarySize.MB) { + return nls.localize('sizeKB', "{0}KB", (size / BinarySize.KB).toFixed(2)); + } + + if (size < BinarySize.GB) { + return nls.localize('sizeMB', "{0}MB", (size / BinarySize.MB).toFixed(2)); + } + + if (size < BinarySize.TB) { + return nls.localize('sizeGB', "{0}GB", (size / BinarySize.GB).toFixed(2)); + } + + return nls.localize('sizeTB', "{0}TB", (size / BinarySize.TB).toFixed(2)); + } +} + +export interface ResourceViewerContext { + layout(dimension: Dimension); +} + +/** + * Helper to actually render the given resource into the provided container. Will adjust scrollbar (if provided) automatically based on loading + * progress of the binary resource. + */ +export class ResourceViewer { + public static show( + descriptor: IResourceDescriptor, + container: Builder, + scrollbar: DomScrollableElement, + openExternal: (uri: URI) => void, + metadataClb: (meta: string) => void + ): ResourceViewerContext { + // Ensure CSS class + $(container).setClass('monaco-resource-viewer'); + + if (ResourceViewer.isImageResource(descriptor)) { + return ImageView.create(container, descriptor, scrollbar, openExternal, metadataClb); + } + + GenericBinaryFileView.create(container, metadataClb, descriptor, scrollbar); + return null; + } + + private static isImageResource(descriptor: IResourceDescriptor) { + const mime = ResourceViewer.getMime(descriptor); + return mime.indexOf('image/') >= 0; + } + + private static getMime(descriptor: IResourceDescriptor): string { + let mime = descriptor.mime; + if (!mime && descriptor.resource.scheme === Schemas.file) { + const ext = paths.extname(descriptor.resource.toString()); + if (ext) { + mime = mapExtToMediaMimes[ext.toLowerCase()]; + } + } + return mime || mimes.MIME_BINARY; + } +} + +class ImageView { + private static readonly MAX_IMAGE_SIZE = BinarySize.MB; // showing images inline is memory intense, so we have a limit + private static readonly BASE64_MARKER = 'base64,'; + + public static create( + container: Builder, + descriptor: IResourceDescriptor, + scrollbar: DomScrollableElement, + openExternal: (uri: URI) => void, + metadataClb: (meta: string) => void + ): ResourceViewerContext | null { + if (ImageView.shouldShowImageInline(descriptor)) { + return InlineImageView.create(container, descriptor, scrollbar, metadataClb); + } + + LargeImageView.create(container, descriptor, openExternal); + return null; + } + + private static shouldShowImageInline(descriptor: IResourceDescriptor): boolean { + let skipInlineImage: boolean; + + // Data URI + if (descriptor.resource.scheme === Schemas.data) { + const base64MarkerIndex = descriptor.resource.path.indexOf(ImageView.BASE64_MARKER); + const hasData = base64MarkerIndex >= 0 && descriptor.resource.path.substring(base64MarkerIndex + ImageView.BASE64_MARKER.length).length > 0; + + skipInlineImage = !hasData || descriptor.size > ImageView.MAX_IMAGE_SIZE || descriptor.resource.path.length > ImageView.MAX_IMAGE_SIZE; + } + + // File URI + else { + skipInlineImage = typeof descriptor.size !== 'number' || descriptor.size > ImageView.MAX_IMAGE_SIZE; + } + + return !skipInlineImage; + } +} + +class LargeImageView { + public static create( + container: Builder, + descriptor: IResourceDescriptor, + openExternal: (uri: URI) => void + ) { + const imageContainer = $(container) + .empty() + .p({ + text: nls.localize('largeImageError', "The image is too large to display in the editor. ") + }); + + if (descriptor.resource.scheme !== Schemas.data) { + imageContainer.append($('a', { + role: 'button', + class: 'open-external', + text: nls.localize('resourceOpenExternalButton', "Open image using external program?") + }).on(DOM.EventType.CLICK, (e) => { + openExternal(descriptor.resource); + })); + } + } +} + +class GenericBinaryFileView { + public static create( + container: Builder, + metadataClb: (meta: string) => void, + descriptor: IResourceDescriptor, + scrollbar: DomScrollableElement + ) { + $(container) + .empty() + .span({ + text: nls.localize('nativeBinaryError', "The file will not be displayed in the editor because it is either binary, very large or uses an unsupported text encoding.") + }); + if (metadataClb) { + metadataClb(BinarySize.formatSize(descriptor.size)); + } + scrollbar.scanDomNode(); + } +} + +type Scale = number | 'fit'; + +class ZoomStatusbarItem extends Themable implements IStatusbarItem { + showTimeout: number; + public static instance: ZoomStatusbarItem; + + private statusBarItem: HTMLElement; + + private onSelectScale?: (scale: Scale) => void; + + constructor( + @IContextMenuService private contextMenuService: IContextMenuService, + @IEditorGroupService editorGroupService: IEditorGroupService, + @IThemeService themeService: IThemeService + ) { + super(themeService); + ZoomStatusbarItem.instance = this; + this.toUnbind.push(editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); + } + + private onEditorsChanged(): void { + this.hide(); + this.onSelectScale = undefined; + } + + public show(scale: Scale, onSelectScale: (scale: number) => void) { + clearTimeout(this.showTimeout); + this.showTimeout = setTimeout(() => { + this.onSelectScale = onSelectScale; + this.statusBarItem.style.display = 'block'; + this.updateLabel(scale); + }, 0); + } + + public hide() { + this.statusBarItem.style.display = 'none'; + } + + public render(container: HTMLElement): IDisposable { + if (!this.statusBarItem && container) { + this.statusBarItem = $(container).a() + .addClass('.zoom-statusbar-item') + .on('click', () => { + this.contextMenuService.showContextMenu({ + getAnchor: () => container, + getActions: () => TPromise.as(this.zoomActions) + }); + }) + .getHTMLElement(); + this.statusBarItem.style.display = 'none'; + } + return this; + } + + private updateLabel(scale: Scale) { + this.statusBarItem.textContent = ZoomStatusbarItem.zoomLabel(scale); + } + + @memoize + private get zoomActions(): Action[] { + const scales: Scale[] = [10, 5, 2, 1, 0.5, 0.25, 'fit']; + return scales.map(scale => + new Action('zoom.' + scale, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => { + if (this.onSelectScale) { + this.onSelectScale(scale); + } + return null; + })); + } + + private static zoomLabel(scale: Scale): string { + return scale === 'fit' + ? nls.localize('zoom.action.fit.label', 'Whole Image') + : `${+(scale * 100).toFixed(2)}%`; + } +} + +Registry.as(Extensions.Statusbar).registerStatusbarItem( + new StatusbarItemDescriptor(ZoomStatusbarItem, StatusbarAlignment.RIGHT, 101) +); + +interface ImageState { + scale: Scale; + offsetX: number; + offsetY: number; +} + +class InlineImageView { + private static readonly SCALE_PINCH_FACTOR = 0.05; + private static readonly SCALE_FACTOR = 1.5; + private static readonly MAX_SCALE = 20; + private static readonly MIN_SCALE = 0.1; + + /** + * Enable image-rendering: pixelated for images scaled by more than this. + */ + private static readonly PIXELATION_THRESHOLD = 3; + + /** + * Chrome is caching images very aggressively and so we use the ETag information to find out if + * we need to bypass the cache or not. We could always bypass the cache everytime we show the image + * however that has very bad impact on memory consumption because each time the image gets shown, + * memory grows (see also https://github.com/electron/electron/issues/6275) + */ + private static IMAGE_RESOURCE_ETAG_CACHE = new LRUCache(100); + + /** + * Store the scale and position of an image so it can be restored when changing editor tabs + */ + private static readonly imageStateCache = new LRUCache(100); + + public static create( + container: Builder, + descriptor: IResourceDescriptor, + scrollbar: DomScrollableElement, + metadataClb: (meta: string) => void + ) { + const context = { + layout(dimension: Dimension) { } + }; + + const cacheKey = descriptor.resource.toString(); + + let scaleDirection = ScaleDirection.IN; + const initialState: ImageState = InlineImageView.imageStateCache.get(cacheKey) || { scale: 'fit', offsetX: 0, offsetY: 0 }; + let scale = initialState.scale; + let img: Builder | null = null; + let imgElement: HTMLImageElement | null = null; + + function updateScale(newScale: Scale) { + if (!img || !imgElement.parentElement) { + return; + } + + if (newScale === 'fit') { + scale = 'fit'; + img.addClass('scale-to-fit'); + img.removeClass('pixelated'); + img.style('min-width', 'auto'); + img.style('width', 'auto'); + InlineImageView.imageStateCache.set(cacheKey, null); + } else { + const oldWidth = imgElement.width; + const oldHeight = imgElement.height; + + scale = clamp(newScale, InlineImageView.MIN_SCALE, InlineImageView.MAX_SCALE); + if (scale >= InlineImageView.PIXELATION_THRESHOLD) { + img.addClass('pixelated'); + } else { + img.removeClass('pixelated'); + } + + const { scrollTop, scrollLeft } = imgElement.parentElement; + const dx = (scrollLeft + imgElement.parentElement.clientWidth / 2) / imgElement.parentElement.scrollWidth; + const dy = (scrollTop + imgElement.parentElement.clientHeight / 2) / imgElement.parentElement.scrollHeight; + + img.removeClass('scale-to-fit'); + img.style('min-width', `${(imgElement.naturalWidth * scale)}px`); + img.style('width', `${(imgElement.naturalWidth * scale)}px`); + + const newWidth = imgElement.width; + const scaleFactor = (newWidth - oldWidth) / oldWidth; + + const newScrollLeft = ((oldWidth * scaleFactor * dx) + scrollLeft); + const newScrollTop = ((oldHeight * scaleFactor * dy) + scrollTop); + scrollbar.setScrollPosition({ + scrollLeft: newScrollLeft, + scrollTop: newScrollTop, + }); + + InlineImageView.imageStateCache.set(cacheKey, { scale: scale, offsetX: newScrollLeft, offsetY: newScrollTop }); + + } + ZoomStatusbarItem.instance.show(scale, updateScale); + scrollbar.scanDomNode(); + } + + function firstZoom() { + scale = imgElement.clientWidth / imgElement.naturalWidth; + updateScale(scale); + } + + $(container) + .on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent, c) => { + if (!img) { + return; + } + + if (e.altKey) { + scaleDirection = ScaleDirection.OUT; + c.removeClass('zoom-in').addClass('zoom-out'); + } + }) + .on(DOM.EventType.KEY_UP, (e: KeyboardEvent, c) => { + if (!img) { + return; + } + + if (!e.altKey) { + scaleDirection = ScaleDirection.IN; + c.removeClass('zoom-out').addClass('zoom-in'); + } + }) + .on(DOM.EventType.CLICK, (e: MouseEvent) => { + if (!img) { + return; + } + + if (e.button !== 0) { + return; + } + + // left click + if (scale === 'fit') { + firstZoom(); + } + + const scaleMultiplier = scaleDirection === ScaleDirection.IN + ? InlineImageView.SCALE_FACTOR + : 1 / InlineImageView.SCALE_FACTOR; + updateScale(scale as number * scaleMultiplier); + }) + .on(DOM.EventType.WHEEL, (e: WheelEvent) => { + if (!img) { + return; + } + // pinching is reported as scroll wheel + ctrl + if (!e.ctrlKey) { + return; + } + if (scale === 'fit') { + firstZoom(); + } + + // scrolling up, pinching out should increase the scale + const delta = -e.deltaY; + updateScale(scale as number + delta * InlineImageView.SCALE_PINCH_FACTOR); + }) + .on(DOM.EventType.SCROLL, () => { + if (!imgElement || !imgElement.parentElement || scale === 'fit') { + return; + } + + const entry = InlineImageView.imageStateCache.get(cacheKey); + if (entry) { + const { scrollTop, scrollLeft } = imgElement.parentElement; + InlineImageView.imageStateCache.set(cacheKey, { scale: entry.scale, offsetX: scrollLeft, offsetY: scrollTop }); + } + }); + + $(container) + .empty() + .addClass('image', 'zoom-in') + .img({ src: InlineImageView.imageSrc(descriptor) }) + .style('visibility', 'hidden') + .addClass('scale-to-fit') + .on(DOM.EventType.LOAD, (e, i) => { + img = i; + imgElement = img.getHTMLElement() as HTMLImageElement; + metadataClb(nls.localize('imgMeta', '{0}x{1} {2}', imgElement.naturalWidth, imgElement.naturalHeight, BinarySize.formatSize(descriptor.size))); + scrollbar.scanDomNode(); + img.style('visibility', 'visible'); + updateScale(scale); + if (initialState.scale !== 'fit') { + scrollbar.setScrollPosition({ + scrollLeft: initialState.offsetX, + scrollTop: initialState.offsetY, + }); + } + }); + + return context; + } + + private static imageSrc(descriptor: IResourceDescriptor): string { + if (descriptor.resource.scheme === Schemas.data) { + return descriptor.resource.toString(true /* skip encoding */); + } + + const src = descriptor.resource.toString(); + + let cached = InlineImageView.IMAGE_RESOURCE_ETAG_CACHE.get(src); + if (!cached) { + cached = { etag: descriptor.etag, src }; + InlineImageView.IMAGE_RESOURCE_ETAG_CACHE.set(src, cached); + } + + if (cached.etag !== descriptor.etag) { + cached.etag = descriptor.etag; + cached.src = `${src}?${Date.now()}`; // bypass cache with this trick + } + + return cached.src; + } +} + + diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 6ac7609d531..892dc38d274 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -118,12 +118,6 @@ export class TabsTitleControl extends TitleControl { return this.instantiationService.createChild(new ServiceCollection([IWorkbenchEditorService, delegatingEditorService])); } - public setContext(group: IEditorGroup): void { - super.setContext(group); - - this.editorActionsToolbar.context = { group }; - } - public create(parent: HTMLElement): void { super.create(parent); diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index d60983725ca..a4dba3d6963 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -15,7 +15,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { RunOnceScheduler } from 'vs/base/common/async'; import arrays = require('vs/base/common/arrays'); -import { IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IStacksModelChangeEvent, toResource } from 'vs/workbench/common/editor'; +import { IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IStacksModelChangeEvent, toResource, IEditorCommandsContext } from 'vs/workbench/common/editor'; import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -170,6 +170,8 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl public setContext(group: IEditorGroup): void { this.context = group; + + this.editorActionsToolbar.context = { groupId: group ? group.id : void 0 } as IEditorCommandsContext; } public hasContext(): boolean { @@ -310,7 +312,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl const titleBarMenu = this.menuService.createMenu(MenuId.EditorTitle, scopedContextKeyService); this.disposeOnEditorActions.push(titleBarMenu, titleBarMenu.onDidChange(_ => this.update())); - fillInActions(titleBarMenu, { arg: this.resourceContext.get() }, { primary, secondary }, this.contextMenuService); + fillInActions(titleBarMenu, { arg: this.resourceContext.get(), shouldForwardArgs: true }, { primary, secondary }, this.contextMenuService); } return { primary, secondary }; @@ -328,16 +330,20 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl // Update Editor Actions Toolbar let primaryEditorActions: IAction[] = []; let secondaryEditorActions: IAction[] = []; + + const editorActions = this.getEditorActions({ group, editor }); + + // Primary actions only for the active group if (isActive) { - const editorActions = this.getEditorActions({ group, editor }); primaryEditorActions = prepareActions(editorActions.primary); - if (isActive && editor instanceof EditorInput && editor.supportsSplitEditor()) { + if (editor instanceof EditorInput && editor.supportsSplitEditor()) { this.updateSplitActionEnablement(); primaryEditorActions.push(this.splitEditorAction); } - secondaryEditorActions = prepareActions(editorActions.secondary); } + secondaryEditorActions = prepareActions(editorActions.secondary); + const tabOptions = this.editorGroupService.getTabOptions(); const primaryEditorActionIds = primaryEditorActions.map(a => a.id); @@ -392,7 +398,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl this.contextMenuService.showContextMenu({ getAnchor: () => anchor, getActions: () => TPromise.as(actions), - getActionsContext: () => identifier, + getActionsContext: () => ({ groupId: identifier.group.id, editorIndex: identifier.group.indexOf(identifier.editor) } as IEditorCommandsContext), getKeyBinding: (action) => this.getKeybinding(action), onHide: (cancel) => { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 17228613cdd..1162557713b 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -250,14 +250,6 @@ export class PanelPart extends CompositePart implements IPanelService { return this.toolbarWidth.get(activePanel.getId()); } - - public shutdown(): void { - // Persist Hidden State - this.compositeBar.store(); - - // Pass to super - super.shutdown(); - } } registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index a3720fad8db..935b7d8bed5 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -54,7 +54,7 @@ import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { FileKind, IFileService } from 'vs/platform/files/common/files'; import { scoreItem, ScorerCache, compareItemsByScore, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; import { getBaseLabel } from 'vs/base/common/labels'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; const HELP_PREFIX = '?'; @@ -107,7 +107,6 @@ export class QuickOpenController extends Component implements IQuickOpenService @IConfigurationService private configurationService: IConfigurationService, @IInstantiationService private instantiationService: IInstantiationService, @IPartService private partService: IPartService, - @IListService private listService: IListService, @IEnvironmentService private environmentService: IEnvironmentService, @IThemeService themeService: IThemeService ) { @@ -311,7 +310,7 @@ export class QuickOpenController extends Component implements IQuickOpenService }, { inputPlaceHolder: options.placeHolder || '', keyboardSupport: false, - treeCreator: (container, config, opts) => new WorkbenchTree(container, config, opts, this.contextKeyService, this.listService, this.themeService) + treeCreator: (container, config, opts) => this.instantiationService.createInstance(WorkbenchTree, container, config, opts) } ); this.toUnbind.push(attachQuickOpenStyler(this.pickOpenWidget, this.themeService, { background: SIDE_BAR_BACKGROUND, foreground: SIDE_BAR_FOREGROUND })); @@ -569,7 +568,7 @@ export class QuickOpenController extends Component implements IQuickOpenService }, { inputPlaceHolder: this.hasHandler(HELP_PREFIX) ? nls.localize('quickOpenInput', "Type '?' to get help on the actions you can take from here") : '', keyboardSupport: false, - treeCreator: (container, config, opts) => new WorkbenchTree(container, config, opts, this.contextKeyService, this.listService, this.themeService) + treeCreator: (container, config, opts) => this.instantiationService.createInstance(WorkbenchTree, container, config, opts) } ); this.toUnbind.push(attachQuickOpenStyler(this.quickOpenWidget, this.themeService, { background: SIDE_BAR_BACKGROUND, foreground: SIDE_BAR_FOREGROUND })); diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index f3b98771b75..3cda0e9caf6 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -20,10 +20,17 @@ content: ' '; } -.file-icon-themable-tree.align-icons-and-twisties .monaco-tree-row:not(.has-children) .content::before { +.file-icon-themable-tree.align-icons-and-twisties .monaco-tree-row:not(.has-children) .content::before, +.file-icon-themable-tree.hide-arrows .monaco-tree-row .content::before { display: none; } +/** Show the twistie content if the parent has opt in icon **/ +.tree-explorer-viewlet-tree-view.file-icon-themable-tree.align-icons-and-twisties .monaco-tree-row:not(.has-children) .content.parent-has-icon::before, +.tree-explorer-viewlet-tree-view.file-icon-themable-tree.hide-arrows .monaco-tree-row .content.parent-has-icon::before { + display: inline-block; +} + .file-icon-themable-tree .monaco-tree-row.has-children.expanded .content::before { background-image: url("expanded.svg"); } @@ -49,10 +56,6 @@ background-image: url("collapsed-hc.svg"); } -.file-icon-themable-tree.hide-arrows .monaco-tree-row .content::before { - display: none; -} - .tree-explorer-viewlet-tree-view .monaco-tree .monaco-tree-row .custom-view-tree-node-item { display: flex; height: 22px; diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index a1cb7fc9468..98235ba28b6 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -26,7 +26,7 @@ import { ViewsRegistry, TreeItemCollapsibleState, ITreeItem, ITreeViewDataProvid import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IViewletViewOptions, IViewOptions, TreeViewsViewletPanel, FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { ResourceLabel } from 'vs/workbench/browser/labels'; import URI from 'vs/base/common/uri'; import { basename } from 'vs/base/common/paths'; @@ -48,9 +48,7 @@ export class TreeView extends TreeViewsViewletPanel { @IKeybindingService keybindingService: IKeybindingService, @IContextMenuService contextMenuService: IContextMenuService, @IInstantiationService private instantiationService: IInstantiationService, - @IListService private listService: IListService, - @IThemeService private themeService: IWorkbenchThemeService, - @IContextKeyService private contextKeyService: IContextKeyService, + @IThemeService themeService: IWorkbenchThemeService, @IExtensionService private extensionService: IExtensionService, @ICommandService private commandService: ICommandService ) { @@ -91,13 +89,10 @@ export class TreeView extends TreeViewsViewletPanel { const dataSource = this.instantiationService.createInstance(TreeDataSource, this.id); const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, this.menus); const controller = this.instantiationService.createInstance(TreeController, this.id, this.menus); - const tree = new FileIconThemableWorkbenchTree( + const tree = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, container.getHTMLElement(), { dataSource, renderer, controller }, - { keyboardSupport: false }, - this.contextKeyService, - this.listService, - this.themeService + { keyboardSupport: false } ); tree.contextKeyService.createKey(this.id, true); @@ -250,7 +245,8 @@ class TreeDataSource implements IDataSource { return children; }); } - return TPromise.as(null); + + return TPromise.as([]); } public shouldAutoexpand(tree: ITree, node: ITreeItem): boolean { @@ -267,6 +263,7 @@ class TreeDataSource implements IDataSource { } interface ITreeExplorerTemplateData { + container: HTMLElement; label: HTMLElement; resourceLabel: ResourceLabel; icon: HTMLElement; @@ -305,14 +302,13 @@ class TreeRenderer implements IRenderer { actionRunner: new MultipleSelectionActionRunner(() => tree.getSelection()) }); - return { label, resourceLabel, icon, actionBar }; + return { container, label, resourceLabel, icon, actionBar }; } public renderElement(tree: ITree, node: ITreeItem, templateId: string, templateData: ITreeExplorerTemplateData): void { const resource = node.resourceUri ? URI.revive(node.resourceUri) : null; const name = node.label || basename(resource.path); - const theme = this.themeService.getTheme(); - const icon = theme.type === LIGHT ? node.icon : node.iconDark; + const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark; // reset templateData.resourceLabel.clear(); @@ -336,6 +332,14 @@ class TreeRenderer implements IRenderer { templateData.actionBar.context = ({ $treeViewId: this.treeViewId, $treeItemHandle: node.handle }); templateData.actionBar.push(this.menus.getResourceActions(node), { icon: true, label: false }); + + // Fix when the theme do not show folder icons but parent has opt in icon. + DOM.toggleClass(templateData.container, 'parent-has-icon', this.hasParentHasOptInIcon(node, tree)); + } + + private hasParentHasOptInIcon(node: ITreeItem, tree: ITree): boolean { + const parent: ITreeItem = tree.getNavigator(node).parent(); + return parent ? !!(this.themeService.getTheme().type === LIGHT ? parent.icon : parent.iconDark) : false; } public disposeTemplate(tree: ITree, templateId: string, templateData: ITreeExplorerTemplateData): void { diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 5b7544394ff..1ab63b6f749 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -122,8 +122,10 @@ export abstract class TreeViewsViewletPanel extends ViewsViewletPanel { } setExpanded(expanded: boolean): void { - this.updateTreeVisibility(this.tree, expanded); - super.setExpanded(expanded); + if (this.isExpanded() !== expanded) { + this.updateTreeVisibility(this.tree, expanded); + super.setExpanded(expanded); + } } protected renderHeader(container: HTMLElement): void { @@ -784,4 +786,4 @@ export class FileIconThemableWorkbenchTree extends WorkbenchTree { this.disposables.push(themeService.onDidFileIconThemeChange(onFileIconThemeChange)); onFileIconThemeChange(themeService.getFileIconTheme()); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 03436fe0657..96b57287a71 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -788,6 +788,16 @@ export interface IEditorIdentifier { editor: IEditorInput; } +/** + * The editor commands context is used for editor commands (e.g. in the editor title) + * and we must ensure that the context is serializable because it potentially travels + * to the extension host! + */ +export interface IEditorCommandsContext { + groupId: GroupIdentifier; + editorIndex?: number; +} + export interface IEditorCloseEvent extends IEditorIdentifier { replaced: boolean; index: number; diff --git a/src/vs/workbench/common/editor/textEditorModel.ts b/src/vs/workbench/common/editor/textEditorModel.ts index 524ffbdf8d6..63f9d2e6ba9 100644 --- a/src/vs/workbench/common/editor/textEditorModel.ts +++ b/src/vs/workbench/common/editor/textEditorModel.ts @@ -5,7 +5,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { EndOfLinePreference, ITextModel, ITextBufferFactory } from 'vs/editor/common/model'; +import { ITextModel, ITextBufferFactory } from 'vs/editor/common/model'; import { IMode } from 'vs/editor/common/modes'; import { EditorModel } from 'vs/workbench/common/editor'; import URI from 'vs/base/common/uri'; @@ -13,6 +13,7 @@ import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { ITextSnapshot } from 'vs/platform/files/common/files'; /** * The base text editor model leverages the code editor model. This class is only intended to be subclassed and not instantiated. @@ -66,13 +67,13 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd /** * Creates the text editor model with the provided value, modeId (can be comma separated for multiple values) and optional resource URL. */ - protected createTextEditorModel(value: string | ITextBufferFactory, resource?: URI, modeId?: string): TPromise { + protected createTextEditorModel(value: ITextBufferFactory, resource?: URI, modeId?: string): TPromise { const firstLineText = this.getFirstLineText(value); const mode = this.getOrCreateMode(this.modeService, modeId, firstLineText); return TPromise.as(this.doCreateTextEditorModel(value, mode, resource)); } - private doCreateTextEditorModel(value: string | ITextBufferFactory, mode: TPromise, resource: URI): EditorModel { + private doCreateTextEditorModel(value: ITextBufferFactory, mode: TPromise, resource: URI): EditorModel { let model = resource && this.modelService.getModel(resource); if (!model) { model = this.modelService.createModel(value, mode, resource); @@ -90,24 +91,29 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd return this; } - protected getFirstLineText(value: string | ITextBufferFactory): string { - if (typeof value === 'string') { - const firstLineText = value.substr(0, 100); + protected getFirstLineText(value: ITextBufferFactory | ITextSnapshot): string { - let crIndex = firstLineText.indexOf('\r'); - if (crIndex < 0) { - crIndex = firstLineText.length; - } - - let lfIndex = firstLineText.indexOf('\n'); - if (lfIndex < 0) { - lfIndex = firstLineText.length; - } - - return firstLineText.substr(0, Math.min(crIndex, lfIndex)); - } else { - return value.getFirstLineText(100); + // text buffer factory + const textBufferFactory = value as ITextBufferFactory; + if (typeof textBufferFactory.getFirstLineText === 'function') { + return textBufferFactory.getFirstLineText(100); } + + // text snapshot + const textSnapshot = value as ITextSnapshot; + const firstLineText = textSnapshot.read().substr(0, 100); + + let crIndex = firstLineText.indexOf('\r'); + if (crIndex < 0) { + crIndex = firstLineText.length; + } + + let lfIndex = firstLineText.indexOf('\n'); + if (lfIndex < 0) { + lfIndex = firstLineText.length; + } + + return firstLineText.substr(0, Math.min(crIndex, lfIndex)); } /** @@ -122,7 +128,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd /** * Updates the text editor model with the provided value. If the value is the same as the model has, this is a no-op. */ - protected updateTextEditorModel(newValue: string | ITextBufferFactory): void { + protected updateTextEditorModel(newValue: ITextBufferFactory): void { if (!this.textEditorModel) { return; } @@ -130,13 +136,10 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd this.modelService.updateModel(this.textEditorModel, newValue); } - /** - * Returns the textual value of this editor model or null if it has not yet been created. - */ - public getValue(): string { + public createSnapshot(): ITextSnapshot { const model = this.textEditorModel; if (model) { - return model.getValue(EndOfLinePreference.TextDefined, true /* Preserve BOM */); + return model.createSnapshot(true /* Preserve BOM */); } return null; diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 9a817653721..ee33d7720af 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -10,16 +10,16 @@ import { IEncodingSupport } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import URI from 'vs/base/common/uri'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; -import { EndOfLinePreference } from 'vs/editor/common/model'; import { CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/files'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IMode } from 'vs/editor/common/modes'; import Event, { Emitter } from 'vs/base/common/event'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IBackupFileService, BACKUP_FILE_RESOLVE_OPTIONS } from 'vs/workbench/services/backup/common/backup'; -import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; +import { ITextBufferFactory } from 'vs/editor/common/model'; +import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; export class UntitledEditorModel extends BaseTextEditorModel implements IEncodingSupport { @@ -47,7 +47,6 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IBackupFileService private backupFileService: IBackupFileService, - @ITextFileService private textFileService: ITextFileService, @ITextResourceConfigurationService private configurationService: ITextResourceConfigurationService ) { super(modelService, modeService); @@ -113,14 +112,6 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin return this.versionId; } - public getValue(): string { - if (this.textEditorModel) { - return this.textEditorModel.getValue(EndOfLinePreference.TextDefined, true /* Preserve BOM */); - } - - return null; - } - public getModeId(): string { if (this.textEditorModel) { return this.textEditorModel.getLanguageIdentifier().language; @@ -172,18 +163,24 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin // Check for backups first return this.backupFileService.loadBackupResource(this.resource).then(backupResource => { if (backupResource) { - return this.textFileService.resolveTextContent(backupResource, BACKUP_FILE_RESOLVE_OPTIONS).then(rawTextContent => { - return this.backupFileService.parseBackupContent(rawTextContent.value); - }); + return this.backupFileService.resolveBackupContent(backupResource); } return null; - }).then(backupContent => { + }).then(backupTextBufferFactory => { + const hasBackup = !!backupTextBufferFactory; // untitled associated to file path are dirty right away as well as untitled with content - this.setDirty(this.hasAssociatedFilePath || !!backupContent); + this.setDirty(this.hasAssociatedFilePath || hasBackup); - return this.doLoad(backupContent || this.initialValue || '').then(model => { + let untitledContents: ITextBufferFactory; + if (backupTextBufferFactory) { + untitledContents = backupTextBufferFactory; + } else { + untitledContents = createTextBufferFactory(this.initialValue || ''); + } + + return this.doLoad(untitledContents).then(model => { // Encoding this.configuredEncoding = this.configurationService.getValue(this.resource, 'files.encoding'); @@ -198,7 +195,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin }); } - private doLoad(content: string): TPromise { + private doLoad(content: ITextBufferFactory): TPromise { // Create text editor model if not yet done if (!this.textEditorModel) { diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index f0a5ba05fad..94d13e96a34 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -46,6 +46,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IExtensionService, ActivationTimes } from 'vs/platform/extensions/common/extensions'; import { getEntries } from 'vs/base/common/performance'; import { IEditor } from 'vs/platform/editor/common/editor'; +import { IIssueService } from 'vs/platform/issue/common/issue'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder } from 'vs/platform/theme/common/colorRegistry'; +import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; // --- actions @@ -324,14 +328,6 @@ export class ShowStartupPerformance extends Action { (console).table(this.getStartupMetricsTable(nodeModuleLoadTime)); - if (this.environmentService.performance) { - const data = this.analyzeLoaderStats(); - for (let type in data) { - (console).groupCollapsed(`Loader: ${type}`); - (console).table(data[type]); - (console).groupEnd(); - } - } (console).groupEnd(); @@ -367,6 +363,7 @@ export class ShowStartupPerformance extends Action { if (metrics.initialStartup) { table.push({ Topic: '[main] start => app.isReady', 'Took (ms)': metrics.timers.ellapsedAppReady }); + table.push({ Topic: '[main] nls:start => nls:end', 'Took (ms)': metrics.timers.ellapsedNlsGeneration }); table.push({ Topic: '[main] app.isReady => window.loadUrl()', 'Took (ms)': metrics.timers.ellapsedWindowLoad }); } @@ -422,114 +419,6 @@ export class ShowStartupPerformance extends Action { return { table: result, duration: Math.round(total) }; } - - private analyzeLoaderStats(): { [type: string]: any[] } { - const stats = (require).getStats().slice(0).sort((a: ILoaderEvent, b: ILoaderEvent) => { - if (a.detail < b.detail) { - return -1; - } else if (a.detail > b.detail) { - return 1; - } else if (a.type < b.type) { - return -1; - } else if (a.type > b.type) { - return 1; - } else { - return 0; - } - }); - - class Tick { - - public readonly duration: number; - public readonly detail: string; - - constructor(public readonly start: ILoaderEvent, public readonly end: ILoaderEvent) { - console.assert(start.detail === end.detail); - - this.duration = this.end.timestamp - this.start.timestamp; - this.detail = start.detail; - } - - toTableObject() { - return { - ['Path']: this.start.detail, - ['Took (ms)']: this.duration.toFixed(2), - // ['Start (ms)']: this.start.timestamp, - // ['End (ms)']: this.end.timestamp - }; - } - - static compareUsingStartTimestamp(a: Tick, b: Tick): number { - if (a.start.timestamp < b.start.timestamp) { - return -1; - } else if (a.start.timestamp > b.start.timestamp) { - return 1; - } else { - return 0; - } - } - } - - const ticks: { [type: number]: Tick[] } = { - [LoaderEventType.BeginLoadingScript]: [], - [LoaderEventType.BeginInvokeFactory]: [], - [LoaderEventType.NodeBeginEvaluatingScript]: [], - [LoaderEventType.NodeBeginNativeRequire]: [], - }; - - for (let i = 1; i < stats.length - 1; i++) { - const stat = stats[i]; - const nextStat = stats[i + 1]; - - if (nextStat.type - stat.type > 2) { - //bad?! - break; - } - - i += 1; - ticks[stat.type].push(new Tick(stat, nextStat)); - } - - ticks[LoaderEventType.BeginInvokeFactory].sort(Tick.compareUsingStartTimestamp); - ticks[LoaderEventType.BeginInvokeFactory].sort(Tick.compareUsingStartTimestamp); - ticks[LoaderEventType.NodeBeginEvaluatingScript].sort(Tick.compareUsingStartTimestamp); - ticks[LoaderEventType.NodeBeginNativeRequire].sort(Tick.compareUsingStartTimestamp); - - const ret = { - 'Load Script': ticks[LoaderEventType.BeginLoadingScript].map(t => t.toTableObject()), - '(Node) Load Script': ticks[LoaderEventType.NodeBeginNativeRequire].map(t => t.toTableObject()), - 'Eval Script': ticks[LoaderEventType.BeginInvokeFactory].map(t => t.toTableObject()), - '(Node) Eval Script': ticks[LoaderEventType.NodeBeginEvaluatingScript].map(t => t.toTableObject()), - }; - - function total(ticks: Tick[]): number { - let sum = 0; - for (const tick of ticks) { - sum += tick.duration; - } - return sum; - } - - // totals - ret['Load Script'].push({ - ['Path']: 'TOTAL TIME', - ['Took (ms)']: total(ticks[LoaderEventType.BeginLoadingScript]).toFixed(2) - }); - ret['Eval Script'].push({ - ['Path']: 'TOTAL TIME', - ['Took (ms)']: total(ticks[LoaderEventType.BeginInvokeFactory]).toFixed(2) - }); - ret['(Node) Load Script'].push({ - ['Path']: 'TOTAL TIME', - ['Took (ms)']: total(ticks[LoaderEventType.NodeBeginNativeRequire]).toFixed(2) - }); - ret['(Node) Eval Script'].push({ - ['Path']: 'TOTAL TIME', - ['Took (ms)']: total(ticks[LoaderEventType.NodeBeginEvaluatingScript]).toFixed(2) - }); - - return ret; - } } export class ReloadWindowAction extends Action { @@ -859,6 +748,53 @@ export class CloseMessagesAction extends Action { } } +export class OpenIssueReporterAction extends Action { + public static readonly ID = 'workbench.action.openIssueReporter'; + public static readonly LABEL = nls.localize('openIssueReporter', "Open Issue Reporter"); + + constructor( + id: string, + label: string, + @IIssueService private issueService: IIssueService, + @IThemeService private themeService: IThemeService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService + ) { + super(id, label); + } + + public run(): TPromise { + return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => { + const enabledExtensions = extensions.filter(extension => this.extensionEnablementService.isEnabled(extension.identifier)); + const theme = this.themeService.getTheme(); + const styles = { + backgroundColor: theme.getColor(SIDE_BAR_BACKGROUND) && theme.getColor(SIDE_BAR_BACKGROUND).toString(), + color: theme.getColor(foreground).toString(), + textLinkColor: theme.getColor(textLinkForeground) && theme.getColor(textLinkForeground).toString(), + inputBackground: theme.getColor(inputBackground) && theme.getColor(inputBackground).toString(), + inputForeground: theme.getColor(inputForeground) && theme.getColor(inputForeground).toString(), + inputBorder: theme.getColor(inputBorder) && theme.getColor(inputBorder).toString(), + inputActiveBorder: theme.getColor(inputActiveOptionBorder) && theme.getColor(inputActiveOptionBorder).toString(), + inputErrorBorder: theme.getColor(inputValidationErrorBorder) && theme.getColor(inputValidationErrorBorder).toString(), + buttonBackground: theme.getColor(buttonBackground) && theme.getColor(buttonBackground).toString(), + buttonForeground: theme.getColor(buttonForeground) && theme.getColor(buttonForeground).toString(), + buttonHoverBackground: theme.getColor(buttonHoverBackground) && theme.getColor(buttonHoverBackground).toString(), + zoomLevel: webFrame.getZoomLevel(), + extensions + }; + const issueReporterData = { + styles, + zoomLevel: webFrame.getZoomLevel(), + enabledExtensions + }; + + return this.issueService.openReporter(issueReporterData).then(() => { + return TPromise.as(true); + }); + }); + } +} + export class ReportIssueAction extends Action { public static readonly ID = 'workbench.action.reportIssues'; diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index 867ed81842e..558e8df307e 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -13,6 +13,7 @@ const perf = require('../../../base/common/performance'); perf.mark('renderer/started'); const path = require('path'); +const fs = require('fs'); const electron = require('electron'); const remote = electron.remote; const ipc = electron.ipcRenderer; @@ -66,6 +67,18 @@ function uriFromPath(_path) { return encodeURI('file://' + pathName); } +function readFile(file) { + return new Promise(function(resolve, reject) { + fs.readFile(file, 'utf8', function(err, data) { + if (err) { + reject(err); + return; + } + resolve(data); + }); + }); +} + function registerListeners(enableDeveloperTools) { // Devtools & reload support @@ -124,13 +137,30 @@ function main() { } catch (e) { /*noop*/ } } + if (nlsConfig._resolvedLanguagePackCoreLocation) { + let bundles = Object.create(null); + nlsConfig.loadBundle = function(bundle, language, cb) { + let result = bundles[bundle]; + if (result) { + cb(undefined, result); + return; + } + let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json'); + readFile(bundleFile).then(function (content) { + let json = JSON.parse(content); + bundles[bundle] = json; + cb(undefined, json); + }) + .catch(cb); + }; + } + var locale = nlsConfig.availableLanguages['*'] || 'en'; if (locale === 'zh-tw') { locale = 'zh-Hant'; } else if (locale === 'zh-cn') { locale = 'zh-Hans'; } - window.document.documentElement.setAttribute('lang', locale); const enableDeveloperTools = (process.env['VSCODE_DEV'] || !!configuration.extensionDevelopmentPath) && !configuration.extensionTestsPath; diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index c4c44281642..d72fb4e04e6 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -14,7 +14,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; -import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, ReportIssueAction, ReportPerformanceIssueAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, CloseMessagesAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ConfigureLocaleAction } from 'vs/workbench/electron-browser/actions'; +import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportIssueAction, ReportPerformanceIssueAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, CloseMessagesAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ConfigureLocaleAction } from 'vs/workbench/electron-browser/actions'; import { MessagesVisibleContext } from 'vs/workbench/electron-browser/workbench'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { registerCommands } from 'vs/workbench/electron-browser/commands'; @@ -46,6 +46,7 @@ if (isMacintosh) { } workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory); +workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenIssueReporterAction, OpenIssueReporterAction.ID, OpenIssueReporterAction.LABEL), 'Help: Open Issue Reporter', helpCategory); if (!!product.reportIssueUrl) { workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReportIssueAction, ReportIssueAction.ID, ReportIssueAction.LABEL), 'Help: Report Issues', helpCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReportPerformanceIssueAction, ReportPerformanceIssueAction.ID, ReportPerformanceIssueAction.LABEL), 'Help: Report Performance Issue', helpCategory); @@ -255,14 +256,15 @@ configurationRegistry.registerConfiguration({ }, 'workbench.fontAliasing': { 'type': 'string', - 'enum': ['default', 'antialiased', 'none'], + 'enum': ['default', 'antialiased', 'none', 'auto'], 'default': 'default', 'description': - nls.localize('fontAliasing', "Controls font aliasing method in the workbench.\n- default: Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text\n- antialiased: Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall\n- none: Disables font smoothing. Text will show with jagged sharp edges"), + nls.localize('fontAliasing', "Controls font aliasing method in the workbench.\n- default: Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text\n- antialiased: Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall\n- none: Disables font smoothing. Text will show with jagged sharp edges\n- auto: Applies `default` or `antialiased` automatically based on the DPI of displays."), 'enumDescriptions': [ nls.localize('workbench.fontAliasing.default', "Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text."), nls.localize('workbench.fontAliasing.antialiased', "Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall."), - nls.localize('workbench.fontAliasing.none', "Disables font smoothing. Text will show with jagged sharp edges.") + nls.localize('workbench.fontAliasing.none', "Disables font smoothing. Text will show with jagged sharp edges."), + nls.localize('workbench.fontAliasing.auto', "Applies `default` or `antialiased` automatically based on the DPI of displays.") ], 'included': isMacintosh }, diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 9e75b4e4cfa..6c93107c6cc 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -31,7 +31,7 @@ import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/commo import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { StorageService, inMemoryLocalStorageInstance } from 'vs/platform/storage/common/storageService'; +import { StorageService, inMemoryLocalStorageInstance, IStorage } from 'vs/platform/storage/common/storageService'; import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser'; import { webFrame } from 'electron'; import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc'; @@ -43,7 +43,10 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import fs = require('fs'); -import { ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log'; +import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log'; +import { IssueChannelClient } from 'vs/platform/issue/common/issueIpc'; +import { IIssueService } from 'vs/platform/issue/common/issue'; +import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; gracefulFs.gracefulify(fs); // enable gracefulFs export function startup(configuration: IWindowConfiguration): TPromise { @@ -73,16 +76,12 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { const mainServices = createMainProcessServices(mainProcessClient, configuration); const environmentService = new EnvironmentService(configuration, configuration.execPath); - const spdlogService = createSpdLogService(`renderer${configuration.windowId}`, environmentService); - const consoleLogService = new ConsoleLogService(environmentService); - const logService = new MultiplexLogService([consoleLogService, spdlogService]); - + const logService = createLogService(mainProcessClient, configuration, environmentService); logService.trace('openWorkbench configuration', JSON.stringify(configuration)); // Since the configuration service is one of the core services that is used in so many places, we initialize it // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService).then(workspaceService => { - const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); const storageService = createStorageService(workspaceService, environmentService); @@ -185,11 +184,28 @@ function createStorageService(workspaceService: IWorkspaceContextService, enviro } const disableStorage = !!environmentService.extensionTestsPath; // never keep any state when running extension tests! - const storage = disableStorage ? inMemoryLocalStorageInstance : window.localStorage; + + let storage: IStorage; + if (disableStorage) { + storage = inMemoryLocalStorageInstance; + } else { + // TODO@Ben remove me after a while + perf.mark('willAccessLocalStorage'); + storage = window.localStorage; + perf.mark('didAccessLocalStorage'); + } return new StorageService(storage, storage, workspaceId, secondaryWorkspaceId); } +function createLogService(mainProcessClient: ElectronIPCClient, configuration: IWindowConfiguration, environmentService: IEnvironmentService): ILogService { + const spdlogService = createSpdLogService(`renderer${configuration.windowId}`, configuration.logLevel, environmentService.logsPath); + const consoleLogService = new ConsoleLogService(configuration.logLevel); + const logService = new MultiplexLogService([consoleLogService, spdlogService]); + const logLevelClient = new LogLevelSetterChannelClient(mainProcessClient.getChannel('loglevel')); + return new FollowerLogService(logLevelClient, logService); +} + function createMainProcessServices(mainProcessClient: ElectronIPCClient, configuration: IWindowConfiguration): ServiceCollection { const serviceCollection = new ServiceCollection(); @@ -202,6 +218,9 @@ function createMainProcessServices(mainProcessClient: ElectronIPCClient, configu const urlChannel = mainProcessClient.getChannel('url'); serviceCollection.set(IURLService, new SyncDescriptor(URLChannelClient, urlChannel, configuration.windowId)); + const issueChannel = mainProcessClient.getChannel('issue'); + serviceCollection.set(IIssueService, new SyncDescriptor(IssueChannelClient, issueChannel)); + const workspacesChannel = mainProcessClient.getChannel('workspaces'); serviceCollection.set(IWorkspacesService, new WorkspacesChannelClient(workspacesChannel)); diff --git a/src/vs/workbench/electron-browser/media/workbench.css b/src/vs/workbench/electron-browser/media/workbench.css index e3b64be9207..2b45ff41a7b 100644 --- a/src/vs/workbench/electron-browser/media/workbench.css +++ b/src/vs/workbench/electron-browser/media/workbench.css @@ -26,4 +26,18 @@ .monaco-workbench.windows .monaco-action-bar .select-box { margin-top: 7px; /* Center the select box */ +} + +.monaco-font-aliasing-antialiased { + -webkit-font-smoothing: antialiased; +} + +.monaco-font-aliasing-none { + -webkit-font-smoothing: none; +} + +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .monaco-font-aliasing-auto { + -webkit-font-smoothing: antialiased; + } } \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 04cd7a48b26..cc86097415f 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -87,6 +87,8 @@ import { IBroadcastService, BroadcastService } from 'vs/platform/broadcast/elect import { HashService } from 'vs/workbench/services/hash/node/hashService'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; import { ILogService } from 'vs/platform/log/common/log'; +import { stat } from 'fs'; +import { join } from 'path'; /** * Services that we require for the Shell @@ -206,6 +208,11 @@ export class WorkbenchShell { } } }); + + // localStorage metrics (TODO@Ben remove me later) + if (!this.environmentService.extensionTestsPath && this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + this.logLocalStorageMetrics(); + } }); return workbench; @@ -274,6 +281,37 @@ export class WorkbenchShell { }); } + private logLocalStorageMetrics(): void { + perf.mark('willReadLocalStorage'); + if (!this.storageService.getBoolean('localStorageMetricsSent')) { + perf.mark('didReadLocalStorage'); + + perf.mark('willWriteLocalStorage'); + this.storageService.store('localStorageMetricsSent', true); + + stat(join(this.environmentService.userDataPath, 'Local Storage', 'file__0.localstorage'), (error, stat) => { + /* __GDPR__ + "localStorageMetrics" : { + "accessTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "firstReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "subsequentReadTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "writeTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "keys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "size": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('localStorageMetrics', { + 'accessTime': perf.getDuration('willAccessLocalStorage', 'didAccessLocalStorage'), + 'firstReadTime': perf.getDuration('willReadWorkspaceIdentifier', 'didReadWorkspaceIdentifier'), + 'subsequentReadTime': perf.getDuration('willReadLocalStorage', 'didReadLocalStorage'), + 'writeTime': perf.getDuration('willWriteLocalStorage', 'willComputeLocalStorageSize'), + 'keys': window.localStorage.length, + 'size': stat ? stat.size : -1 + }); + }); + } + } + private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] { const serviceCollection = new ServiceCollection(); serviceCollection.set(IWorkspaceContextService, this.contextService); diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index e13edb24a93..551bcc802f5 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -124,6 +124,8 @@ export interface IWorkbenchStartedInfo { restoredEditors: string[]; } +type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto'; + const Identifiers = { WORKBENCH_CONTAINER: 'workbench.main.container', TITLEBAR_PART: 'workbench.parts.titlebar', @@ -202,7 +204,7 @@ export class Workbench implements IPartService { private inZenMode: IContextKey; private sideBarVisibleContext: IContextKey; private hasFilesToCreateOpenOrDiff: boolean; - private fontAliasing: string; + private fontAliasing: FontAliasingOption; private zenMode: { active: boolean; transitionedToFullScreen: boolean; @@ -643,7 +645,7 @@ export class Workbench implements IPartService { this.activityBarHidden = !activityBarVisible; // Font aliasing - this.fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); + this.fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); // Zen mode this.zenMode = { @@ -937,10 +939,17 @@ export class Workbench implements IPartService { }); } - private setFontAliasing(aliasing: string) { + private setFontAliasing(aliasing: FontAliasingOption) { this.fontAliasing = aliasing; - - document.body.style['-webkit-font-smoothing'] = (aliasing === 'default' ? '' : aliasing); + const fontAliasingClassNames = [ + 'monaco-font-aliasing-antialiased', + 'monaco-font-aliasing-none', + 'monaco-font-aliasing-auto' + ]; + document.body.classList.remove(...fontAliasingClassNames); + if (aliasing !== 'default') { + document.body.classList.add(`monaco-font-aliasing-${aliasing}`); + } } public dispose(reason = ShutdownReason.QUIT): void { @@ -1088,7 +1097,7 @@ export class Workbench implements IPartService { this.setPanelPositionFromStorageOrConfig(); - const fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); + const fontAliasing = this.configurationService.getValue(Workbench.fontAliasingConfigurationKey); if (fontAliasing !== this.fontAliasing) { this.setFontAliasing(fontAliasing); } diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index 7af498132c5..1a37fc04768 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -21,12 +21,11 @@ import * as watchdog from 'native-watchdog'; import * as glob from 'vs/base/common/glob'; import { ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { ILogService } from 'vs/platform/log/common/log'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; import URI from 'vs/base/common/uri'; +import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; // const nativeExit = process.exit.bind(process); function patchProcess(allowExit: boolean) { @@ -78,7 +77,7 @@ export class ExtensionHostMain { private _environment: IEnvironment; private _extensionService: ExtHostExtensionService; private _extHostConfiguration: ExtHostConfiguration; - private _logService: ILogService; + private _extHostLogService: ExtHostLogService; private disposables: IDisposable[] = []; constructor(protocol: IMessagePassingProtocol, initData: IInitData) { @@ -92,14 +91,14 @@ export class ExtensionHostMain { const rpcProtocol = new RPCProtocol(protocol); const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, initData.workspace); const environmentService = new EnvironmentService(initData.args, initData.execPath); - this._logService = createSpdLogService(`exthost${initData.windowId}`, environmentService); - this.disposables.push(this._logService); + this._extHostLogService = new ExtHostLogService(initData.windowId, initData.logLevel, environmentService); + this.disposables.push(this._extHostLogService); - this._logService.info('extension host started'); - this._logService.trace('initData', initData); + this._extHostLogService.info('extension host started'); + this._extHostLogService.trace('initData', initData); this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration); - this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._logService, environmentService); + this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._extHostLogService, environmentService); // error forwarding and stack trace scanning const extensionErrors = new WeakMap(); @@ -143,7 +142,7 @@ export class ExtensionHostMain { .then(() => this.handleEagerExtensions()) .then(() => this.handleExtensionTests()) .then(() => { - this._logService.info(`eager extensions activated`); + this._extHostLogService.info(`eager extensions activated`); }); } diff --git a/src/vs/workbench/parts/backup/common/backupModelTracker.ts b/src/vs/workbench/parts/backup/common/backupModelTracker.ts index 7078c5cd4b5..1c61b9715e2 100644 --- a/src/vs/workbench/parts/backup/common/backupModelTracker.ts +++ b/src/vs/workbench/parts/backup/common/backupModelTracker.ts @@ -72,14 +72,14 @@ export class BackupModelTracker implements IWorkbenchContribution { // Do not backup when auto save after delay is configured if (!this.configuredAutoSaveAfterDelay) { const model = this.textFileService.models.get(event.resource); - this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId()).done(null, errors.onUnexpectedError); + this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId()).done(null, errors.onUnexpectedError); } } } private onUntitledModelChanged(resource: Uri): void { if (this.untitledEditorService.isDirty(resource)) { - this.untitledEditorService.loadOrCreate({ resource }).then(model => this.backupFileService.backupResource(resource, model.getValue(), model.getVersionId())).done(null, errors.onUnexpectedError); + this.untitledEditorService.loadOrCreate({ resource }).then(model => this.backupFileService.backupResource(resource, model.createSnapshot(), model.getVersionId())).done(null, errors.onUnexpectedError); } else { this.discardBackup(resource); } diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts b/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts index 39b0436ad9e..4925f696c31 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import 'vs/css!./media/codeEditor'; import * as nls from 'vs/nls'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -259,7 +258,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: 'editor.action.toggleWordWrap', title: nls.localize('unwrapMinified', "Disable wrapping for this file"), - iconClass: 'toggle-word-wrap-action' + iconPath: { dark: URI.parse(require.toUrl('vs/workbench/parts/codeEditor/electron-browser/WordWrap_16x.svg')).fsPath } }, group: 'navigation', order: 1, @@ -273,7 +272,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: 'editor.action.toggleWordWrap', title: nls.localize('wrapMinified', "Enable wrapping for this file"), - iconClass: 'toggle-word-wrap-action' + iconPath: { dark: URI.parse(require.toUrl('vs/workbench/parts/codeEditor/electron-browser/WordWrap_16x.svg')).fsPath } }, group: 'navigation', order: 1, diff --git a/src/vs/workbench/parts/debug/browser/debugActionItems.ts b/src/vs/workbench/parts/debug/browser/debugActionItems.ts index 12887c33f44..2f8e4a05dfa 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionItems.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionItems.ts @@ -158,7 +158,7 @@ export class StartDebugActionItem implements IActionItem { if (name === manager.selectedName && launch === manager.selectedLaunch) { this.selected = this.options.length; } - const label = launches.length > 1 ? `${name} (${launch.workspace.name})` : name; + const label = launches.length > 1 ? `${name} (${launch.name})` : name; this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } }); })); @@ -169,10 +169,10 @@ export class StartDebugActionItem implements IActionItem { const disabledIdx = this.options.length - 1; launches.forEach(l => { - const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration..."); + const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration..."); this.options.push({ label, handler: () => { - this.commandService.executeCommand('debug.addConfiguration', l.workspace.uri.toString()).done(undefined, errors.onUnexpectedError); + this.commandService.executeCommand('debug.addConfiguration', l.uri.toString()).done(undefined, errors.onUnexpectedError); return false; } }); diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index e98c1e52ab3..293425c4a9f 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -142,7 +142,7 @@ export class StartAction extends AbstractDebugAction { if (contextService && contextService.getWorkbenchState() === WorkbenchState.EMPTY && processes.length > 0) { return false; } - if (processes.some(p => p.getName(false) === configName && (!launch || p.session.root.uri.toString() === launch.workspace.uri.toString()))) { + if (processes.some(p => p.getName(false) === configName && (!launch || !launch.workspace || !p.session.root || p.session.root.uri.toString() === launch.workspace.uri.toString()))) { return false; } const compound = launch && launch.getCompound(configName); diff --git a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts index cd90a6fd6fc..4b93cc51109 100644 --- a/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts +++ b/src/vs/workbench/parts/debug/browser/debugQuickOpen.ts @@ -29,7 +29,7 @@ class AddConfigEntry extends Model.QuickOpenEntry { } public getDescription(): string { - return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : ''; + return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : ''; } public getAriaLabel(): string { @@ -40,7 +40,7 @@ class AddConfigEntry extends Model.QuickOpenEntry { if (mode === QuickOpen.Mode.PREVIEW) { return false; } - this.commandService.executeCommand('debug.addConfiguration', this.launch.workspace.uri.toString()).done(undefined, errors.onUnexpectedError); + this.commandService.executeCommand('debug.addConfiguration', this.launch.uri.toString()).done(undefined, errors.onUnexpectedError); return true; } @@ -57,7 +57,7 @@ class StartDebugEntry extends Model.QuickOpenEntry { } public getDescription(): string { - return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.workspace.name : ''; + return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.launch.name : ''; } public getAriaLabel(): string { @@ -110,7 +110,7 @@ export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler { }); } launches.forEach((l, index) => { - const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.workspace.name) : nls.localize('addConfiguration', "Add Configuration..."); + const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration..."); const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, Filters.matchesContiguousSubString(input, label)); if (index === 0) { configurations.push(new QuickOpenEntryGroup(entry, undefined, true)); diff --git a/src/vs/workbench/parts/debug/browser/debugStatus.ts b/src/vs/workbench/parts/debug/browser/debugStatus.ts index da4007a0a80..01e55d619ed 100644 --- a/src/vs/workbench/parts/debug/browser/debugStatus.ts +++ b/src/vs/workbench/parts/debug/browser/debugStatus.ts @@ -95,7 +95,7 @@ export class DebugStatus extends Themable implements IStatusbarItem { if (manager.selectedName) { const name = manager.selectedName; this.statusBarItem.style.display = 'block'; - this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedLaunch.workspace.name})` : name; + this.label.textContent = manager.getLaunches().length > 1 ? `${name} (${manager.selectedLaunch.name})` : name; } else { this.statusBarItem.style.display = 'none'; } diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 43d81946f37..7c951a07014 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -223,6 +223,7 @@ export interface IEnablement extends ITreeElement { } export interface IRawBreakpoint { + id?: string; lineNumber: number; column?: number; enabled?: boolean; @@ -363,7 +364,7 @@ export interface IConfig extends IEnvConfig { export interface ICompound { name: string; - configurations: string[]; + configurations: (string | { name: string, folder: string })[]; } export interface IAdapterExecutable { @@ -437,6 +438,11 @@ export interface ILaunch { */ uri: uri; + /** + * Name of the launch. + */ + name: string; + workspace: IWorkspaceFolder; /** @@ -455,7 +461,7 @@ export interface ILaunch { * Returns the names of all configurations and compounds. * Ignores configurations which are invalid. */ - getConfigurationNames(): string[]; + getConfigurationNames(includeCompounds?: boolean): string[]; /** * Returns the resolved configuration. @@ -466,7 +472,7 @@ export interface ILaunch { /** * Opens the launch.json file. Creates if it does not exist. */ - openConfigFile(sideBySide: boolean, type?: string): TPromise<{ editor: IEditor; configFileCreated: boolean; }>; + openConfigFile(sideBySide: boolean, type?: string): TPromise; } // Debug service interfaces @@ -544,9 +550,9 @@ export interface IDebugService { removeBreakpoints(id?: string): TPromise; /** - * Adds a new no name function breakpoint. The function breakpoint should be renamed once user enters the name. + * Adds a new function breakpoint for the given name. */ - addFunctionBreakpoint(): void; + addFunctionBreakpoint(name?: string, id?: string): void; /** * Renames an already existing function breakpoint. diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 2923456a42c..7b162f1caab 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -545,7 +545,7 @@ export class Process implements IProcess { } public getName(includeRoot: boolean): string { - return includeRoot ? `${this.configuration.name} (${resources.basenameOrAuthority(this.session.root.uri)})` : this.configuration.name; + return includeRoot && this.session.root ? `${this.configuration.name} (${resources.basenameOrAuthority(this.session.root.uri)})` : this.configuration.name; } public get state(): ProcessState { @@ -560,6 +560,7 @@ export class Process implements IProcess { let source = new Source(raw, this.getId()); if (this.sources.has(source.uri.toString())) { source = this.sources.get(source.uri.toString()); + source.raw = raw; } else { this.sources.set(source.uri.toString(), source); } @@ -674,7 +675,6 @@ export class Breakpoint implements IBreakpoint { public message: string; public endLineNumber: number; public endColumn: number; - private id: string; constructor( public uri: uri, @@ -683,13 +683,13 @@ export class Breakpoint implements IBreakpoint { public enabled: boolean, public condition: string, public hitCondition: string, - public adapterData: any + public adapterData: any, + private id = generateUuid() ) { if (enabled === undefined) { this.enabled = true; } this.verified = false; - this.id = generateUuid(); } public getId(): string { @@ -699,13 +699,11 @@ export class Breakpoint implements IBreakpoint { export class FunctionBreakpoint implements IFunctionBreakpoint { - private id: string; public verified: boolean; public idFromAdapter: number; - constructor(public name: string, public enabled: boolean, public hitCondition: string) { + constructor(public name: string, public enabled: boolean, public hitCondition: string, private id = generateUuid()) { this.verified = false; - this.id = generateUuid(); } public getId(): string { @@ -866,7 +864,7 @@ export class Model implements IModel { } public addBreakpoints(uri: uri, rawData: IRawBreakpoint[], fireEvent = true): Breakpoint[] { - const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled, rawBp.condition, rawBp.hitCondition, undefined)); + const newBreakpoints = rawData.map(rawBp => new Breakpoint(uri, rawBp.lineNumber, rawBp.column, rawBp.enabled, rawBp.condition, rawBp.hitCondition, undefined, rawBp.id)); this.breakpoints = this.breakpoints.concat(newBreakpoints); this.breakpointsActivated = true; this.sortAndDeDup(); @@ -956,8 +954,8 @@ export class Model implements IModel { this._onDidChangeBreakpoints.fire({ changed: changed }); } - public addFunctionBreakpoint(functionName: string): FunctionBreakpoint { - const newFunctionBreakpoint = new FunctionBreakpoint(functionName, true, null); + public addFunctionBreakpoint(functionName: string, id: string): FunctionBreakpoint { + const newFunctionBreakpoint = new FunctionBreakpoint(functionName, true, null, id); this.functionBreakpoints.push(newFunctionBreakpoint); this._onDidChangeBreakpoints.fire({ added: [newFunctionBreakpoint] }); diff --git a/src/vs/workbench/parts/debug/common/debugSource.ts b/src/vs/workbench/parts/debug/common/debugSource.ts index a154158dc82..22a60851431 100644 --- a/src/vs/workbench/parts/debug/common/debugSource.ts +++ b/src/vs/workbench/parts/debug/common/debugSource.ts @@ -19,7 +19,7 @@ export class Source { public readonly uri: uri; public available: boolean; - constructor(public readonly raw: DebugProtocol.Source, sessionId: string) { + constructor(public raw: DebugProtocol.Source, sessionId: string) { if (!raw) { this.raw = { name: UNKNOWN_SOURCE_LABEL }; } @@ -110,4 +110,4 @@ export class Source { processId }; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/parts/debug/electron-browser/breakpointsView.ts b/src/vs/workbench/parts/debug/electron-browser/breakpointsView.ts index 3807f7aa779..6e4c6862c91 100644 --- a/src/vs/workbench/parts/debug/electron-browser/breakpointsView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/breakpointsView.ts @@ -28,9 +28,8 @@ import { IEditorService, IEditor } from 'vs/platform/editor/common/editor'; import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { ViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -50,11 +49,9 @@ export class BreakpointsView extends ViewsViewletPanel { @IDebugService private debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService, @IInstantiationService private instantiationService: IInstantiationService, - @IListService private listService: IListService, @IThemeService private themeService: IThemeService, @IEditorService private editorService: IEditorService, - @IContextViewService private contextViewService: IContextViewService, - @IContextKeyService private contextKeyService: IContextKeyService + @IContextViewService private contextViewService: IContextViewService ) { super(options, keybindingService, contextMenuService); @@ -67,7 +64,7 @@ export class BreakpointsView extends ViewsViewletPanel { dom.addClass(container, 'debug-breakpoints'); const delegate = new BreakpointsDelegate(this.debugService); - this.list = new WorkbenchList(container, delegate, [ + this.list = this.instantiationService.createInstance(WorkbenchList, container, delegate, [ this.instantiationService.createInstance(BreakpointsRenderer), new ExceptionBreakpointsRenderer(this.debugService), new FunctionBreakpointsRenderer(this.debugService), @@ -75,7 +72,7 @@ export class BreakpointsView extends ViewsViewletPanel { ], { identityProvider: element => element.getId(), multipleSelectionSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); CONTEXT_BREAKPOINTS_FOCUSED.bindTo(this.list.contextKeyService); diff --git a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts index 5948091a39d..123bcb9be6c 100644 --- a/src/vs/workbench/parts/debug/electron-browser/callStackView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/callStackView.ts @@ -15,7 +15,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MenuId } from 'vs/platform/actions/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; import { BaseDebugController, twistiePixels, renderViewTree } from 'vs/workbench/parts/debug/electron-browser/baseDebugView'; import { ITree, IActionProvider, IDataSource, IRenderer, IAccessibilityProvider } from 'vs/base/parts/tree/browser/tree'; import { IAction, IActionItem } from 'vs/base/common/actions'; @@ -25,8 +24,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/ import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Source } from 'vs/workbench/parts/debug/common/debugSource'; import { basenameOrAuthority } from 'vs/base/common/resources'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import FileResultsNavigation from 'vs/workbench/parts/files/browser/fileResultsNavigation'; @@ -40,16 +38,14 @@ export class CallStackView extends TreeViewsViewletPanel { private onCallStackChangeScheduler: RunOnceScheduler; private settings: any; private needsRefresh: boolean; + private ignoreSelectionChangedEvent: boolean; constructor( private options: IViewletViewOptions, @IContextMenuService contextMenuService: IContextMenuService, - @IContextKeyService private contextKeyService: IContextKeyService, @IDebugService private debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService, @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService private themeService: IThemeService, - @IListService private listService: IListService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, ) { super({ ...(options as IViewOptions), ariaHeaderLabel: nls.localize('callstackSection', "Call Stack Section") }, keybindingService, contextMenuService); @@ -99,7 +95,7 @@ export class CallStackView extends TreeViewsViewletPanel { const actionProvider = new CallStackActionProvider(this.debugService, this.keybindingService); const controller = this.instantiationService.createInstance(CallStackController, actionProvider, MenuId.DebugCallStackContext); - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new CallStackDataSource(), renderer: this.instantiationService.createInstance(CallStackRenderer), accessibilityProvider: this.instantiationService.createInstance(CallstackAccessibilityProvider), @@ -108,13 +104,16 @@ export class CallStackView extends TreeViewsViewletPanel { ariaLabel: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'callStackAriaLabel' }, "Debug Call Stack"), twistiePixels, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); const fileResultsNavigation = new FileResultsNavigation(this.tree); this.disposables.push(fileResultsNavigation); this.disposables.push(fileResultsNavigation.openFile(e => { - const element = e.element; + if (this.ignoreSelectionChangedEvent) { + return; + } + const element = e.element; if (element instanceof StackFrame) { this.debugService.focusStackFrame(element, element.thread, element.thread.process, true); element.openInEditor(this.editorService, e.editorOptions.preserveFocus, e.sideBySide).done(undefined, errors.onUnexpectedError); @@ -145,8 +144,14 @@ export class CallStackView extends TreeViewsViewletPanel { this.onCallStackChangeScheduler.schedule(); } })); - this.disposables.push(this.debugService.getViewModel().onDidFocusStackFrame(() => - this.updateTreeSelection().done(undefined, errors.onUnexpectedError))); + this.disposables.push(this.debugService.getViewModel().onDidFocusStackFrame(() => { + if (!this.isVisible) { + this.needsRefresh = true; + return; + } + + this.updateTreeSelection().done(undefined, errors.onUnexpectedError); + })); // Schedule the update of the call stack tree if the viewlet is opened after a session started #14684 if (this.debugService.state === State.Stopped) { @@ -163,13 +168,22 @@ export class CallStackView extends TreeViewsViewletPanel { const stackFrame = this.debugService.getViewModel().focusedStackFrame; const thread = this.debugService.getViewModel().focusedThread; const process = this.debugService.getViewModel().focusedProcess; + const updateSelection = (element: IStackFrame | IProcess) => { + this.ignoreSelectionChangedEvent = true; + try { + this.tree.setSelection([element]); + } finally { + this.ignoreSelectionChangedEvent = false; + } + }; + if (!thread) { if (!process) { this.tree.clearSelection(); return TPromise.as(null); } - this.tree.setSelection([process]); + updateSelection(process); return this.tree.reveal(process); } @@ -178,7 +192,7 @@ export class CallStackView extends TreeViewsViewletPanel { return TPromise.as(null); } - this.tree.setSelection([stackFrame]); + updateSelection(stackFrame); return this.tree.reveal(stackFrame); }); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index f8768ff718e..fb9e5dec2ed 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -223,7 +223,7 @@ if (isMacintosh) { const registerTouchBarEntry = (id: string, title: string, order, when: ContextKeyExpr, icon: string) => { MenuRegistry.appendMenuItem(MenuId.TouchBarContext, { command: { - id, title, iconPath: URI.parse(require.toUrl(`vs/workbench/parts/debug/electron-browser/media/${icon}`)).fsPath + id, title, iconPath: { dark: URI.parse(require.toUrl(`vs/workbench/parts/debug/electron-browser/media/${icon}`)).fsPath } }, when, group: '9_debug', diff --git a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts index 37e840a1666..3387c35f8a5 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts @@ -22,6 +22,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; export function registerCommands(): void { + // TODO@Isidor remove in february KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'debug.logToDebugConsole', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), @@ -162,17 +163,17 @@ export function registerCommands(): void { weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), when: undefined, primary: undefined, - handler: (accessor, workspaceUri: string) => { + handler: (accessor, launchUri: string) => { const manager = accessor.get(IDebugService).getConfigurationManager(); if (accessor.get(IWorkspaceContextService).getWorkbenchState() === WorkbenchState.EMPTY) { accessor.get(IMessageService).show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); return TPromise.as(null); } - const launch = manager.getLaunches().filter(l => l.workspace.uri.toString() === workspaceUri).pop() || manager.selectedLaunch; + const launch = manager.getLaunches().filter(l => l.uri.toString() === launchUri).pop() || manager.selectedLaunch; - return launch.openConfigFile(false).done(result => { - if (result.editor && !result.configFileCreated) { - const codeEditor = result.editor.getControl(); + return launch.openConfigFile(false).done(editor => { + if (editor) { + const codeEditor = editor.getControl(); if (codeEditor) { return codeEditor.getContribution(EDITOR_CONTRIBUTION_ID).addLaunchConfiguration(); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 3a779ea68b0..6fe509caccb 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -24,7 +24,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; -import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug'; @@ -33,6 +33,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; // debuggers extension point export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint('debuggers', [], { @@ -102,11 +103,11 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE } }, osx: { - description: nls.localize('vscode.extension.contributes.debuggers.osx', "OS X specific settings."), + description: nls.localize('vscode.extension.contributes.debuggers.osx', "macOS specific settings."), type: 'object', properties: { runtime: { - description: nls.localize('vscode.extension.contributes.debuggers.osx.runtime', "Runtime used for OSX."), + description: nls.localize('vscode.extension.contributes.debuggers.osx.runtime', "Runtime used for macOS."), type: 'string' } } @@ -147,14 +148,12 @@ const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtens }); // debug general schema - -export const schemaId = 'vscode://schemas/launch'; const defaultCompound: ICompound = { name: 'Compound', configurations: [] }; const schema: IJSONSchema = { - id: schemaId, + id: launchSchemaId, type: 'object', title: nls.localize('app.launch.json.title', "Launch"), - required: ['version', 'configurations'], + required: [], default: { version: '0.2.0', configurations: [], compounds: [] }, properties: { version: { @@ -186,7 +185,23 @@ const schema: IJSONSchema = { type: 'array', default: [], items: { - type: 'string' + oneOf: [{ + enum: [], + description: nls.localize('useUniqueNames', "Please use unique configuration names.") + }, { + type: 'object', + required: ['name'], + properties: { + name: { + enum: [], + description: nls.localize('app.launch.json.compound.name', "Name of compound. Appears in the launch configuration drop down menu.") + }, + folder: { + enum: [], + description: nls.localize('app.launch.json.compound.folder', "Name of folder in which the compound is located.") + } + } + }] }, description: nls.localize('app.launch.json.compounds.configurations', "Names of configurations that will be started as part of this compound.") } @@ -201,7 +216,7 @@ const schema: IJSONSchema = { }; const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); -jsonRegistry.registerSchema(schemaId, schema); +jsonRegistry.registerSchema(launchSchemaId, schema); const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; const DEBUG_SELECTED_ROOT = 'debug.selectedroot'; @@ -232,7 +247,7 @@ export class ConfigurationManager implements IConfigurationManager { this.registerListeners(lifecycleService); this.initLaunches(); const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE); - const filtered = this.launches.filter(l => l.workspace.uri.toString() === previousSelectedRoot); + const filtered = this.launches.filter(l => l.uri.toString() === previousSelectedRoot); this.selectConfiguration(filtered.length ? filtered[0] : undefined, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE)); } @@ -310,6 +325,8 @@ export class ConfigurationManager implements IConfigurationManager { items.defaultSnippets.push(...configurationSnippets); } }); + + this.setCompoundSchemaValues(); }); breakpointsExtPoint.setHandler(extensions => { @@ -323,10 +340,12 @@ export class ConfigurationManager implements IConfigurationManager { this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => { this.initLaunches(); this.selectConfiguration(); + this.setCompoundSchemaValues(); })); this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('launch')) { this.selectConfiguration(); + this.setCompoundSchemaValues(); } })); @@ -335,11 +354,28 @@ export class ConfigurationManager implements IConfigurationManager { private initLaunches(): void { this.launches = this.contextService.getWorkspace().folders.map(folder => this.instantiationService.createInstance(Launch, this, folder)); + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + this.launches.push(this.instantiationService.createInstance(WorkspaceLaunch, this)); + } + if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } } + private setCompoundSchemaValues(): void { + const compoundConfigurationsSchema = (schema.properties['compounds'].items).properties['configurations']; + const launchNames = this.launches.map(l => + l.getConfigurationNames(false)).reduce((first, second) => first.concat(second), []); + (compoundConfigurationsSchema.items).oneOf[0].enum = launchNames; + (compoundConfigurationsSchema.items).oneOf[1].properties.name.enum = launchNames; + + const folderNames = this.contextService.getWorkspace().folders.map(f => f.name); + (compoundConfigurationsSchema.items).oneOf[1].properties.folder.enum = folderNames; + + jsonRegistry.registerSchema(launchSchemaId, schema); + } + public getLaunches(): ILaunch[] { return this.launches; } @@ -356,6 +392,14 @@ export class ConfigurationManager implements IConfigurationManager { return this._onDidSelectConfigurationName.event; } + public getWorkspaceLaunch(): ILaunch { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + return this.launches[this.launches.length - 1]; + } + + return undefined; + } + public selectConfiguration(launch?: ILaunch, name?: string, debugStarted?: boolean): void { const previousLaunch = this._selectedLaunch; const previousName = this._selectedName; @@ -403,6 +447,7 @@ export class ConfigurationManager implements IConfigurationManager { } const editor = this.editorService.getActiveEditor(); + let candidates: Adapter[]; if (editor) { const codeEditor = editor.getControl(); if (isCodeEditor(codeEditor)) { @@ -412,10 +457,16 @@ export class ConfigurationManager implements IConfigurationManager { if (adapters.length === 1) { return TPromise.as(adapters[0]); } + if (adapters.length > 1) { + candidates = adapters; + } } } - return this.quickOpenService.pick([...this.adapters.filter(a => a.hasInitialConfiguration() || a.hasConfigurationProvider), { label: 'More...', separator: { border: true } }], { placeHolder: nls.localize('selectDebug', "Select Environment") }) + if (!candidates) { + candidates = this.adapters.filter(a => a.hasInitialConfiguration() || a.hasConfigurationProvider); + } + return this.quickOpenService.pick([...candidates, { label: 'More...', separator: { border: true } }], { placeHolder: nls.localize('selectDebug', "Select Environment") }) .then(picked => { if (picked instanceof Adapter) { return picked; @@ -431,7 +482,7 @@ export class ConfigurationManager implements IConfigurationManager { private store(): void { this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.selectedName, StorageScope.WORKSPACE); if (this._selectedLaunch) { - this.storageService.store(DEBUG_SELECTED_ROOT, this._selectedLaunch.workspace.uri.toString(), StorageScope.WORKSPACE); + this.storageService.store(DEBUG_SELECTED_ROOT, this._selectedLaunch.uri.toString(), StorageScope.WORKSPACE); } } @@ -446,15 +497,27 @@ class Launch implements ILaunch { private configurationManager: ConfigurationManager, public workspace: IWorkspaceFolder, @IFileService private fileService: IFileService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IConfigurationService private configurationService: IConfigurationService, + @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, + @IConfigurationService protected configurationService: IConfigurationService, @IConfigurationResolverService private configurationResolverService: IConfigurationResolverService ) { // noop } + public get uri(): uri { + return this.workspace.uri.with({ path: paths.join(this.workspace.uri.path, '/.vscode/launch.json') }); + } + + public get name(): string { + return this.workspace.name; + } + + protected getConfig(): IGlobalConfig { + return this.configurationService.getValue('launch', { resource: this.workspace.uri }); + } + public getCompound(name: string): ICompound { - const config = this.configurationService.getValue('launch', { resource: this.workspace.uri }); + const config = this.getConfig(); if (!config || !config.compounds) { return null; } @@ -462,13 +525,13 @@ class Launch implements ILaunch { return config.compounds.filter(compound => compound.name === name).pop(); } - public getConfigurationNames(): string[] { - const config = this.configurationService.getValue('launch', { resource: this.workspace.uri }); + public getConfigurationNames(includeCompounds = true): string[] { + const config = this.getConfig(); if (!config || !config.configurations || !Array.isArray(config.configurations)) { return []; } else { const names = config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name); - if (names.length > 0 && config.compounds) { + if (includeCompounds && names.length > 0 && config.compounds) { if (config.compounds) { names.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length) .map(compound => compound.name)); @@ -480,7 +543,7 @@ class Launch implements ILaunch { } public getConfiguration(name: string): IConfig { - const config = objects.deepClone(this.configurationService.getValue('launch', { resource: this.workspace.uri })); + const config = this.getConfig(); if (!config || !config.configurations) { return null; } @@ -511,15 +574,11 @@ class Launch implements ILaunch { return this.configurationResolverService.resolveInteractiveVariables(result, adapter ? adapter.variables : null); } - public get uri(): uri { - return this.workspace.uri.with({ path: paths.join(this.workspace.uri.path, '/.vscode/launch.json') }); - } - - public openConfigFile(sideBySide: boolean, type?: string): TPromise<{ editor: IEditor; configFileCreated: boolean; }> { + public openConfigFile(sideBySide: boolean, type?: string): TPromise { const resource = this.uri; - let configFileCreated = false; + let pinned = false; - return this.fileService.resolveContent(resource).then(content => content, err => { + return this.fileService.resolveContent(resource).then(content => content.value, err => { // launch.json not found: create one by collecting launch configs from debugConfigProviders @@ -537,20 +596,20 @@ class Launch implements ILaunch { return undefined; } - configFileCreated = true; + pinned = true; // pin only if config file is created #8727 return this.fileService.updateContent(resource, content).then(() => { // convert string into IContent; see #32135 - return { value: content }; + return content; }); }); }).then(content => { if (!content) { - return { editor: undefined, configFileCreated }; + return undefined; } - const index = content.value.indexOf(`"${this.configurationManager.selectedName}"`); + const index = content.indexOf(`"${this.configurationManager.selectedName}"`); let startLineNumber = 1; for (let i = 0; i < index; i++) { - if (content.value.charAt(i) === '\n') { + if (content.charAt(i) === '\n') { startLineNumber++; } } @@ -561,12 +620,42 @@ class Launch implements ILaunch { options: { forceOpen: true, selection, - pinned: configFileCreated, // pin only if config file is created #8727 + pinned, revealIfVisible: true }, - }, sideBySide).then(editor => ({ editor, configFileCreated })); + }, sideBySide); }, (error) => { throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error)); }); } } + +class WorkspaceLaunch extends Launch implements ILaunch { + + constructor( + configurationManager: ConfigurationManager, + @IFileService fileService: IFileService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IConfigurationService configurationService: IConfigurationService, + @IConfigurationResolverService configurationResolverService: IConfigurationResolverService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService + ) { + super(configurationManager, undefined, fileService, editorService, configurationService, configurationResolverService); + } + + get uri(): uri { + return this.workspaceContextService.getWorkspace().configuration; + } + + get name(): string { + return nls.localize('workspace', "workspace"); + } + + protected getConfig(): IGlobalConfig { + return this.configurationService.inspect('launch').workspace; + } + + openConfigFile(sideBySide: boolean, type?: string): TPromise { + return this.editorService.openEditor({ resource: this.workspaceContextService.getWorkspace().configuration }); + } +} diff --git a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts index 9205cb17df3..5db4e4a3828 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts @@ -41,7 +41,6 @@ import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { first } from 'vs/base/common/arrays'; import { IMarginData } from 'vs/editor/browser/controller/mouseTarget'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IListService } from 'vs/platform/list/browser/listService'; const HOVER_DELAY = 300; const LAUNCH_JSON_REGEX = /launch\.json$/; @@ -78,13 +77,12 @@ export class DebugEditorContribution implements IDebugEditorContribution { @ICommandService private commandService: ICommandService, @ICodeEditorService private codeEditorService: ICodeEditorService, @ITelemetryService private telemetryService: ITelemetryService, - @IListService listService: IListService, @IConfigurationService private configurationService: IConfigurationService, @IThemeService themeService: IThemeService, @IKeybindingService private keybindingService: IKeybindingService ) { this.breakpointHintDecoration = []; - this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService, this.instantiationService, themeService, contextKeyService, listService); + this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService, this.instantiationService, themeService); this.toDispose = []; this.showHoverScheduler = new RunOnceScheduler(() => this.showHover(this.hoverRange, false), HOVER_DELAY); this.hideHoverScheduler = new RunOnceScheduler(() => this.hoverWidget.hide(), HOVER_DELAY); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts index 072347dc3b7..30c4fca4496 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts @@ -25,8 +25,7 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; const $ = dom.$; const MAX_ELEMENTS_SHOWN = 18; @@ -54,9 +53,7 @@ export class DebugHoverWidget implements IContentWidget { private editor: ICodeEditor, private debugService: IDebugService, private instantiationService: IInstantiationService, - private themeService: IThemeService, - private contextKeyService: IContextKeyService, - private listService: IListService + private themeService: IThemeService ) { this.toDispose = []; @@ -71,7 +68,7 @@ export class DebugHoverWidget implements IContentWidget { this.complexValueTitle = dom.append(this.complexValueContainer, $('.title')); this.treeContainer = dom.append(this.complexValueContainer, $('.debug-hover-tree')); this.treeContainer.setAttribute('role', 'tree'); - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new VariablesDataSource(), renderer: this.instantiationService.createInstance(VariablesHoverRenderer), controller: new DebugHoverController(this.editor) @@ -80,7 +77,7 @@ export class DebugHoverWidget implements IContentWidget { twistiePixels: 15, ariaLabel: nls.localize('treeAriaLabel', "Debug Hover"), keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); this.valueContainer = $('.value'); this.valueContainer.tabIndex = 0; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 26eadcb5141..5afd2c0b374 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -11,7 +11,6 @@ import * as strings from 'vs/base/common/strings'; import { generateUuid } from 'vs/base/common/uuid'; import uri from 'vs/base/common/uri'; import * as platform from 'vs/base/common/platform'; -import { Action } from 'vs/base/common/actions'; import { first, distinct } from 'vs/base/common/arrays'; import { isObject, isUndefinedOrNull } from 'vs/base/common/types'; import * as errors from 'vs/base/common/errors'; @@ -25,7 +24,7 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/files/common/files'; -import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; +import { IMessageService, CloseAction, IChoiceService } from 'vs/platform/message/common/message'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; @@ -37,7 +36,7 @@ import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import * as debugactions from 'vs/workbench/parts/debug/browser/debugActions'; import { ConfigurationManager } from 'vs/workbench/parts/debug/electron-browser/debugConfigurationManager'; -import { ToggleMarkersPanelAction } from 'vs/workbench/parts/markers/browser/markersPanelActions'; +import Constants from 'vs/workbench/parts/markers/common/constants'; import { ITaskService, ITaskSummary } from 'vs/workbench/parts/tasks/common/taskService'; import { TaskError } from 'vs/workbench/parts/tasks/common/taskSystem'; import { VIEWLET_ID as EXPLORER_VIEWLET_ID } from 'vs/workbench/parts/files/common/files'; @@ -89,6 +88,7 @@ export class DebugService implements debug.IDebugService { @IViewletService private viewletService: IViewletService, @IPanelService private panelService: IPanelService, @IMessageService private messageService: IMessageService, + @IChoiceService private choiceService: IChoiceService, @IPartService private partService: IPartService, @IWindowService private windowService: IWindowService, @IBroadcastService private broadcastService: IBroadcastService, @@ -607,8 +607,8 @@ export class DebugService implements debug.IDebugService { return this.sendAllBreakpoints(); } - public addFunctionBreakpoint(): void { - const newFunctionBreakpoint = this.model.addFunctionBreakpoint(''); + public addFunctionBreakpoint(name?: string, id?: string): void { + const newFunctionBreakpoint = this.model.addFunctionBreakpoint(name || '', id); this.viewModel.setSelectedFunctionBreakpoint(newFunctionBreakpoint); } @@ -668,8 +668,8 @@ export class DebugService implements debug.IDebugService { this.model.getBreakpoints().forEach(bp => bp.verified = false); } this.launchJsonChanged = false; - const manager = this.getConfigurationManager(); - const launch = root ? manager.getLaunches().filter(l => l.workspace.uri.toString() === root.uri.toString()).pop() : undefined; + const launch = root ? this.configurationManager.getLaunches().filter(l => l.workspace && l.workspace.uri.toString() === root.uri.toString()).pop() + : this.configurationManager.getWorkspaceLaunch(); let config: debug.IConfig, compound: debug.ICompound; if (!configOrName) { @@ -683,7 +683,7 @@ export class DebugService implements debug.IDebugService { } if (launch) { // in the drop down the name of the top most compound takes precedence over the launch config name - manager.selectConfiguration(launch, topCompoundName || (typeof configOrName === 'string' ? configOrName : undefined), true); + this.configurationManager.selectConfiguration(launch, topCompoundName || (typeof configOrName === 'string' ? configOrName : undefined), true); } if (compound) { @@ -692,7 +692,35 @@ export class DebugService implements debug.IDebugService { "Compound must have \"configurations\" attribute set in order to start multiple configurations."))); } - return TPromise.join(compound.configurations.map(name => name !== compound.name ? this.startDebugging(root, name, noDebug, topCompoundName || compound.name) : TPromise.as(null))); + return TPromise.join(compound.configurations.map(configData => { + const name = typeof configData === 'string' ? configData : configData.name; + if (name === compound.name) { + return TPromise.as(null); + } + + let rootForName: IWorkspaceFolder; + if (typeof configData === 'string') { + const launchesContainingName = this.configurationManager.getLaunches().filter(l => !!l.getConfiguration(name)); + if (launchesContainingName.length === 1) { + rootForName = launchesContainingName[0].workspace; + } else if (launchesContainingName.length > 1 && launchesContainingName.indexOf(launch) >= 0) { + // If there are multiple launches containing the configuration give priority to the configuration in the current launch + rootForName = launch.workspace; + } else { + return TPromise.wrapError(new Error(launchesContainingName.length === 0 ? nls.localize('noConfigurationNameInWorkspace', "Could not find launch configuration '{0}' in the workspace.", name) + : nls.localize('multipleConfigurationNamesInWorkspace', "There are multiple launch configurates `{0}` in the workspace. Use folder name to qualify the configuration.", name))); + } + } else if (configData.folder) { + const root = this.contextService.getWorkspace().folders.filter(f => f.name === configData.folder).pop(); + if (root) { + rootForName = root; + } else { + return TPromise.wrapError(new Error(nls.localize('noFolderWithName', "Can not find folder with name '{0}' for configuration '{1}' in compound '{2}'.", configData.folder, configData.name, compound.name))); + } + } + + return this.startDebugging(rootForName, name, noDebug, topCompoundName || compound.name); + })); } if (configOrName && !config) { const message = !!launch ? nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", configOrName) : @@ -723,14 +751,11 @@ export class DebugService implements debug.IDebugService { return (type ? TPromise.as(null) : this.configurationManager.guessAdapter().then(a => type = a && a.type)).then(() => (type ? this.extensionService.activateByEvent(`onDebugResolve:${type}`) : TPromise.as(null)).then(() => - this.configurationManager.resolveConfigurationByProviders(launch ? launch.workspace.uri : undefined, type, config).then(config => { + this.configurationManager.resolveConfigurationByProviders(launch && launch.workspace ? launch.workspace.uri : undefined, type, config).then(config => { // a falsy config indicates an aborted launch if (config && config.type) { return this.createProcess(root, config, sessionId); } - if (launch) { - return launch.openConfigFile(false, type).then(() => undefined); - } return undefined; }) @@ -765,10 +790,6 @@ export class DebugService implements debug.IDebugService { } this.toDisposeOnSessionEnd.set(sessionId, []); - const debugAnywayAction = new Action('debug.continue', nls.localize('debugAnyway', "Debug Anyway"), null, true, () => { - this.messageService.hideAll(); - return this.doCreateProcess(root, resolvedConfig, sessionId); - }); return this.runPreLaunchTask(sessionId, root, resolvedConfig.preLaunchTask).then((taskSummary: ITaskSummary) => { const errorCount = resolvedConfig.preLaunchTask ? this.markerService.getStatistics().errors : 0; @@ -778,26 +799,32 @@ export class DebugService implements debug.IDebugService { return this.doCreateProcess(root, resolvedConfig, sessionId); } - this.messageService.show(severity.Error, { - message: errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", resolvedConfig.preLaunchTask) : - errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", resolvedConfig.preLaunchTask) : - nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", resolvedConfig.preLaunchTask, taskSummary.exitCode), - actions: [ - debugAnywayAction, - this.instantiationService.createInstance(ToggleMarkersPanelAction, ToggleMarkersPanelAction.ID, ToggleMarkersPanelAction.LABEL), - CloseAction - ] + const message = errorCount > 1 ? nls.localize('preLaunchTaskErrors', "Build errors have been detected during preLaunchTask '{0}'.", resolvedConfig.preLaunchTask) : + errorCount === 1 ? nls.localize('preLaunchTaskError', "Build error has been detected during preLaunchTask '{0}'.", resolvedConfig.preLaunchTask) : + nls.localize('preLaunchTaskExitCode', "The preLaunchTask '{0}' terminated with exit code {1}.", resolvedConfig.preLaunchTask, taskSummary.exitCode); + + return this.choiceService.choose(severity.Error, message, [nls.localize('debugAnyway', "Debug Anyway"), nls.localize('showErrors', "Show Errors"), nls.localize('cancel', "Cancel")], 2, true).then(choice => { + switch (choice) { + case 0: + return this.doCreateProcess(root, resolvedConfig, sessionId); + case 1: + return this.panelService.openPanel(Constants.MARKERS_PANEL_ID).then(() => undefined); + default: + return undefined; + } }); - return undefined; }, (err: TaskError) => { - this.messageService.show(err.severity, { - message: err.message, - actions: [ - debugAnywayAction, - this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), - this.taskService.configureAction(), - CloseAction - ] + return this.choiceService.choose(severity.Error, err.message, [nls.localize('debugAnyway', "Debug Anyway"), debugactions.ConfigureAction.LABEL, this.taskService.configureAction().label, nls.localize('cancel', "Cancel")], 3, true).then(choice => { + switch (choice) { + case 0: + return this.doCreateProcess(root, resolvedConfig, sessionId); + case 1: + return this.configurationManager.selectedLaunch.openConfigFile(false); + case 2: + return this.taskService.configureAction().run(); + default: + return undefined; + } }); }); }, err => { @@ -806,12 +833,7 @@ export class DebugService implements debug.IDebugService { return undefined; } - return this.configurationManager.selectedLaunch.openConfigFile(false).then(result => { - if (result.configFileCreated) { - this.messageService.show(severity.Info, nls.localize('NewLaunchConfig', "Please set up the launch configuration file for your application. {0}", err.message)); - } - return undefined; - }); + return this.configurationManager.selectedLaunch.openConfigFile(false).then(editor => void 0); }) ); } @@ -1021,43 +1043,45 @@ export class DebugService implements debug.IDebugService { } public restartProcess(process: debug.IProcess, restartData?: any): TPromise { - if (process.session.capabilities.supportsRestartRequest) { - return process.session.custom('restart', null); - } - const focusedProcess = this.viewModel.focusedProcess; - const preserveFocus = focusedProcess && process.getId() === focusedProcess.getId(); - - return process.session.disconnect(true).then(() => { - if (strings.equalsIgnoreCase(process.configuration.type, 'extensionHost')) { - return this.broadcastService.broadcast({ - channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, - payload: [process.session.root.uri.fsPath] - }); + return this.textFileService.saveAll().then(() => { + if (process.session.capabilities.supportsRestartRequest) { + return process.session.custom('restart', null); } + const focusedProcess = this.viewModel.focusedProcess; + const preserveFocus = focusedProcess && process.getId() === focusedProcess.getId(); - return new TPromise((c, e) => { - setTimeout(() => { - // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration - let config = process.configuration; - if (this.launchJsonChanged && this.configurationManager.selectedLaunch) { - this.launchJsonChanged = false; - config = this.configurationManager.selectedLaunch.getConfiguration(process.configuration.name) || config; - // Take the type from the process since the debug extension might overwrite it #21316 - config.type = process.configuration.type; - config.noDebug = process.configuration.noDebug; - } - config.__restart = restartData; - this.startDebugging(process.session.root, config).then(() => c(null), err => e(err)); - }, 300); - }); - }).then(() => { - if (preserveFocus) { - // Restart should preserve the focused process - const restartedProcess = this.model.getProcesses().filter(p => p.configuration.name === process.configuration.name).pop(); - if (restartedProcess && restartedProcess !== this.viewModel.focusedProcess) { - this.focusStackFrame(undefined, undefined, restartedProcess); + return process.session.disconnect(true).then(() => { + if (strings.equalsIgnoreCase(process.configuration.type, 'extensionHost') && process.session.root) { + return this.broadcastService.broadcast({ + channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, + payload: [process.session.root.uri.fsPath] + }); } - } + + return new TPromise((c, e) => { + setTimeout(() => { + // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration + let config = process.configuration; + if (this.launchJsonChanged && this.configurationManager.selectedLaunch) { + this.launchJsonChanged = false; + config = this.configurationManager.selectedLaunch.getConfiguration(process.configuration.name) || config; + // Take the type from the process since the debug extension might overwrite it #21316 + config.type = process.configuration.type; + config.noDebug = process.configuration.noDebug; + } + config.__restart = restartData; + this.startDebugging(process.session.root, config).then(() => c(null), err => e(err)); + }, 300); + }); + }).then(() => { + if (preserveFocus) { + // Restart should preserve the focused process + const restartedProcess = this.model.getProcesses().filter(p => p.configuration.name === process.configuration.name).pop(); + if (restartedProcess && restartedProcess !== this.viewModel.focusedProcess) { + this.focusStackFrame(undefined, undefined, restartedProcess); + } + } + }); }); } diff --git a/src/vs/workbench/parts/debug/electron-browser/repl.ts b/src/vs/workbench/parts/debug/electron-browser/repl.ts index db4c7dd26a1..6ea2b74afef 100644 --- a/src/vs/workbench/parts/debug/electron-browser/repl.ts +++ b/src/vs/workbench/parts/debug/electron-browser/repl.ts @@ -41,7 +41,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { clipboard } from 'electron'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { memoize } from 'vs/base/common/decorators'; import { dispose } from 'vs/base/common/lifecycle'; @@ -93,8 +93,7 @@ export class Repl extends Panel implements IPrivateReplService { @IPanelService private panelService: IPanelService, @IThemeService protected themeService: IThemeService, @IModelService private modelService: IModelService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IListService private listService: IListService + @IContextKeyService private contextKeyService: IContextKeyService ) { super(debug.REPL_ID, telemetryService, themeService); @@ -139,12 +138,12 @@ export class Repl extends Panel implements IPrivateReplService { const controller = this.instantiationService.createInstance(ReplExpressionsController, new ReplExpressionsActionProvider(this.instantiationService), MenuId.DebugConsoleContext); controller.toFocusOnClick = this.replInput; - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new ReplExpressionsDataSource(), renderer: this.renderer, accessibilityProvider: new ReplExpressionsAccessibilityProvider(), controller - }, replTreeOptions, this.contextKeyService, this.listService, this.themeService); + }, replTreeOptions); if (!Repl.HISTORY) { Repl.HISTORY = new ReplHistory(JSON.parse(this.storageService.get(HISTORY_STORAGE_KEY, StorageScope.WORKSPACE, '[]'))); diff --git a/src/vs/workbench/parts/debug/electron-browser/variablesView.ts b/src/vs/workbench/parts/debug/electron-browser/variablesView.ts index 36384afa9f8..e157a61a862 100644 --- a/src/vs/workbench/parts/debug/electron-browser/variablesView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/variablesView.ts @@ -16,7 +16,6 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MenuId } from 'vs/platform/actions/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { once } from 'vs/base/common/event'; import { twistiePixels, renderViewTree, IVariableTemplateData, BaseDebugController, renderRenameBox, renderVariable } from 'vs/workbench/parts/debug/electron-browser/baseDebugView'; @@ -28,7 +27,7 @@ import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; const $ = dom.$; @@ -45,10 +44,7 @@ export class VariablesView extends TreeViewsViewletPanel { @IContextMenuService contextMenuService: IContextMenuService, @IDebugService private debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService, - @IInstantiationService private instantiationService: IInstantiationService, - @IListService private listService: IListService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IThemeService private themeService: IThemeService + @IInstantiationService private instantiationService: IInstantiationService ) { super({ ...(options as IViewOptions), ariaHeaderLabel: nls.localize('variablesSection', "Variables Section") }, keybindingService, contextMenuService); @@ -87,7 +83,7 @@ export class VariablesView extends TreeViewsViewletPanel { dom.addClass(container, 'debug-variables'); this.treeContainer = renderViewTree(container); - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new VariablesDataSource(), renderer: this.instantiationService.createInstance(VariablesRenderer), accessibilityProvider: new VariablesAccessibilityProvider(), @@ -96,7 +92,7 @@ export class VariablesView extends TreeViewsViewletPanel { ariaLabel: nls.localize('variablesAriaTreeLabel', "Debug Variables"), twistiePixels, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); CONTEXT_VARIABLES_FOCUSED.bindTo(this.tree.contextKeyService); diff --git a/src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts b/src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts index 23ddbee6eff..dbbd7bfeb29 100644 --- a/src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts +++ b/src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts @@ -19,7 +19,6 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MenuId } from 'vs/platform/actions/common/actions'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { once } from 'vs/base/common/event'; import { IAction, IActionItem } from 'vs/base/common/actions'; @@ -29,7 +28,7 @@ import { equalsIgnoreCase } from 'vs/base/common/strings'; import { IMouseEvent, DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { DefaultDragAndDrop } from 'vs/base/parts/tree/browser/treeDefaults'; import { IVariableTemplateData, renderVariable, renderRenameBox, renderExpressionValue, BaseDebugController, twistiePixels, renderViewTree } from 'vs/workbench/parts/debug/electron-browser/baseDebugView'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; const $ = dom.$; const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024; @@ -46,10 +45,7 @@ export class WatchExpressionsView extends TreeViewsViewletPanel { @IContextMenuService contextMenuService: IContextMenuService, @IDebugService private debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IListService private listService: IListService, - @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService private themeService: IThemeService + @IInstantiationService private instantiationService: IInstantiationService ) { super({ ...(options as IViewOptions), ariaHeaderLabel: nls.localize('expressionsSection', "Expressions Section") }, keybindingService, contextMenuService); this.settings = options.viewletSettings; @@ -65,7 +61,7 @@ export class WatchExpressionsView extends TreeViewsViewletPanel { this.treeContainer = renderViewTree(container); const actionProvider = new WatchExpressionsActionProvider(this.debugService, this.keybindingService); - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new WatchExpressionsDataSource(this.debugService), renderer: this.instantiationService.createInstance(WatchExpressionsRenderer), accessibilityProvider: new WatchExpressionsAccessibilityProvider(), @@ -75,7 +71,7 @@ export class WatchExpressionsView extends TreeViewsViewletPanel { ariaLabel: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'watchAriaTreeLabel' }, "Debug Watch Expressions"), twistiePixels, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); CONTEXT_WATCH_EXPRESSIONS_FOCUSED.bindTo(this.tree.contextKeyService); diff --git a/src/vs/workbench/parts/extensions/browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/browser/extensionEditor.ts index 95a51e0fadc..f101cbd65d6 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionEditor.ts @@ -30,10 +30,10 @@ import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, IExtensionDependencies } from 'vs/workbench/parts/extensions/common/extensions'; import { Renderer, DataSource, Controller } from 'vs/workbench/parts/extensions/browser/dependenciesViewer'; -import { RatingsWidget, InstallWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; +import { RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; import { EditorOptions } from 'vs/workbench/common/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, BuiltinStatusLabelAction, ReloadAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; +import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, BuiltinStatusLabelAction, ReloadAction, MaliciousStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import WebView from 'vs/workbench/parts/html/browser/webview'; import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -51,7 +51,8 @@ import { Command, ICommandOptions } from 'vs/editor/browser/editorExtensions'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { Color } from 'vs/base/common/color'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; /** A context key that is set when an extension editor webview has focus. */ export const KEYBINDING_CONTEXT_EXTENSIONEDITOR_WEBVIEW_FOCUS = new RawContextKey('extensionEditorWebviewFocus', undefined); @@ -63,12 +64,13 @@ export const KEYBINDING_CONTEXT_EXTENSIONEDITOR_FIND_WIDGET_INPUT_FOCUSED = new export const KEYBINDING_CONTEXT_EXTENSIONEDITOR_FIND_WIDGET_INPUT_NOT_FOCUSED: ContextKeyExpr = KEYBINDING_CONTEXT_EXTENSIONEDITOR_FIND_WIDGET_INPUT_FOCUSED.toNegated(); function renderBody(body: string): string { + const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-core-resource://'); return ` - - + + @@ -190,11 +192,12 @@ export class ExtensionEditor extends BaseEditor { @IKeybindingService private keybindingService: IKeybindingService, @IMessageService private messageService: IMessageService, @IOpenerService private openerService: IOpenerService, - @IListService private listService: IListService, @IPartService private partService: IPartService, @IContextViewService private contextViewService: IContextViewService, @IContextKeyService private contextKeyService: IContextKeyService, - @IExtensionTipsService private extensionTipsService: IExtensionTipsService + @IExtensionTipsService private extensionTipsService: IExtensionTipsService, + @IEnvironmentService private environmentService: IEnvironmentService + ) { super(ExtensionEditor.ID, telemetryService, themeService); this.disposables = []; @@ -334,13 +337,14 @@ export class ExtensionEditor extends BaseEditor { this.repository.style.display = 'none'; } - const install = this.instantiationService.createInstance(InstallWidget, this.installCount, { extension }); + const install = this.instantiationService.createInstance(InstallCountWidget, this.installCount, { extension }); this.transientDisposables.push(install); const ratings = this.instantiationService.createInstance(RatingsWidget, this.rating, { extension }); this.transientDisposables.push(ratings); const builtinStatusAction = this.instantiationService.createInstance(BuiltinStatusLabelAction); + const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, true); const installAction = this.instantiationService.createInstance(CombinedInstallAction); const updateAction = this.instantiationService.createInstance(UpdateAction); const enableAction = this.instantiationService.createInstance(EnableAction); @@ -349,14 +353,15 @@ export class ExtensionEditor extends BaseEditor { installAction.extension = extension; builtinStatusAction.extension = extension; + maliciousStatusAction.extension = extension; updateAction.extension = extension; enableAction.extension = extension; disableAction.extension = extension; reloadAction.extension = extension; this.extensionActionBar.clear(); - this.extensionActionBar.push([reloadAction, updateAction, enableAction, disableAction, installAction, builtinStatusAction], { icon: true, label: true }); - this.transientDisposables.push(enableAction, updateAction, reloadAction, disableAction, installAction, builtinStatusAction); + this.extensionActionBar.push([reloadAction, updateAction, enableAction, disableAction, installAction, builtinStatusAction, maliciousStatusAction], { icon: true, label: true }); + this.transientDisposables.push(enableAction, updateAction, reloadAction, disableAction, installAction, builtinStatusAction, maliciousStatusAction); this.navbar.clear(); this.navbar.onChange(this.onNavbarChange.bind(this, extension), this, this.transientDisposables); @@ -412,8 +417,8 @@ export class ExtensionEditor extends BaseEditor { .then(removeEmbeddedSVGs) .then(body => { const allowedBadgeProviders = this.extensionsWorkbenchService.allowedBadgeProviders; - const webViewOptions = allowedBadgeProviders.length > 0 ? { allowScripts: false, allowSvgs: false, svgWhiteList: allowedBadgeProviders } : undefined; - this.activeWebview = new WebView(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions); + const webViewOptions = allowedBadgeProviders.length > 0 ? { allowScripts: false, allowSvgs: false, svgWhiteList: allowedBadgeProviders } : {}; + this.activeWebview = new WebView(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.environmentService, this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions, false); const removeLayoutParticipant = arrays.insert(this.layoutParticipants, this.activeWebview); this.contentDisposables.push(toDisposable(removeLayoutParticipant)); @@ -462,7 +467,8 @@ export class ExtensionEditor extends BaseEditor { this.renderColors(content, manifest, layout), this.renderJSONValidation(content, manifest, layout), this.renderDebuggers(content, manifest, layout), - this.renderViews(content, manifest, layout) + this.renderViews(content, manifest, layout), + this.renderLocalizations(content, manifest, layout) ]; const isEmpty = !renders.reduce((v, r) => r || v, false); @@ -514,7 +520,7 @@ export class ExtensionEditor extends BaseEditor { private renderDependencies(container: HTMLElement, extensionDependencies: IExtensionDependencies): Tree { const renderer = this.instantiationService.createInstance(Renderer); const controller = this.instantiationService.createInstance(Controller); - const tree = new WorkbenchTree(container, { + const tree = this.instantiationService.createInstance(WorkbenchTree, container, { dataSource: new DataSource(), renderer, controller @@ -522,7 +528,7 @@ export class ExtensionEditor extends BaseEditor { indentPixels: 40, twistiePixels: 20, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); tree.setInput(extensionDependencies); @@ -618,6 +624,26 @@ export class ExtensionEditor extends BaseEditor { return true; } + private renderLocalizations(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean { + const contributes = manifest.contributes; + const localizations = contributes && contributes.localizations || []; + + if (!localizations.length) { + return false; + } + + const details = $('details', { open: true, ontoggle: onDetailsToggle }, + $('summary', null, localize('localizations', "Localizations ({0})", localizations.length)), + $('table', null, + $('tr', null, $('th', null, localize('localizations language id', "Language Id")), $('th', null, localize('localizations language name', "Langauge Name")), $('th', null, localize('translations location', "Translations Location"))), + ...localizations.map(localization => $('tr', null, $('td', null, localization.languageId), $('td', null, localization.languageName), $('td', null, localization.translations))) + ) + ); + + append(container, details); + return true; + } + private renderColorThemes(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean { const contributes = manifest.contributes; const contrib = contributes && contributes.themes || []; diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index fa54bc803d7..84f9afb3ff8 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -437,7 +437,7 @@ export class EnableForWorkspaceAction extends Action implements IExtensionAction private update(): void { this.enabled = false; if (this.extension) { - this.enabled = (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && this.extensionEnablementService.canChangeEnablement(); + this.enabled = (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -475,7 +475,7 @@ export class EnableGloballyAction extends Action implements IExtensionAction { private update(): void { this.enabled = false; if (this.extension) { - this.enabled = (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && this.extensionEnablementService.canChangeEnablement(); + this.enabled = (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -560,7 +560,8 @@ export class DisableForWorkspaceAction extends Action implements IExtensionActio constructor(label: string, @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService, - @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService + @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, + @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService ) { super(DisableForWorkspaceAction.ID, label); @@ -572,7 +573,7 @@ export class DisableForWorkspaceAction extends Action implements IExtensionActio private update(): void { this.enabled = false; if (this.extension && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - this.enabled = this.extension.type !== LocalExtensionType.System && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled); + this.enabled = this.extension.type !== LocalExtensionType.System && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -598,7 +599,8 @@ export class DisableGloballyAction extends Action implements IExtensionAction { set extension(extension: IExtension) { this._extension = extension; this.update(); } constructor(label: string, - @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService + @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, + @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService ) { super(DisableGloballyAction.ID, label); @@ -609,7 +611,7 @@ export class DisableGloballyAction extends Action implements IExtensionAction { private update(): void { this.enabled = false; if (this.extension) { - this.enabled = this.extension.type !== LocalExtensionType.System && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled); + this.enabled = this.extension.type !== LocalExtensionType.System && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -1553,6 +1555,34 @@ export class BuiltinStatusLabelAction extends Action { } } +export class MaliciousStatusLabelAction extends Action { + + private static readonly Class = 'malicious-status'; + + private _extension: IExtension; + get extension(): IExtension { return this._extension; } + set extension(extension: IExtension) { this._extension = extension; this.update(); } + + constructor(long: boolean) { + const tooltip = localize('malicious tooltip', "This extension was reported to be malicious."); + const label = long ? tooltip : localize('malicious', "Malicious"); + super('extensions.install', label, '', false); + this.tooltip = localize('malicious tooltip', "This extension was reported to be malicious."); + } + + private update(): void { + if (this.extension && this.extension.isMalicious) { + this.class = `${MaliciousStatusLabelAction.Class} malicious`; + } else { + this.class = `${MaliciousStatusLabelAction.Class} not-malicious`; + } + } + + run(): TPromise { + return TPromise.as(null); + } +} + export class DisableAllAction extends Action { static readonly ID = 'workbench.extensions.action.disableAll'; @@ -1633,7 +1663,7 @@ export class EnableAllAction extends Action { } private update(): void { - this.enabled = this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canChangeEnablement() && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); + this.enabled = this.extensionsWorkbenchService.local.some(e => e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); } run(): TPromise { @@ -1666,7 +1696,7 @@ export class EnableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canChangeEnablement() && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); + this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); } run(): TPromise { @@ -1690,6 +1720,17 @@ CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsForL }); }); +CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsWithId', function (accessor: ServicesAccessor, extensionId: string) { + const viewletService = accessor.get(IViewletService); + + return viewletService.openViewlet(VIEWLET_ID, true) + .then(viewlet => viewlet as IExtensionsViewlet) + .then(viewlet => { + viewlet.search(`@id:${extensionId}`); + viewlet.focus(); + }); +}); + export const extensionButtonProminentBackground = registerColor('extensionButton.prominentBackground', { dark: '#327e36', light: '#327e36', diff --git a/src/vs/workbench/parts/extensions/browser/extensionsList.ts b/src/vs/workbench/parts/extensions/browser/extensionsList.ts index 2179edff031..fbe2e45ff31 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsList.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsList.ts @@ -16,9 +16,9 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; import { once } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { IExtension, IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions'; -import { InstallAction, UpdateAction, BuiltinStatusLabelAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground } from 'vs/workbench/parts/extensions/browser/extensionsActions'; +import { InstallAction, UpdateAction, BuiltinStatusLabelAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { Label, RatingsWidget, InstallWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; +import { Label, RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -93,17 +93,18 @@ export class Renderer implements IPagedRenderer { actionbar.onDidRun(({ error }) => error && this.messageService.show(Severity.Error, error)); const versionWidget = this.instantiationService.createInstance(Label, version, (e: IExtension) => e.version); - const installCountWidget = this.instantiationService.createInstance(InstallWidget, installCount, { small: true }); + const installCountWidget = this.instantiationService.createInstance(InstallCountWidget, installCount, { small: true }); const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, ratings, { small: true }); const builtinStatusAction = this.instantiationService.createInstance(BuiltinStatusLabelAction); + const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, false); const installAction = this.instantiationService.createInstance(InstallAction); const updateAction = this.instantiationService.createInstance(UpdateAction); const reloadAction = this.instantiationService.createInstance(ReloadAction); const manageAction = this.instantiationService.createInstance(ManageExtensionAction); - actionbar.push([reloadAction, updateAction, installAction, builtinStatusAction, manageAction], actionOptions); - const disposables = [versionWidget, installCountWidget, ratingsWidget, builtinStatusAction, updateAction, reloadAction, manageAction, actionbar, bookmarkStyler]; + actionbar.push([reloadAction, updateAction, installAction, builtinStatusAction, maliciousStatusAction, manageAction], actionOptions); + const disposables = [versionWidget, installCountWidget, ratingsWidget, builtinStatusAction, maliciousStatusAction, updateAction, reloadAction, manageAction, actionbar, bookmarkStyler]; return { root, element, icon, name, installCount, ratings, author, description, disposables, @@ -113,6 +114,7 @@ export class Renderer implements IPagedRenderer { installCountWidget.extension = extension; ratingsWidget.extension = extension; builtinStatusAction.extension = extension; + maliciousStatusAction.extension = extension; installAction.extension = extension; updateAction.extension = extension; reloadAction.extension = extension; diff --git a/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts b/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts index e2af2e4e734..cf4aebc302c 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsQuickOpen.ts @@ -11,6 +11,7 @@ import { QuickOpenHandler } from 'vs/workbench/browser/quickopen'; import { IExtensionsViewlet, VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IMessageService, Severity } from 'vs/platform/message/common/message'; class SimpleEntry extends QuickOpenEntry { @@ -75,7 +76,8 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { constructor( @IViewletService private viewletService: IViewletService, @IExtensionGalleryService private galleryService: IExtensionGalleryService, - @IExtensionManagementService private extensionsService: IExtensionManagementService + @IExtensionManagementService private extensionsService: IExtensionManagementService, + @IMessageService private messageService: IMessageService ) { super(); } @@ -97,7 +99,8 @@ export class GalleryExtensionsHandler extends QuickOpenHandler { return this.viewletService.openViewlet(VIEWLET_ID, true) .then(viewlet => viewlet as IExtensionsViewlet) .then(viewlet => viewlet.search(`@id:${text}`)) - .done(() => this.extensionsService.installFromGallery(galleryExtension)); + .then(() => this.extensionsService.installFromGallery(galleryExtension)) + .done(null, err => this.messageService.show(Severity.Error, err)); }; entries.push(new SimpleEntry(label, action)); diff --git a/src/vs/workbench/parts/extensions/browser/extensionsWidgets.ts b/src/vs/workbench/parts/extensions/browser/extensionsWidgets.ts index 3167b710f49..f8e86e08d88 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsWidgets.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsWidgets.ts @@ -42,7 +42,7 @@ export class Label implements IDisposable { } } -export class InstallWidget implements IDisposable { +export class InstallCountWidget implements IDisposable { private disposables: IDisposable[] = []; private _extension: IExtension; diff --git a/src/vs/workbench/parts/extensions/browser/media/extensionActions.css b/src/vs/workbench/parts/extensions/browser/media/extensionActions.css index 8314dddb331..9ff9876d7e5 100644 --- a/src/vs/workbench/parts/extensions/browser/media/extensionActions.css +++ b/src/vs/workbench/parts/extensions/browser/media/extensionActions.css @@ -30,11 +30,13 @@ .monaco-action-bar .action-item.disabled .action-label.extension-action.enable, .monaco-action-bar .action-item.disabled .action-label.extension-action.disable, .monaco-action-bar .action-item.disabled .action-label.extension-action.reload, -.monaco-action-bar .action-item.disabled .action-label.built-in-status.user { +.monaco-action-bar .action-item.disabled .action-label.built-in-status.user, +.monaco-action-bar .action-item.disabled .action-label.malicious-status.not-malicious { display: none; } -.monaco-action-bar .action-item .action-label.built-in-status { +.monaco-action-bar .action-item .action-label.built-in-status +.monaco-action-bar .action-item .action-label.malicious-status { border-radius: 4px; color: inherit; background-color: transparent; @@ -44,7 +46,8 @@ line-height: initial; } -.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.built-in-status { +.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.built-in-status, +.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.malicious-status { font-weight: normal; } diff --git a/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css b/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css index 01dd0458f1d..75f9f139f12 100644 --- a/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/parts/extensions/browser/media/extensionEditor.css @@ -171,6 +171,7 @@ height: calc(100% - 36px); position: relative; overflow: hidden; + user-select: text; } .extension-editor > .body > .content.loading { diff --git a/src/vs/workbench/parts/extensions/common/extensions.ts b/src/vs/workbench/parts/extensions/common/extensions.ts index b836148a1b7..d26c46d117b 100644 --- a/src/vs/workbench/parts/extensions/common/extensions.ts +++ b/src/vs/workbench/parts/extensions/common/extensions.ts @@ -8,7 +8,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import Event from 'vs/base/common/event'; import { TPromise } from 'vs/base/common/winjs.base'; import { IPager } from 'vs/base/common/paging'; -import { IQueryOptions, IExtensionManifest, LocalExtensionType, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IQueryOptions, IExtensionManifest, LocalExtensionType, EnablementState, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; export const VIEWLET_ID = 'workbench.view.extensions'; @@ -51,6 +51,8 @@ export interface IExtension { getManifest(): TPromise; getReadme(): TPromise; getChangelog(): TPromise; + local?: ILocalExtension; + isMalicious: boolean; } export interface IExtensionDependencies { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts index 307d628fdd3..7a8e65fd19e 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts @@ -16,6 +16,7 @@ import { StatusbarAlignment, IStatusbarRegistry, StatusbarItemDescriptor, Extens import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionHostProfileService, ProfileSessionState, RuntimeExtensionsInput } from 'vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IMessageService, Severity } from 'vs/platform/message/common/message'; export class ExtensionHostProfileService extends Disposable implements IExtensionHostProfileService { @@ -38,6 +39,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio @IExtensionService private readonly _extensionService: IExtensionService, @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IMessageService private readonly _messageService: IMessageService ) { super(); this._profile = null; @@ -67,6 +69,12 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio if (this._state !== ProfileSessionState.None) { return; } + + if (!this._extensionService.canProfileExtensionHost()) { + this._messageService.show(Severity.Info, nls.localize('noPro', "To profile extensions, launch with `--inspect-extensions=`.")); + return; + } + this._setState(ProfileSessionState.Starting); this._extensionService.startExtensionHostProfile().then((value) => { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index d097b862e8e..82e056f0e3b 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -29,6 +29,9 @@ import * as pfs from 'vs/base/node/pfs'; import * as os from 'os'; import { flatten, distinct } from 'vs/base/common/arrays'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { guessMimeTypes, MIME_UNKNOWN } from 'vs/base/common/mime'; +import { ShowLanguageExtensionsAction } from 'vs/workbench/browser/parts/editor/editorStatus'; +import { IExtensionService } from 'vs/platform/extensions/common/extensions'; interface IExtensionsContent { recommendations: string[]; @@ -36,6 +39,8 @@ interface IExtensionsContent { const empty: { [key: string]: any; } = Object.create(null); const milliSecondsInADay = 1000 * 60 * 60 * 24; +const choiceNever = localize('neverShowAgain', "Don't show again"); +const choiceClose = localize('close', "Close"); export class ExtensionTipsService extends Disposable implements IExtensionTipsService { @@ -61,7 +66,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe @IConfigurationService private configurationService: IConfigurationService, @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService, - @IEnvironmentService private environmentService: IEnvironmentService + @IEnvironmentService private environmentService: IEnvironmentService, + @IExtensionService private extensionService: IExtensionService ) { super(); @@ -70,6 +76,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe } this._suggestFileBasedRecommendations(); + this.promptWorkspaceRecommendationsPromise = this._suggestWorkspaceRecommendations(); // Executable based recommendations carry out a lot of file stats, so run them after 10 secs @@ -254,8 +261,15 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe this._modelService.getModels().forEach(model => this._suggest(model)); } + private getMimeTypes(path: string): TPromise { + return this.extensionService.whenInstalledExtensionsRegistered().then(() => { + return guessMimeTypes(path); + }); + } + private _suggest(model: ITextModel): void { const uri = model.uri; + let hasSuggestion = false; if (!uri || uri.scheme !== Schemas.file) { return; @@ -282,91 +296,176 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe ); const config = this.configurationService.getValue(ConfigurationKey); - const importantRecommendationsIgnoreList = JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]')); - - if (config.ignoreRecommendations || !product.extensionImportantTips) { + if (config.ignoreRecommendations) { return; } - this.extensionsService.getInstalled(LocalExtensionType.User).done(local => { - Object.keys(product.extensionImportantTips) - .filter(id => importantRecommendationsIgnoreList.indexOf(id) === -1) - .filter(id => local.every(local => `${local.manifest.publisher}.${local.manifest.name}` !== id)) - .forEach(id => { - const { pattern, name } = product.extensionImportantTips[id]; + const importantRecommendationsIgnoreList = JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]')); + let recommendationsToSuggest = Object.keys(product.extensionImportantTips || []) + .filter(id => importantRecommendationsIgnoreList.indexOf(id) === -1 && match(product.extensionImportantTips[id]['pattern'], uri.fsPath)); - if (!match(pattern, uri.fsPath)) { - return; - } + const importantTipsPromise = recommendationsToSuggest.length === 0 ? TPromise.as(null) : this.extensionsService.getInstalled(LocalExtensionType.User).then(local => { + recommendationsToSuggest = recommendationsToSuggest.filter(id => local.every(local => `${local.manifest.publisher}.${local.manifest.name}` !== id)); + if (!recommendationsToSuggest.length) { + return; + } + const id = recommendationsToSuggest[0]; + const name = product.extensionImportantTips[id]['name']; - let message = localize('reallyRecommended2', "The '{0}' extension is recommended for this file type.", name); - // Temporary fix for the only extension pack we recommend. See https://github.com/Microsoft/vscode/issues/35364 - if (id === 'vscjava.vscode-java-pack') { - message = localize('reallyRecommendedExtensionPack', "The '{0}' extension pack is recommended for this file type.", name); - } + // Indicates we have a suggested extension via the whitelist + hasSuggestion = true; - const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); - const installAction = this.instantiationService.createInstance(InstallRecommendedExtensionAction, id); - const options = [ - localize('install', 'Install'), - recommendationsAction.label, - localize('neverShowAgain', "Don't Show Again"), - localize('close', "Close") - ]; + let message = localize('reallyRecommended2', "The '{0}' extension is recommended for this file type.", name); + // Temporary fix for the only extension pack we recommend. See https://github.com/Microsoft/vscode/issues/35364 + if (id === 'vscjava.vscode-java-pack') { + message = localize('reallyRecommendedExtensionPack', "The '{0}' extension pack is recommended for this file type.", name); + } - this.choiceService.choose(Severity.Info, message, options, 3).done(choice => { - switch (choice) { - case 0: - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'install', extensionId: name }); - return installAction.run(); - case 1: - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'show', extensionId: name }); - return recommendationsAction.run(); - case 2: importantRecommendationsIgnoreList.push(id); - this.storageService.store( - 'extensionsAssistant/importantRecommendationsIgnore', - JSON.stringify(importantRecommendationsIgnoreList), - StorageScope.GLOBAL - ); - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId: name }); - return this.ignoreExtensionRecommendations(); - case 3: - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'close', extensionId: name }); - } - }, () => { + const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations")); + const installAction = this.instantiationService.createInstance(InstallRecommendedExtensionAction, id); + const options = [ + localize('install', 'Install'), + recommendationsAction.label, + choiceNever, + choiceClose + ]; + + this.choiceService.choose(Severity.Info, message, options, 3).done(choice => { + switch (choice) { + case 0: /* __GDPR__ "extensionRecommendations:popup" : { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); - }); + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'install', extensionId: name }); + return installAction.run(); + case 1: + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'show', extensionId: name }); + return recommendationsAction.run(); + case 2: importantRecommendationsIgnoreList.push(id); + this.storageService.store( + 'extensionsAssistant/importantRecommendationsIgnore', + JSON.stringify(importantRecommendationsIgnoreList), + StorageScope.GLOBAL + ); + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId: name }); + return this.ignoreExtensionRecommendations(); + case 3: + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'close', extensionId: name }); + } + }, () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); + }); + }); + + const mimeTypesPromise = this.getMimeTypes(uri.fsPath); + TPromise.join([importantTipsPromise, mimeTypesPromise]).then(result => { + + const fileExtensionSuggestionIgnoreList = JSON.parse(this.storageService.get + ('extensionsAssistant/fileExtensionsSuggestionIgnore', StorageScope.GLOBAL, '[]')); + const mimeTypes = result[1]; + let fileExtension = paths.extname(uri.fsPath); + if (fileExtension) { + fileExtension = fileExtension.substr(1); // Strip the dot + } + + if (hasSuggestion || + !fileExtension || + mimeTypes.length !== 1 || + mimeTypes[0] !== MIME_UNKNOWN || + fileExtensionSuggestionIgnoreList.indexOf(fileExtension) > -1 + ) { + return; + } + + const keywords = this.getKeywordsForExtension(fileExtension); + this._galleryService.query({ text: `tag:"__ext_${fileExtension}" ${keywords.map(tag => `tag:"${tag}"`)}` }).then(pager => { + if (!pager || !pager.firstPage || !pager.firstPage.length) { + return; + } + + const message = localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension); + + const searchMarketplaceAction = this.instantiationService.createInstance(ShowLanguageExtensionsAction, fileExtension); + + const options = [ + localize('searchMarketplace', "Search Marketplace"), + choiceNever, + choiceClose + ]; + + this.choiceService.choose(Severity.Info, message, options, 2).done(choice => { + switch (choice) { + case 0: + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'ok', fileExtension: fileExtension }); + searchMarketplaceAction.run(); + break; + case 1: + fileExtensionSuggestionIgnoreList.push(fileExtension); + this.storageService.store( + 'extensionsAssistant/fileExtensionsSuggestionIgnore', + JSON.stringify(fileExtensionSuggestionIgnoreList), + StorageScope.GLOBAL + ); + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'neverShowAgain', fileExtension: fileExtension }); + case 2: + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'close', fileExtension: fileExtension }); + break; + } + }, () => { + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension }); }); + }); }); }); } @@ -395,8 +494,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe const options = [ installAllAction.label, showAction.label, - localize('neverShowAgain', "Don't Show Again"), - localize('close', "Close") + choiceNever, + choiceClose ]; return this.choiceService.choose(Severity.Info, message, options, 3).done(choice => { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index 18f4e4a6d56..178a39a6886 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -28,7 +28,7 @@ import { OpenExtensionsFolderAction, InstallVSIXAction } from 'vs/workbench/part import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { ExtensionEditor } from 'vs/workbench/parts/extensions/browser/extensionEditor'; -import { StatusUpdater, ExtensionsViewlet } from 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; +import { StatusUpdater, ExtensionsViewlet, MaliciousExtensionChecker } from 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import jsonContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); @@ -52,6 +52,7 @@ registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService); const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Running); +workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(ConfigureRecommendedExtensionsCommandsContributor, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Running); workbenchRegistry.registerWorkbenchContribution(BetterMergeDisabled, LifecyclePhase.Running); @@ -222,4 +223,4 @@ CommandsRegistry.registerCommand('_extensions.manage', (accessor: ServicesAccess if (extension.length === 1) { extensionService.open(extension[0]).done(null, errors.onUnexpectedError); } -}); +}); \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts index de679af9945..ac45a445b75 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsUtils.ts @@ -90,7 +90,7 @@ export class KeymapExtensions implements IWorkbenchContribution { this.telemetryService.publicLog('disableOtherKeymaps', telemetryData); if (confirmed) { return TPromise.join(oldKeymaps.map(keymap => { - return this.extensionEnablementService.setEnablement(keymap.local.identifier, EnablementState.Disabled); + return this.extensionEnablementService.setEnablement(keymap.local, EnablementState.Disabled); })); } return undefined; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index ac4d9aafbc7..59a354f9f39 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -51,6 +51,9 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService, ContextKeyExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { getGalleryExtensionIdFromLocal, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { ILogService } from 'vs/platform/log/common/log'; +import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; interface SearchInputEvent extends Event { target: HTMLInputElement; @@ -452,3 +455,49 @@ export class StatusUpdater implements IWorkbenchContribution { dispose(this.badgeHandle); } } + +export class MaliciousExtensionChecker implements IWorkbenchContribution { + + private disposables: IDisposable[]; + + constructor( + @IExtensionManagementService private extensionsManagementService: IExtensionManagementService, + @IInstantiationService private instantiationService: IInstantiationService, + @ILogService private logService: ILogService, + @IMessageService private messageService: IMessageService + ) { + this.loopCheckForMaliciousExtensions(); + } + + private loopCheckForMaliciousExtensions(): void { + this.checkForMaliciousExtensions() + .then(() => TPromise.timeout(1000 * 60 * 5)) // every five minutes + .then(() => this.loopCheckForMaliciousExtensions()); + } + + private checkForMaliciousExtensions(): TPromise { + return this.extensionsManagementService.getExtensionsReport().then(report => { + const maliciousSet = getMaliciousExtensionsSet(report); + + return this.extensionsManagementService.getInstalled(LocalExtensionType.User).then(installed => { + const maliciousExtensions = installed + .filter(e => maliciousSet.has(getGalleryExtensionIdFromLocal(e))); + + if (maliciousExtensions.length) { + return TPromise.join(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e, true).then(() => { + this.messageService.show(Severity.Warning, { + message: localize('malicious warning', "We have uninstalled '{0}' which was reported to be malicious.", getGalleryExtensionIdFromLocal(e)), + actions: [this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('reloadNow', "Reload Now"))] + }); + }))); + } else { + return TPromise.as(null); + } + }); + }, err => this.logService.error(err)); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts index 8f6cb11fba0..69e6766f25c 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts @@ -35,8 +35,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; -import { WorkbenchPagedList, IListService } from 'vs/platform/list/browser/listService'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { WorkbenchPagedList } from 'vs/platform/list/browser/listService'; export class ExtensionsListView extends ViewsViewletPanel { @@ -52,7 +51,6 @@ export class ExtensionsListView extends ViewsViewletPanel { @IKeybindingService keybindingService: IKeybindingService, @IContextMenuService contextMenuService: IContextMenuService, @IInstantiationService protected instantiationService: IInstantiationService, - @IListService private listService: IListService, @IThemeService private themeService: IThemeService, @IExtensionService private extensionService: IExtensionService, @IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -60,8 +58,7 @@ export class ExtensionsListView extends ViewsViewletPanel { @IEditorGroupService private editorInputService: IEditorGroupService, @IExtensionTipsService private tipsService: IExtensionTipsService, @IModeService private modeService: IModeService, - @ITelemetryService private telemetryService: ITelemetryService, - @IContextKeyService private contextKeyService: IContextKeyService + @ITelemetryService private telemetryService: ITelemetryService ) { super({ ...(options as IViewOptions), ariaHeaderLabel: options.name }, keybindingService, contextMenuService); } @@ -80,10 +77,10 @@ export class ExtensionsListView extends ViewsViewletPanel { this.messageBox = append(container, $('.message')); const delegate = new Delegate(); const renderer = this.instantiationService.createInstance(Renderer); - this.list = new WorkbenchPagedList(this.extensionsList, delegate, [renderer], { + this.list = this.instantiationService.createInstance(WorkbenchPagedList, this.extensionsList, delegate, [renderer], { ariaLabel: localize('extensions', "Extensions"), keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); chain(this.list.onSelectionChange) .map(e => e.elements[0]) @@ -237,7 +234,7 @@ export class ExtensionsListView extends ViewsViewletPanel { const languageTag = languageName ? ` tag:"${languageName}"` : ''; // Construct a rich query - return `tag:"__ext_${ext}"${keywords.map(tag => ` tag:${tag}`)}${languageTag}`; + return `tag:"__ext_${ext}" tag:"__ext_.${ext}" ${keywords.map(tag => `tag:"${tag}"`).join(' ')}${languageTag} tag:"${ext}"`; }); if (names.length) { diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css b/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css index bad1b92e994..8a9a44e97df 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.runtime-extensions-editor .monaco-list .monaco-list-rows > .monaco-list-row:nth-child(even):not(:hover):not(.focused) { +.runtime-extensions-editor .monaco-list .monaco-list-rows > .monaco-list-row.odd:not(:hover):not(.focused) { background-color: rgba(130, 130, 130, 0.08); } diff --git a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts index 19134fb1b09..bc300591ee4 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -20,11 +20,10 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/parts/extensions/common/extensions'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IExtensionService, IExtensionDescription, IExtensionsStatus, IExtensionHostProfile } from 'vs/platform/extensions/common/extensions'; import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; -import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchList } from 'vs/platform/list/browser/listService'; import { append, $, addClass, toggleClass } from 'vs/base/browser/dom'; import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; @@ -103,8 +102,6 @@ export class RuntimeExtensionsEditor extends BaseEditor { @IThemeService themeService: IThemeService, @IExtensionsWorkbenchService private readonly _extensionsWorkbenchService: IExtensionsWorkbenchService, @IExtensionService private readonly _extensionService: IExtensionService, - @IListService private readonly _listService: IListService, - @IContextKeyService private readonly _contextKeyService: IContextKeyService, @IMessageService private readonly _messageService: IMessageService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @@ -294,6 +291,8 @@ export class RuntimeExtensionsEditor extends BaseEditor { data.elementDisposables = dispose(data.elementDisposables); + toggleClass(data.root, 'odd', index % 2 === 1); + data.name.textContent = element.marketplaceInfo ? element.marketplaceInfo.displayName : element.description.displayName; const activationTimes = element.status.activationTimes; @@ -363,9 +362,9 @@ export class RuntimeExtensionsEditor extends BaseEditor { } }; - this._list = new WorkbenchList(container, delegate, [renderer], { + this._list = this._instantiationService.createInstance(WorkbenchList, container, delegate, [renderer], { multipleSelectionSupport: false - }, this._contextKeyService, this._listService, this.themeService); + }); this._list.splice(0, this._list.length, this._elements); diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 10a5d3b69ed..23944c6caad 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -22,7 +22,7 @@ import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, IExtensionManifest, InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { getGalleryExtensionIdFromLocal, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; +import { getGalleryExtensionIdFromLocal, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWindowService } from 'vs/platform/windows/common/windows'; @@ -35,9 +35,10 @@ import { IURLService } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; import product from 'vs/platform/node/product'; import { ILogService } from 'vs/platform/log/common/log'; +import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress'; -interface IExtensionStateProvider { - (extension: Extension): ExtensionState; +interface IExtensionStateProvider { + (extension: Extension): T; } class Extension implements IExtension { @@ -46,7 +47,7 @@ class Extension implements IExtension { constructor( private galleryService: IExtensionGalleryService, - private stateProvider: IExtensionStateProvider, + private stateProvider: IExtensionStateProvider, public local: ILocalExtension, public gallery: IGalleryExtension, private telemetryService: ITelemetryService @@ -152,6 +153,8 @@ class Extension implements IExtension { return this.stateProvider(this); } + public isMalicious: boolean = false; + get installCount(): number { return this.gallery ? this.gallery.installCount : null; } @@ -320,7 +323,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { private static readonly SyncPeriod = 1000 * 60 * 60 * 12; // 12 hours _serviceBrand: any; - private stateProvider: IExtensionStateProvider; + private stateProvider: IExtensionStateProvider; private installing: IActiveExtension[] = []; private uninstalling: IActiveExtension[] = []; private installed: Extension[] = []; @@ -345,7 +348,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { @IURLService urlService: IURLService, @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, @IWindowService private windowService: IWindowService, - @ILogService private logService: ILogService + @ILogService private logService: ILogService, + @IProgressService2 private progressService: IProgressService2 ) { this.stateProvider = ext => this.getExtensionState(ext); @@ -397,15 +401,19 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } queryGallery(options: IQueryOptions = {}): TPromise> { - return this.galleryService.query(options) - .then(result => mapPager(result, gallery => this.fromGallery(gallery))) - .then(null, err => { - if (/No extension gallery service configured/.test(err.message)) { - return TPromise.as(singlePagePager([])); - } + return this.extensionService.getExtensionsReport().then(report => { + const maliciousSet = getMaliciousExtensionsSet(report); - return TPromise.wrapError>(err); - }); + return this.galleryService.query(options) + .then(result => mapPager(result, gallery => this.fromGallery(gallery, maliciousSet))) + .then(null, err => { + if (/No extension gallery service configured/.test(err.message)) { + return TPromise.as(singlePagePager([])); + } + + return TPromise.wrapError>(err); + }); + }); } loadDependencies(extension: IExtension): TPromise { @@ -413,38 +421,47 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return TPromise.wrap(null); } - return this.galleryService.loadAllDependencies((extension).dependencies.map(id => { id })) - .then(galleryExtensions => galleryExtensions.map(galleryExtension => this.fromGallery(galleryExtension))) - .then(extensions => [...this.local, ...extensions]) - .then(extensions => { - const map = new Map(); - for (const extension of extensions) { - map.set(extension.id, extension); - } - return new ExtensionDependencies(extension, extension.id, map); - }); + return this.extensionService.getExtensionsReport().then(report => { + const maliciousSet = getMaliciousExtensionsSet(report); + + return this.galleryService.loadAllDependencies((extension).dependencies.map(id => { id })) + .then(galleryExtensions => galleryExtensions.map(galleryExtension => this.fromGallery(galleryExtension, maliciousSet))) + .then(extensions => [...this.local, ...extensions]) + .then(extensions => { + const map = new Map(); + for (const extension of extensions) { + map.set(extension.id, extension); + } + return new ExtensionDependencies(extension, extension.id, map); + }); + }); } open(extension: IExtension, sideByside: boolean = false): TPromise { return this.editorService.openEditor(this.instantiationService.createInstance(ExtensionsInput, extension), null, sideByside); } - private fromGallery(gallery: IGalleryExtension): Extension { - const installed = this.getInstalledExtensionMatchingGallery(gallery); + private fromGallery(gallery: IGalleryExtension, maliciousExtensionSet: Set): Extension { + let result = this.getInstalledExtensionMatchingGallery(gallery); - if (installed) { + if (result) { // Loading the compatible version only there is an engine property // Otherwise falling back to old way so that we will not make many roundtrips if (gallery.properties.engine) { this.galleryService.loadCompatibleVersion(gallery) - .then(compatible => compatible ? this.syncLocalWithGalleryExtension(installed, compatible) : null); + .then(compatible => compatible ? this.syncLocalWithGalleryExtension(result, compatible) : null); } else { - this.syncLocalWithGalleryExtension(installed, gallery); + this.syncLocalWithGalleryExtension(result, gallery); } - return installed; + } else { + result = new Extension(this.galleryService, this.stateProvider, null, gallery, this.telemetryService); } - return new Extension(this.galleryService, this.stateProvider, null, gallery, this.telemetryService); + if (maliciousExtensionSet.has(result.id)) { + result.isMalicious = true; + } + + return result; } private getInstalledExtensionMatchingGallery(gallery: IGalleryExtension): Extension { @@ -531,18 +548,30 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return false; } + if (extension.isMalicious) { + return false; + } + return !!(extension as Extension).gallery; } install(extension: string | IExtension): TPromise { if (typeof extension === 'string') { - return this.extensionService.install(extension); + return this.progressService.withProgress({ + location: ProgressLocation.Extensions, + title: nls.localize('installingVSIXExtension', 'Installing extension from VSIX...'), + tooltip: `${extension}` + }, () => this.extensionService.install(extension)); } if (!(extension instanceof Extension)) { return undefined; } + if (extension.isMalicious) { + return TPromise.wrapError(new Error(nls.localize('malicious', "This extension is reported to be malicious."))); + } + const ext = extension as Extension; const gallery = ext.gallery; @@ -550,7 +579,11 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return TPromise.wrapError(new Error('Missing gallery')); } - return this.extensionService.installFromGallery(gallery); + return this.progressService.withProgress({ + location: ProgressLocation.Extensions, + title: nls.localize('installingMarketPlaceExtension', 'Installing extension from Market place....'), + tooltip: `${extension.id}` + }, () => this.extensionService.installFromGallery(gallery)); } setEnablement(extension: IExtension, enablementState: EnablementState): TPromise { @@ -591,8 +624,11 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } this.logService.info(`Requested uninstalling the extension ${extension.id} from window ${this.windowService.getCurrentWindowId()}`); - return this.extensionService.uninstall(local); - + return this.progressService.withProgress({ + location: ProgressLocation.Extensions, + title: nls.localize('uninstallingExtension', 'Uninstalling extension....'), + tooltip: `${local.identifier.id}` + }, () => this.extensionService.uninstall(local)); } private promptAndSetEnablement(extension: IExtension, enablementState: EnablementState, enable: boolean): TPromise { @@ -709,7 +745,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } private doSetEnablement(extension: IExtension, enablementState: EnablementState): TPromise { - return this.extensionEnablementService.setEnablement(extension, enablementState); + return this.extensionEnablementService.setEnablement(extension.local, enablementState); } get allowedBadgeProviders(): string[] { @@ -743,25 +779,25 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { private onDidInstallExtension(event: DidInstallExtensionEvent): void { const { local, zipPath, error, gallery } = event; - const installing = gallery ? this.installing.filter(e => areSameExtensions(e.extension, gallery.identifier))[0] : null; - const extension: Extension = installing ? installing.extension : zipPath ? new Extension(this.galleryService, this.stateProvider, null, null, this.telemetryService) : null; + const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e.extension, gallery.identifier))[0] : null; + const extension: Extension = installingExtension ? installingExtension.extension : zipPath ? new Extension(this.galleryService, this.stateProvider, null, null, this.telemetryService) : null; if (extension) { - this.installing = installing ? this.installing.filter(e => e !== installing) : this.installing; + this.installing = installingExtension ? this.installing.filter(e => e !== installingExtension) : this.installing; if (error) { if (extension.gallery) { // Updating extension can be only a gallery extension const installed = this.installed.filter(e => e.id === extension.id)[0]; - if (installed && installing) { - installing.operation = Operation.Updating; + if (installed && installingExtension) { + installingExtension.operation = Operation.Updating; } } } else { extension.local = local; const installed = this.installed.filter(e => e.id === extension.id)[0]; if (installed) { - if (installing) { - installing.operation = Operation.Updating; + if (installingExtension) { + installingExtension.operation = Operation.Updating; } installed.local = local; } else { @@ -770,7 +806,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } if (extension.gallery) { // Report telemetry only for gallery extensions - this.reportTelemetry(installing, error); + this.reportTelemetry(installingExtension, error); } } this._onChange.fire(); diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts index 0e697f0d9ef..312c16c9b5c 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsActions.test.ts @@ -75,6 +75,7 @@ suite('ExtensionsActions Test', () => { setup(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []); + instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage()); instantiationService.stub(IExtensionService, { getExtensions: () => TPromise.wrap([]) }); (instantiationService.get(IExtensionEnablementService)).reset(); @@ -92,78 +93,79 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test Install action when state is installed', (done) => { + test('Test Install action when state is installed', () => { const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.InstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(() => { - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier }))); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - assert.ok(!testObject.enabled); - assert.equal('Install', testObject.label); - assert.equal('extension-action prominent install', testObject.class); - done(); + return workbenchService.queryLocal() + .then(() => { + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier }))); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + assert.ok(!testObject.enabled); + assert.equal('Install', testObject.label); + assert.equal('extension-action prominent install', testObject.class); + }); }); - }); }); - test('Test Install action when state is installing', (done) => { + test('Test Install action when state is installing', () => { const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.InstallAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - assert.equal('Installing', testObject.label); - assert.equal('extension-action install installing', testObject.class); - done(); - }); + assert.ok(!testObject.enabled); + assert.equal('Installing', testObject.label); + assert.equal('extension-action install installing', testObject.class); + }); }); - test('Test Install action when state is uninstalled', (done) => { + test('Test Install action when state is uninstalled', () => { const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.InstallAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - assert.ok(testObject.enabled); - assert.equal('Install', testObject.label); - done(); - }); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + assert.ok(testObject.enabled); + assert.equal('Install', testObject.label); + }); }); - test('Test Install action when extension is system action', (done) => { + test('Test Install action when extension is system action', () => { const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.InstallAction); const local = aLocalExtension('a', {}, { type: LocalExtensionType.System }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - uninstallEvent.fire(local.identifier); - didUninstallEvent.fire({ identifier: local.identifier }); - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + uninstallEvent.fire(local.identifier); + didUninstallEvent.fire({ identifier: local.identifier }); + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test Install action when extension doesnot has gallery', (done) => { + test('Test Install action when extension doesnot has gallery', () => { const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.InstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - uninstallEvent.fire(local.identifier); - didUninstallEvent.fire({ identifier: local.identifier }); - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + uninstallEvent.fire(local.identifier); + didUninstallEvent.fire({ identifier: local.identifier }); + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); }); test('Uninstall action is disabled when there is no extension', () => { @@ -172,65 +174,65 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test Uninstall action when state is uninstalling', (done) => { + test('Test Uninstall action when state is uninstalling', () => { const testObject: ExtensionsActions.UninstallAction = instantiationService.createInstance(ExtensionsActions.UninstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - assert.equal('Uninstalling', testObject.label); - assert.equal('extension-action uninstall uninstalling', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + assert.ok(!testObject.enabled); + assert.equal('Uninstalling', testObject.label); + assert.equal('extension-action uninstall uninstalling', testObject.class); + }); }); - test('Test Uninstall action when state is installed and is user extension', (done) => { + test('Test Uninstall action when state is installed and is user extension', () => { const testObject: ExtensionsActions.UninstallAction = instantiationService.createInstance(ExtensionsActions.UninstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - assert.equal('Uninstall', testObject.label); - assert.equal('extension-action uninstall', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + assert.equal('Uninstall', testObject.label); + assert.equal('extension-action uninstall', testObject.class); + }); }); - test('Test Uninstall action when state is installed and is system extension', (done) => { + test('Test Uninstall action when state is installed and is system extension', () => { const testObject: ExtensionsActions.UninstallAction = instantiationService.createInstance(ExtensionsActions.UninstallAction); const local = aLocalExtension('a', {}, { type: LocalExtensionType.System }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - assert.equal('Uninstall', testObject.label); - assert.equal('extension-action uninstall', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + assert.equal('Uninstall', testObject.label); + assert.equal('extension-action uninstall', testObject.class); + }); }); - test('Test Uninstall action after extension is installed', (done) => { + test('Test Uninstall action after extension is installed', () => { const testObject: ExtensionsActions.UninstallAction = instantiationService.createInstance(ExtensionsActions.UninstallAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(paged => { - testObject.extension = paged.firstPage[0]; + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(paged => { + testObject.extension = paged.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - assert.ok(testObject.enabled); - assert.equal('Uninstall', testObject.label); - assert.equal('extension-action uninstall', testObject.class); - done(); - }); + assert.ok(testObject.enabled); + assert.equal('Uninstall', testObject.label); + assert.equal('extension-action uninstall', testObject.class); + }); }); test('Test CombinedInstallAction when there is no extension', () => { @@ -240,77 +242,77 @@ suite('ExtensionsActions Test', () => { assert.equal('extension-action prominent install no-extension', testObject.class); }); - test('Test CombinedInstallAction when extension is system extension', (done) => { + test('Test CombinedInstallAction when extension is system extension', () => { const testObject: ExtensionsActions.CombinedInstallAction = instantiationService.createInstance(ExtensionsActions.CombinedInstallAction); const local = aLocalExtension('a', {}, { type: LocalExtensionType.System }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - assert.equal('extension-action prominent install no-extension', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + assert.equal('extension-action prominent install no-extension', testObject.class); + }); }); - test('Test CombinedInstallAction when installAction is enabled', (done) => { + test('Test CombinedInstallAction when installAction is enabled', () => { const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const testObject: ExtensionsActions.CombinedInstallAction = instantiationService.createInstance(ExtensionsActions.CombinedInstallAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - assert.ok(testObject.enabled); - assert.equal('Install', testObject.label); - assert.equal('extension-action prominent install', testObject.class); - done(); - }); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + assert.ok(testObject.enabled); + assert.equal('Install', testObject.label); + assert.equal('extension-action prominent install', testObject.class); + }); }); - test('Test CombinedInstallAction when unInstallAction is enabled', (done) => { + test('Test CombinedInstallAction when unInstallAction is enabled', () => { const testObject: ExtensionsActions.CombinedInstallAction = instantiationService.createInstance(ExtensionsActions.CombinedInstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - assert.equal('Uninstall', testObject.label); - assert.equal('extension-action uninstall', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + assert.equal('Uninstall', testObject.label); + assert.equal('extension-action uninstall', testObject.class); + }); }); - test('Test CombinedInstallAction when state is installing', (done) => { + test('Test CombinedInstallAction when state is installing', () => { const testObject: ExtensionsActions.CombinedInstallAction = instantiationService.createInstance(ExtensionsActions.CombinedInstallAction); const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - assert.equal('Installing', testObject.label); - assert.equal('extension-action install installing', testObject.class); - done(); - }); + assert.ok(!testObject.enabled); + assert.equal('Installing', testObject.label); + assert.equal('extension-action install installing', testObject.class); + }); }); - test('Test CombinedInstallAction when state is uninstalling', (done) => { + test('Test CombinedInstallAction when state is uninstalling', () => { const testObject: ExtensionsActions.CombinedInstallAction = instantiationService.createInstance(ExtensionsActions.CombinedInstallAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - assert.equal('Uninstalling', testObject.label); - assert.equal('extension-action uninstall uninstalling', testObject.class); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + assert.ok(!testObject.enabled); + assert.equal('Uninstalling', testObject.label); + assert.equal('extension-action uninstall uninstalling', testObject.class); + }); }); test('Test UpdateAction when there is no extension', () => { @@ -319,77 +321,75 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test UpdateAction when extension is uninstalled', (done) => { + test('Test UpdateAction when extension is uninstalled', () => { const testObject: ExtensionsActions.UpdateAction = instantiationService.createInstance(ExtensionsActions.UpdateAction); const gallery = aGalleryExtension('a', { version: '1.0.0' }); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test UpdateAction when extension is installed and not outdated', (done) => { + test('Test UpdateAction when extension is installed and not outdated', () => { const testObject: ExtensionsActions.UpdateAction = instantiationService.createInstance(ExtensionsActions.UpdateAction); const local = aLocalExtension('a', { version: '1.0.0' }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: local.manifest.version }))); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(extensions => { - assert.ok(!testObject.enabled); - done(); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: local.manifest.version }))); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(extensions => assert.ok(!testObject.enabled)); }); - }); }); - test('Test UpdateAction when extension is installed outdated and system extension', (done) => { + test('Test UpdateAction when extension is installed outdated and system extension', () => { const testObject: ExtensionsActions.UpdateAction = instantiationService.createInstance(ExtensionsActions.UpdateAction); const local = aLocalExtension('a', { version: '1.0.0' }, { type: LocalExtensionType.System }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }))); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(extensions => { - assert.ok(!testObject.enabled); - done(); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }))); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(extensions => assert.ok(!testObject.enabled)); }); - }); }); - test('Test UpdateAction when extension is installed outdated and user extension', (done) => { + test('Test UpdateAction when extension is installed outdated and user extension', () => { const testObject: ExtensionsActions.UpdateAction = instantiationService.createInstance(ExtensionsActions.UpdateAction); const local = aLocalExtension('a', { version: '1.0.0' }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }))); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(extensions => { - assert.ok(testObject.enabled); - done(); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }))); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(extensions => assert.ok(testObject.enabled)); }); - }); }); - test('Test UpdateAction when extension is installing and outdated and user extension', (done) => { + test('Test UpdateAction when extension is installing and outdated and user extension', () => { const testObject: ExtensionsActions.UpdateAction = instantiationService.createInstance(ExtensionsActions.UpdateAction); const local = aLocalExtension('a', { version: '1.0.0' }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(extensions => { - installEvent.fire({ identifier: local.identifier, gallery }); - assert.ok(!testObject.enabled); - done(); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.1' }); + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(extensions => { + installEvent.fire({ identifier: local.identifier, gallery }); + assert.ok(!testObject.enabled); + }); }); - }); }); test('Test ManageExtensionAction when there is no extension', () => { @@ -398,101 +398,95 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test ManageExtensionAction when extension is installed', (done) => { + test('Test ManageExtensionAction when extension is installed', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - assert.equal('extension-action manage', testObject.class); - assert.equal('', testObject.tooltip); - - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + assert.equal('extension-action manage', testObject.class); + assert.equal('', testObject.tooltip); + }); }); - test('Test ManageExtensionAction when extension is uninstalled', (done) => { + test('Test ManageExtensionAction when extension is uninstalled', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; - assert.ok(!testObject.enabled); - assert.equal('extension-action manage hide', testObject.class); - assert.equal('', testObject.tooltip); - - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; + assert.ok(!testObject.enabled); + assert.equal('extension-action manage hide', testObject.class); + assert.equal('', testObject.tooltip); + }); }); - test('Test ManageExtensionAction when extension is installing', (done) => { + test('Test ManageExtensionAction when extension is installing', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - assert.equal('extension-action manage hide', testObject.class); - assert.equal('', testObject.tooltip); - - done(); - }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + assert.ok(!testObject.enabled); + assert.equal('extension-action manage hide', testObject.class); + assert.equal('', testObject.tooltip); + }); }); - test('Test ManageExtensionAction when extension is queried from gallery and installed', (done) => { + test('Test ManageExtensionAction when extension is queried from gallery and installed', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - assert.ok(testObject.enabled); - assert.equal('extension-action manage', testObject.class); - assert.equal('', testObject.tooltip); - - done(); - }); + assert.ok(testObject.enabled); + assert.equal('extension-action manage', testObject.class); + assert.equal('', testObject.tooltip); + }); }); - test('Test ManageExtensionAction when extension is system extension', (done) => { + test('Test ManageExtensionAction when extension is system extension', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const local = aLocalExtension('a', {}, { type: LocalExtensionType.System }); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - assert.equal('extension-action manage hide', testObject.class); - assert.equal('', testObject.tooltip); - - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + assert.equal('extension-action manage hide', testObject.class); + assert.equal('', testObject.tooltip); + }); }); - test('Test ManageExtensionAction when extension is uninstalling', (done) => { + test('Test ManageExtensionAction when extension is uninstalling', () => { const testObject: ExtensionsActions.ManageExtensionAction = instantiationService.createInstance(ExtensionsActions.ManageExtensionAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - assert.equal('extension-action manage', testObject.class); - assert.equal('Uninstalling', testObject.tooltip); - - done(); - }); + assert.ok(!testObject.enabled); + assert.equal('extension-action manage', testObject.class); + assert.equal('Uninstalling', testObject.tooltip); + }); }); test('Test EnableForWorkspaceAction when there is no extension', () => { @@ -501,20 +495,7 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test EnableForWorkspaceAction when there extension is not disabled', (done) => { - const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); - const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); - }); - - test('Test EnableForWorkspaceAction when the extension is disabled globally', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); + test('Test EnableForWorkspaceAction when there extension is not disabled', () => { const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); @@ -522,34 +503,53 @@ suite('ExtensionsActions Test', () => { return instantiationService.get(IExtensionsWorkbenchService).queryLocal() .then(extensions => { testObject.extension = extensions[0]; - assert.ok(testObject.enabled); + assert.ok(!testObject.enabled); + }); + }); + + test('Test EnableForWorkspaceAction when the extension is disabled globally', () => { + const local = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); }); test('Test EnableForWorkspaceAction when extension is disabled for workspace', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled) + .then(() => { + const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - return instantiationService.get(IExtensionsWorkbenchService).queryLocal() - .then(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); }); test('Test EnableForWorkspaceAction when the extension is disabled globally and workspace', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled)) + .then(() => { + const testObject: ExtensionsActions.EnableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.EnableForWorkspaceAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - return instantiationService.get(IExtensionsWorkbenchService).queryLocal() - .then(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); }); @@ -559,56 +559,62 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test EnableGloballyAction when the extension is not disabled', (done) => { - const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + test('Test EnableGloballyAction when the extension is not disabled', () => { const local = aLocalExtension('a'); + const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test EnableGloballyAction when the extension is disabled for workspace', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + test('Test EnableGloballyAction when the extension is disabled for workspace', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled) + .then(() => { + const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); + }); }); - test('Test EnableGloballyAction when the extension is disabled globally', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + test('Test EnableGloballyAction when the extension is disabled globally', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); + }); }); - test('Test EnableGloballyAction when the extension is disabled in both', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + test('Test EnableGloballyAction when the extension is disabled in both', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled)) + .then(() => { + const testObject: ExtensionsActions.EnableGloballyAction = instantiationService.createInstance(ExtensionsActions.EnableGloballyAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); + }); }); test('Test EnableAction when there is no extension', () => { @@ -617,82 +623,85 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test EnableAction when extension is installed and enabled', (done) => { + test('Test EnableAction when extension is installed and enabled', () => { const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test EnableAction when extension is installed and disabled globally', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); + test('Test EnableAction when extension is installed and disabled globally', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); + }); }); - test('Test EnableAction when extension is installed and disabled for workspace', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); + test('Test EnableAction when extension is installed and disabled for workspace', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled) + .then(() => { + const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); + }); }); - test('Test EnableAction when extension is uninstalled', (done) => { + test('Test EnableAction when extension is uninstalled', () => { const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test EnableAction when extension is installing', (done) => { + test('Test EnableAction when extension is installing', () => { const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - - done(); - }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + assert.ok(!testObject.enabled); + }); }); - test('Test EnableAction when extension is uninstalling', (done) => { + test('Test EnableAction when extension is uninstalling', () => { const testObject: ExtensionsActions.EnableAction = instantiationService.createInstance(ExtensionsActions.EnableAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + assert.ok(!testObject.enabled); + }); }); test('Test DisableForWorkspaceAction when there is no extension', () => { @@ -701,42 +710,46 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test DisableForWorkspaceAction when the extension is disabled globally', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.DisableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.DisableForWorkspaceAction, 'id'); + test('Test DisableForWorkspaceAction when the extension is disabled globally', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.DisableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.DisableForWorkspaceAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableForWorkspaceAction when the extension is disabled workspace', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.DisableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.DisableForWorkspaceAction, 'id'); + test('Test DisableForWorkspaceAction when the extension is disabled workspace', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.DisableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.DisableForWorkspaceAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableForWorkspaceAction when extension is enabled', (done) => { + test('Test DisableForWorkspaceAction when extension is enabled', () => { const testObject: ExtensionsActions.DisableForWorkspaceAction = instantiationService.createInstance(ExtensionsActions.DisableForWorkspaceAction, 'id'); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); test('Test DisableGloballyAction when there is no extension', () => { @@ -745,42 +758,46 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test DisableGloballyAction when the extension is disabled globally', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.DisableGloballyAction = instantiationService.createInstance(ExtensionsActions.DisableGloballyAction, 'id'); + test('Test DisableGloballyAction when the extension is disabled globally', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.DisableGloballyAction = instantiationService.createInstance(ExtensionsActions.DisableGloballyAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableGloballyAction when the extension is disabled for workspace', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.DisableGloballyAction = instantiationService.createInstance(ExtensionsActions.DisableGloballyAction, 'id'); + test('Test DisableGloballyAction when the extension is disabled for workspace', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled) + .then(() => { + const testObject: ExtensionsActions.DisableGloballyAction = instantiationService.createInstance(ExtensionsActions.DisableGloballyAction, 'id'); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableGloballyAction when the extension is enabled', (done) => { + test('Test DisableGloballyAction when the extension is enabled', () => { const testObject: ExtensionsActions.DisableGloballyAction = instantiationService.createInstance(ExtensionsActions.DisableGloballyAction, 'id'); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); test('Test DisableAction when there is no extension', () => { @@ -789,82 +806,85 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test DisableAction when extension is installed and enabled', (done) => { + test('Test DisableAction when extension is installed and enabled', () => { const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(testObject.enabled); + }); }); - test('Test DisableAction when extension is installed and disabled globally', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); + test('Test DisableAction when extension is installed and disabled globally', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableAction when extension is installed and disabled for workspace', (done) => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); + test('Test DisableAction when extension is installed and disabled for workspace', () => { const local = aLocalExtension('a'); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.WorkspaceDisabled) + .then(() => { + const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + assert.ok(!testObject.enabled); + }); + }); }); - test('Test DisableAction when extension is uninstalled', (done) => { + test('Test DisableAction when extension is uninstalled', () => { const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; + assert.ok(!testObject.enabled); + }); }); - test('Test DisableAction when extension is installing', (done) => { + test('Test DisableAction when extension is installing', () => { const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done(page => { - testObject.extension = page.firstPage[0]; + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then(page => { + testObject.extension = page.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - - done(); - }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + assert.ok(!testObject.enabled); + }); }); - test('Test DisableAction when extension is uninstalling', (done) => { + test('Test DisableAction when extension is uninstalling', () => { const testObject: ExtensionsActions.DisableAction = instantiationService.createInstance(ExtensionsActions.DisableAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + assert.ok(!testObject.enabled); + }); }); test('Test UpdateAllAction when no installed extensions', () => { @@ -873,60 +893,59 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test UpdateAllAction when installed extensions are not outdated', (done) => { + test('Test UpdateAllAction when installed extensions are not outdated', () => { const testObject: ExtensionsActions.UpdateAllAction = instantiationService.createInstance(ExtensionsActions.UpdateAllAction, 'id', 'label'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a'), aLocalExtension('b')]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => assert.ok(!testObject.enabled)); }); - test('Test UpdateAllAction when some installed extensions are outdated', (done) => { + test('Test UpdateAllAction when some installed extensions are outdated', () => { const testObject: ExtensionsActions.UpdateAllAction = instantiationService.createInstance(ExtensionsActions.UpdateAllAction, 'id', 'label'); const local = [aLocalExtension('a', { version: '1.0.1' }), aLocalExtension('b', { version: '1.0.1' }), aLocalExtension('c', { version: '1.0.1' })]; const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', local); - workbenchService.queryLocal().done(() => { - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local[0].identifier, version: '1.0.2' }), aGalleryExtension('b', { identifier: local[1].identifier, version: '1.0.2' }), aGalleryExtension('c', local[2].manifest))); - workbenchService.queryGallery().done(() => { - assert.ok(testObject.enabled); - done(); + return workbenchService.queryLocal() + .then(() => { + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', { identifier: local[0].identifier, version: '1.0.2' }), aGalleryExtension('b', { identifier: local[1].identifier, version: '1.0.2' }), aGalleryExtension('c', local[2].manifest))); + return workbenchService.queryGallery() + .then(() => assert.ok(testObject.enabled)); }); - }); }); - test('Test UpdateAllAction when some installed extensions are outdated and some outdated are being installed', (done) => { + test('Test UpdateAllAction when some installed extensions are outdated and some outdated are being installed', () => { const testObject: ExtensionsActions.UpdateAllAction = instantiationService.createInstance(ExtensionsActions.UpdateAllAction, 'id', 'label'); const local = [aLocalExtension('a', { version: '1.0.1' }), aLocalExtension('b', { version: '1.0.1' }), aLocalExtension('c', { version: '1.0.1' })]; const gallery = [aGalleryExtension('a', { identifier: local[0].identifier, version: '1.0.2' }), aGalleryExtension('b', { identifier: local[1].identifier, version: '1.0.2' }), aGalleryExtension('c', local[2].manifest)]; const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', local); - workbenchService.queryLocal().done(() => { - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...gallery)); - workbenchService.queryGallery().done(() => { - installEvent.fire({ identifier: local[0].identifier, gallery: gallery[0] }); - assert.ok(testObject.enabled); - done(); + return workbenchService.queryLocal() + .then(() => { + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...gallery)); + return workbenchService.queryGallery() + .then(() => { + installEvent.fire({ identifier: local[0].identifier, gallery: gallery[0] }); + assert.ok(testObject.enabled); + }); }); - }); }); - test('Test UpdateAllAction when some installed extensions are outdated and all outdated are being installed', (done) => { + test('Test UpdateAllAction when some installed extensions are outdated and all outdated are being installed', () => { const testObject: ExtensionsActions.UpdateAllAction = instantiationService.createInstance(ExtensionsActions.UpdateAllAction, 'id', 'label'); const local = [aLocalExtension('a', { version: '1.0.1' }), aLocalExtension('b', { version: '1.0.1' }), aLocalExtension('c', { version: '1.0.1' })]; const gallery = [aGalleryExtension('a', { identifier: local[0].identifier, version: '1.0.2' }), aGalleryExtension('b', { identifier: local[1].identifier, version: '1.0.2' }), aGalleryExtension('c', local[2].manifest)]; const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', local); - workbenchService.queryLocal().done(() => { - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...gallery)); - workbenchService.queryGallery().done(() => { - installEvent.fire({ identifier: local[0].identifier, gallery: gallery[0] }); - installEvent.fire({ identifier: local[1].identifier, gallery: gallery[1] }); - assert.ok(!testObject.enabled); - done(); + return workbenchService.queryLocal() + .then(() => { + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...gallery)); + return workbenchService.queryGallery() + .then(() => { + installEvent.fire({ identifier: local[0].identifier, gallery: gallery[0] }); + installEvent.fire({ identifier: local[1].identifier, gallery: gallery[1] }); + assert.ok(!testObject.enabled); + }); }); - }); }); test('Test ReloadAction when there is no extension', () => { @@ -935,233 +954,241 @@ suite('ExtensionsActions Test', () => { assert.ok(!testObject.enabled); }); - test('Test ReloadAction when extension state is installing', (done) => { + test('Test ReloadAction when extension state is installing', () => { const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const workbenchService = instantiationService.get(IExtensionsWorkbenchService); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - workbenchService.queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); + return workbenchService.queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + installEvent.fire({ identifier: gallery.identifier, gallery }); - assert.ok(!testObject.enabled); - done(); - }); + assert.ok(!testObject.enabled); + }); }); - test('Test ReloadAction when extension state is uninstalling', (done) => { + test('Test ReloadAction when extension state is uninstalling', () => { const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + assert.ok(!testObject.enabled); + }); }); - test('Test ReloadAction when extension is newly installed', (done) => { + test('Test ReloadAction when extension is newly installed', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - assert.ok(testObject.enabled); - assert.equal('Reload to activate', testObject.tooltip); - assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); - done(); - }); + assert.ok(testObject.enabled); + assert.equal('Reload to activate', testObject.tooltip); + assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); + }); }); - test('Test ReloadAction when extension is installed and uninstalled', (done) => { + test('Test ReloadAction when extension is installed and uninstalled', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const gallery = aGalleryExtension('a'); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery)); - instantiationService.get(IExtensionsWorkbenchService).queryGallery().done((paged) => { - testObject.extension = paged.firstPage[0]; - const identifier = { id: getLocalExtensionIdFromGallery(gallery, gallery.version) }; - installEvent.fire({ identifier: identifier, gallery }); - didInstallEvent.fire({ identifier: identifier, gallery, local: aLocalExtension('a', gallery, { identifier }) }); - uninstallEvent.fire(identifier); - didUninstallEvent.fire({ identifier: identifier }); + return instantiationService.get(IExtensionsWorkbenchService).queryGallery() + .then((paged) => { + testObject.extension = paged.firstPage[0]; + const identifier = { id: getLocalExtensionIdFromGallery(gallery, gallery.version) }; + installEvent.fire({ identifier: identifier, gallery }); + didInstallEvent.fire({ identifier: identifier, gallery, local: aLocalExtension('a', gallery, { identifier }) }); + uninstallEvent.fire(identifier); + didUninstallEvent.fire({ identifier: identifier }); - assert.ok(!testObject.enabled); - done(); - }); + assert.ok(!testObject.enabled); + }); }); - test('Test ReloadAction when extension is uninstalled', (done) => { + test('Test ReloadAction when extension is uninstalled', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.a' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - didUninstallEvent.fire({ identifier: local.identifier }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + didUninstallEvent.fire({ identifier: local.identifier }); - assert.ok(testObject.enabled); - assert.equal('Reload to deactivate', testObject.tooltip); - assert.equal(`Reload this window to deactivate the uninstalled extension 'a'?`, testObject.reloadMessage); - done(); - }); + assert.ok(testObject.enabled); + assert.equal('Reload to deactivate', testObject.tooltip); + assert.equal(`Reload this window to deactivate the uninstalled extension 'a'?`, testObject.reloadMessage); + }); }); - test('Test ReloadAction when extension is uninstalled and installed', (done) => { + test('Test ReloadAction when extension is uninstalled and installed', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.a', version: '1.0.0' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - instantiationService.get(IExtensionsWorkbenchService).queryLocal().done(extensions => { - testObject.extension = extensions[0]; - uninstallEvent.fire(local.identifier); - didUninstallEvent.fire({ identifier: local.identifier }); + return instantiationService.get(IExtensionsWorkbenchService).queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + uninstallEvent.fire(local.identifier); + didUninstallEvent.fire({ identifier: local.identifier }); - const gallery = aGalleryExtension('a'); - const id = getLocalExtensionIdFromGallery(gallery, gallery.version); - installEvent.fire({ identifier: { id }, gallery }); - didInstallEvent.fire({ identifier: { id }, gallery, local }); + const gallery = aGalleryExtension('a'); + const id = getLocalExtensionIdFromGallery(gallery, gallery.version); + installEvent.fire({ identifier: { id }, gallery }); + didInstallEvent.fire({ identifier: { id }, gallery, local }); - assert.ok(!testObject.enabled); - done(); - }); + assert.ok(!testObject.enabled); + }); }); - test('Test ReloadAction when extension is updated while running', (done) => { + test('Test ReloadAction when extension is updated while running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.a', version: '1.0.1' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a', { version: '1.0.1' }); const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; + return workbenchService.queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; - const gallery = aGalleryExtension('a', { uuid: local.identifier.id, version: '1.0.2' }); - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + const gallery = aGalleryExtension('a', { uuid: local.identifier.id, version: '1.0.2' }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - assert.ok(testObject.enabled); - assert.equal('Reload to update', testObject.tooltip); - assert.equal(`Reload this window to activate the updated extension 'a'?`, testObject.reloadMessage); - done(); - - }); + assert.ok(testObject.enabled); + assert.equal('Reload to update', testObject.tooltip); + assert.equal(`Reload this window to activate the updated extension 'a'?`, testObject.reloadMessage); + }); }); - test('Test ReloadAction when extension is updated when not running', (done) => { + test('Test ReloadAction when extension is updated when not running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a', { version: '1.0.1' }); - const workbenchService = instantiationService.get(IExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); + const workbenchService = instantiationService.get(IExtensionsWorkbenchService); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return workbenchService.queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; - const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.2' }); - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.2' }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - assert.ok(!testObject.enabled); - done(); - }); + assert.ok(!testObject.enabled); + }); + }); }); - test('Test ReloadAction when extension is disabled when running', (done) => { + test('Test ReloadAction when extension is disabled when running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.a' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { + return workbenchService.queryLocal().then(extensions => { testObject.extension = extensions[0]; - workbenchService.setEnablement(extensions[0], EnablementState.Disabled); - - assert.ok(testObject.enabled); - assert.equal('Reload to deactivate', testObject.tooltip); - assert.equal(`Reload this window to deactivate the extension 'a'?`, testObject.reloadMessage); - done(); + return workbenchService.setEnablement(extensions[0], EnablementState.Disabled) + .then(() => { + assert.ok(testObject.enabled); + assert.equal('Reload to deactivate', testObject.tooltip); + assert.equal(`Reload this window to deactivate the extension 'a'?`, testObject.reloadMessage); + }); }); }); - test('Test ReloadAction when extension enablement is toggled when running', (done) => { + test('Test ReloadAction when extension enablement is toggled when running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.a', version: '1.0.0' }]); const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); const workbenchService = instantiationService.get(IExtensionsWorkbenchService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; - workbenchService.setEnablement(extensions[0], EnablementState.Disabled); - workbenchService.setEnablement(extensions[0], EnablementState.Enabled); - - assert.ok(!testObject.enabled); - done(); - }); + return workbenchService.queryLocal(). + then(extensions => { + testObject.extension = extensions[0]; + return workbenchService.setEnablement(extensions[0], EnablementState.Disabled) + .then(() => workbenchService.setEnablement(extensions[0], EnablementState.Enabled)) + .then(() => assert.ok(!testObject.enabled)); + }); }); - test('Test ReloadAction when extension is enabled when not running', (done) => { + test('Test ReloadAction when extension is enabled when not running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); - const workbenchService = instantiationService.get(IExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; - workbenchService.setEnablement(extensions[0], EnablementState.Enabled); - - assert.ok(testObject.enabled); - assert.equal('Reload to activate', testObject.tooltip); - assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); - done(); - }); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); + const workbenchService = instantiationService.get(IExtensionsWorkbenchService); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return workbenchService.queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + return workbenchService.setEnablement(extensions[0], EnablementState.Enabled) + .then(() => { + assert.ok(testObject.enabled); + assert.equal('Reload to activate', testObject.tooltip); + assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); + }); + }); + }); }); - test('Test ReloadAction when extension enablement is toggled when not running', (done) => { + test('Test ReloadAction when extension enablement is toggled when not running', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a'); - const workbenchService = instantiationService.get(IExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; - workbenchService.setEnablement(extensions[0], EnablementState.Enabled); - workbenchService.setEnablement(extensions[0], EnablementState.Disabled); - - assert.ok(!testObject.enabled); - done(); - }); + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); + const workbenchService = instantiationService.get(IExtensionsWorkbenchService); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return workbenchService.queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; + return workbenchService.setEnablement(extensions[0], EnablementState.Enabled) + .then(() => workbenchService.setEnablement(extensions[0], EnablementState.Disabled)) + .then(() => assert.ok(!testObject.enabled)); + }); + }); }); - test('Test ReloadAction when extension is updated when not running and enabled', (done) => { + test('Test ReloadAction when extension is updated when not running and enabled', () => { instantiationService.stubPromise(IExtensionService, 'getExtensions', [{ id: 'pub.b' }]); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); const local = aLocalExtension('a', { version: '1.0.1' }); - const workbenchService = instantiationService.get(IExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - workbenchService.queryLocal().done(extensions => { - testObject.extension = extensions[0]; + return instantiationService.get(IExtensionEnablementService).setEnablement(local, EnablementState.Disabled) + .then(() => { + const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction); + const workbenchService = instantiationService.get(IExtensionsWorkbenchService); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); + return workbenchService.queryLocal() + .then(extensions => { + testObject.extension = extensions[0]; - const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.2' }); - installEvent.fire({ identifier: gallery.identifier, gallery }); - didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); - workbenchService.setEnablement(extensions[0], EnablementState.Enabled); + const gallery = aGalleryExtension('a', { identifier: local.identifier, version: '1.0.2' }); + installEvent.fire({ identifier: gallery.identifier, gallery }); + didInstallEvent.fire({ identifier: gallery.identifier, gallery, local: aLocalExtension('a', gallery, gallery) }); + return workbenchService.setEnablement(extensions[0], EnablementState.Enabled) + .then(() => { + assert.ok(testObject.enabled); + assert.equal('Reload to activate', testObject.tooltip); + assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); + }); - assert.ok(testObject.enabled); - assert.equal('Reload to activate', testObject.tooltip); - assert.equal(`Reload this window to activate the extension 'a'?`, testObject.reloadMessage); - done(); - }); + }); + }); }); function aLocalExtension(name: string = 'someext', manifest: any = {}, properties: any = {}): ILocalExtension { diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts index a46d4cb2361..b37b3533a57 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts @@ -46,6 +46,7 @@ import { IChoiceService } from 'vs/platform/message/common/message'; import product from 'vs/platform/node/product'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; const mockExtensionGallery: IGalleryExtension[] = [ aGalleryExtension('MockExtension1', { @@ -179,7 +180,7 @@ suite('ExtensionsTipsService Test', () => { uninstallEvent = new Emitter(); didUninstallEvent = new Emitter(); instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); - + instantiationService.stub(ILifecycleService, new TestLifecycleService()); testConfigurationService = new TestConfigurationService(); instantiationService.stub(IConfigurationService, testConfigurationService); instantiationService.stub(IExtensionManagementService, ExtensionManagementService); diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 0e32124f83d..7c93cf08c8a 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -34,6 +34,8 @@ import { IChoiceService } from 'vs/platform/message/common/message'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IWindowService } from 'vs/platform/windows/common/windows'; +import { IProgressService2 } from 'vs/platform/progress/common/progress'; +import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2'; suite('ExtensionsWorkbenchService Test', () => { @@ -56,6 +58,7 @@ suite('ExtensionsWorkbenchService Test', () => { instantiationService.stub(ITelemetryService, NullTelemetryService); instantiationService.stub(ILogService, NullLogService); instantiationService.stub(IWindowService, TestWindowService); + instantiationService.stub(IProgressService2, ProgressService2); instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); @@ -78,6 +81,7 @@ suite('ExtensionsWorkbenchService Test', () => { setup(() => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []); + instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage()); instantiationService.stubPromise(IChoiceService, 'choose', 0); (instantiationService.get(IExtensionEnablementService)).reset(); @@ -698,283 +702,374 @@ suite('ExtensionsWorkbenchService Test', () => { }); test('test uninstalled extensions are always enabled', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.WorkspaceDisabled); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a'))); - return testObject.queryGallery().then(pagedResponse => { - const actual = pagedResponse.firstPage[0]; - assert.equal(actual.enablementState, EnablementState.Enabled); - }); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.WorkspaceDisabled)) + .then(() => { + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a'))); + return testObject.queryGallery().then(pagedResponse => { + const actual = pagedResponse.firstPage[0]; + assert.equal(actual.enablementState, EnablementState.Enabled); + }); + }); }); test('test enablement state installed enabled extension', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - const actual = testObject.local[0]; + const actual = testObject.local[0]; - assert.equal(actual.enablementState, EnablementState.Enabled); + assert.equal(actual.enablementState, EnablementState.Enabled); + }); }); test('test workspace disabled extension', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.d' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.e' }, EnablementState.WorkspaceDisabled); + const extensionA = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('d'), EnablementState.Disabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.WorkspaceDisabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('e'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const actual = testObject.local[0]; - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.WorkspaceDisabled); + assert.equal(actual.enablementState, EnablementState.WorkspaceDisabled); + }); }); test('test globally disabled extension', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.d' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.WorkspaceDisabled); + const localExtension = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(localExtension, EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('d'), EnablementState.Disabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [localExtension]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const actual = testObject.local[0]; - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.Disabled); + assert.equal(actual.enablementState, EnablementState.Disabled); + }); }); test('test enablement state is updated for user extensions', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - - testObject.setEnablement(testObject.local[0], EnablementState.WorkspaceDisabled); - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.WorkspaceDisabled); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return testObject.setEnablement(testObject.local[0], EnablementState.WorkspaceDisabled) + .then(() => { + const actual = testObject.local[0]; + assert.equal(actual.enablementState, EnablementState.WorkspaceDisabled); + }); + }); }); test('test enable extension globally when extension is disabled for workspace', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - - testObject.setEnablement(testObject.local[0], EnablementState.Enabled); - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.Enabled); + const localExtension = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(localExtension, EnablementState.WorkspaceDisabled) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [localExtension]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return testObject.setEnablement(testObject.local[0], EnablementState.Enabled) + .then(() => { + const actual = testObject.local[0]; + assert.equal(actual.enablementState, EnablementState.Enabled); + }); + }); }); test('test disable extension globally', () => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + const actual = testObject.local[0]; + assert.equal(actual.enablementState, EnablementState.Disabled); + }); }); test('test system extensions are always enabled', () => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', {}, { type: LocalExtensionType.System })]); testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.Enabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + const actual = testObject.local[0]; + assert.equal(actual.enablementState, EnablementState.Enabled); + }); }); test('test enablement state is updated on change from outside', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const localExtension = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [localExtension]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - const actual = testObject.local[0]; - - assert.equal(actual.enablementState, EnablementState.Disabled); + return instantiationService.get(IExtensionEnablementService).setEnablement(localExtension, EnablementState.Disabled) + .then(() => { + const actual = testObject.local[0]; + assert.equal(actual.enablementState, EnablementState.Disabled); + }); + }); }); test('test disable extension with dependencies disable only itself', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c'); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); + }); + }); }); test('test disable extension with dependencies disable all', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c')]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c'); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + }); + }); }); test('test disable extension fails if extension is a dependent of other', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c'); - return testObject.setEnablement(testObject.local[1], EnablementState.Disabled).then(() => assert.fail('Should fail'), error => assert.ok(true)); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return testObject.setEnablement(testObject.local[1], EnablementState.Disabled).then(() => assert.fail('Should fail'), error => assert.ok(true)); + }); }); test('test disable extension does not fail if its dependency is a dependent of other but chosen to disable only itself', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c', { extensionDependencies: ['pub.b'] })]); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.b'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); - - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + }); + }); }); test('test disable extension fails if its dependency is a dependent of other', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c', { extensionDependencies: ['pub.b'] })]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.b'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - - return testObject.setEnablement(testObject.local[0], EnablementState.Disabled).then(() => assert.fail('Should fail'), error => assert.ok(true)); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled).then(() => assert.fail('Should fail'), error => assert.ok(true)); + }); }); test('test disable extension if its dependency is a dependent of other disabled extension', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c', { extensionDependencies: ['pub.b'] })]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.b'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Disabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + }); + }); }); test('test disable extension if its dependencys dependency is itself', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b', { extensionDependencies: ['pub.a'] }), aLocalExtension('c')]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b', { extensionDependencies: ['pub.a'] }); + const extensionC = aLocalExtension('c'); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + }); + }); }); test('test disable extension if its dependency is dependent and is disabled', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c', { extensionDependencies: ['pub.b'] })]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.b'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Disabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => assert.equal(testObject.local[0].enablementState, EnablementState.Disabled)); + }); }); test('test disable extension with cyclic dependencies', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Enabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Enabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b', { extensionDependencies: ['pub.c'] }), aLocalExtension('c', { extensionDependencies: ['pub.a'] })]); - instantiationService.stubPromise(IChoiceService, 'choose', 1); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b', { extensionDependencies: ['pub.c'] }); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.a'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Enabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Enabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Enabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + instantiationService.stubPromise(IChoiceService, 'choose', 1); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Disabled); + }); + }); }); test('test enable extension with dependencies enable all', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b'), aLocalExtension('c')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b'); + const extensionC = aLocalExtension('c'); - testObject.setEnablement(testObject.local[0], EnablementState.Enabled); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Disabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Disabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Enabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Enabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Enabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); + }); + }); }); test('test enable extension with cyclic dependencies', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a', { extensionDependencies: ['pub.b'] }), aLocalExtension('b', { extensionDependencies: ['pub.c'] }), aLocalExtension('c', { extensionDependencies: ['pub.a'] })]); + const extensionA = aLocalExtension('a', { extensionDependencies: ['pub.b'] }); + const extensionB = aLocalExtension('b', { extensionDependencies: ['pub.c'] }); + const extensionC = aLocalExtension('c', { extensionDependencies: ['pub.a'] }); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + return instantiationService.get(IExtensionEnablementService).setEnablement(extensionA, EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionB, EnablementState.Disabled)) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(extensionC, EnablementState.Disabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [extensionA, extensionB, extensionC]); - testObject.setEnablement(testObject.local[0], EnablementState.Enabled); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - assert.equal(testObject.local[0].enablementState, EnablementState.Enabled); - assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); - assert.equal(testObject.local[2].enablementState, EnablementState.Enabled); + return testObject.setEnablement(testObject.local[0], EnablementState.Enabled) + .then(() => { + assert.equal(testObject.local[0].enablementState, EnablementState.Enabled); + assert.equal(testObject.local[1].enablementState, EnablementState.Enabled); + assert.equal(testObject.local[2].enablementState, EnablementState.Enabled); + }); + }); }); test('test change event is fired when disablement flags are changed', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - const target = sinon.spy(); - testObject.onChange(target); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const target = sinon.spy(); + testObject.onChange(target); - testObject.setEnablement(testObject.local[0], EnablementState.Disabled); - - assert.ok(target.calledOnce); + return testObject.setEnablement(testObject.local[0], EnablementState.Disabled) + .then(() => assert.ok(target.calledOnce)); + }); }); test('test change event is fired when disablement flags are changed from outside', () => { - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.c' }, EnablementState.Disabled); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.b' }, EnablementState.WorkspaceDisabled); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [aLocalExtension('a')]); - testObject = instantiationService.createInstance(ExtensionsWorkbenchService); - const target = sinon.spy(); - testObject.onChange(target); + const localExtension = aLocalExtension('a'); + return instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('c'), EnablementState.Disabled) + .then(() => instantiationService.get(IExtensionEnablementService).setEnablement(aLocalExtension('b'), EnablementState.WorkspaceDisabled)) + .then(() => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [localExtension]); + testObject = instantiationService.createInstance(ExtensionsWorkbenchService); + const target = sinon.spy(); + testObject.onChange(target); - instantiationService.get(IExtensionEnablementService).setEnablement({ id: 'pub.a' }, EnablementState.Disabled); - - assert.ok(target.calledOnce); + return instantiationService.get(IExtensionEnablementService).setEnablement(localExtension, EnablementState.Disabled) + .then(() => assert.ok(target.calledOnce)); + }); }); function aLocalExtension(name: string = 'someext', manifest: any = {}, properties: any = {}): ILocalExtension { diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedback.ts b/src/vs/workbench/parts/feedback/electron-browser/feedback.ts index 6d25338079a..8fd4bf78233 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedback.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedback.ts @@ -171,7 +171,7 @@ export class FeedbackDropdown extends Dropdown { $('div').append($('a').attr('target', '_blank').attr('href', '#').text(nls.localize("submit a bug", "Submit a bug")).attr('tabindex', '0')) .on('click', event => { dom.EventHelper.stop(event); - this.commandService.executeCommand('workbench.action.reportIssues').done(null, errors.onUnexpectedError); + this.commandService.executeCommand('workbench.action.openIssueReporter').done(null, errors.onUnexpectedError); }) .appendTo($contactUsContainer); diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index 14a2a7a7489..ed348ccc088 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -7,12 +7,13 @@ import URI from 'vs/base/common/uri'; import paths = require('vs/base/common/paths'); +import resources = require('vs/base/common/resources'); import { ResourceMap } from 'vs/base/common/map'; import { isLinux } from 'vs/base/common/platform'; -import { IFileStat, isParent } from 'vs/platform/files/common/files'; +import { IFileStat } from 'vs/platform/files/common/files'; import { IEditorInput } from 'vs/platform/editor/common/editor'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IEditorGroup, toResource } from 'vs/workbench/common/editor'; +import { IEditorGroup, toResource, IEditorIdentifier } from 'vs/workbench/common/editor'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { getPathLabel } from 'vs/base/common/labels'; @@ -130,7 +131,7 @@ export class FileStat implements IFileStat { // the folder is fully resolved if either it has a list of children or the client requested this by using the resolveTo // array of resource path to resolve. stat.isDirectoryResolved = !!raw.children || (!!resolveTo && resolveTo.some((r) => { - return paths.isEqualOrParent(r.fsPath, stat.resource.fsPath, !isLinux /* ignorecase */); + return resources.isEqualOrParent(r, stat.resource, !isLinux /* ignorecase */); })); // Recurse into children @@ -280,7 +281,7 @@ export class FileStat implements IFileStat { public find(resource: URI): FileStat { // Return if path found - if (paths.isEqual(resource.fsPath, this.resource.fsPath, !isLinux /* ignorecase */)) { + if (resources.isEqual(resource, this.resource, !isLinux /* ignorecase */)) { return this; } @@ -292,11 +293,11 @@ export class FileStat implements IFileStat { for (let i = 0; i < this.children.length; i++) { const child = this.children[i]; - if (paths.isEqual(resource.fsPath, child.resource.fsPath, !isLinux /* ignorecase */)) { + if (resources.isEqual(resource, child.resource, !isLinux /* ignorecase */)) { return child; } - if (child.isDirectory && isParent(resource.fsPath, child.resource.fsPath, !isLinux /* ignorecase */)) { + if (child.isDirectory && resources.isEqualOrParent(resource, child.resource, !isLinux /* ignorecase */)) { return child.find(resource); } } @@ -369,18 +370,18 @@ export class NewStatPlaceholder extends FileStat { } } -export class OpenEditor { +export class OpenEditor implements IEditorIdentifier { - constructor(private editor: IEditorInput, private group: IEditorGroup) { + constructor(private _editor: IEditorInput, private _group: IEditorGroup) { // noop } - public get editorInput() { - return this.editor; + public get editor() { + return this._editor; } - public get editorGroup() { - return this.group; + public get group() { + return this._group; } public getId(): string { diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts index 448a7a7dff1..f365329c68a 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.contribution.ts @@ -11,7 +11,7 @@ import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTI import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; -import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL } from 'vs/workbench/parts/files/electron-browser/fileCommands'; +import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, REVEAL_IN_OS_LABEL, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID } from 'vs/workbench/parts/files/electron-browser/fileCommands'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -23,7 +23,7 @@ import { OPEN_FOLDER_SETTINGS_COMMAND, OPEN_FOLDER_SETTINGS_LABEL } from 'vs/wor import { AutoSaveContext } from 'vs/workbench/services/textfile/common/textfiles'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService'; - +import URI from 'vs/base/common/uri'; // Contribute Global Actions const category = nls.localize('filesCategory', "File"); @@ -116,17 +116,23 @@ function appendEditorTitleContextMenuItem(id: string, title: string, when: Conte } // Editor Title Menu for Conflict Resolution -appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite disk contents"), 'save-conflict-action-accept-changes', -10, acceptLocalChangesCommand); -appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to content on disk"), 'save-conflict-action-revert-changes', -9, revertLocalChangesCommand); +appendSaveConflictEditorTitleAction('workbench.files.action.acceptLocalChanges', nls.localize('acceptLocalChanges', "Use your changes and overwrite disk contents"), { + light: URI.parse(require.toUrl(`vs/workbench/parts/files/electron-browser/media/check.svg`)).fsPath, + dark: URI.parse(require.toUrl(`vs/workbench/parts/files/electron-browser/media/check-inverse.svg`)).fsPath +}, -10, acceptLocalChangesCommand); +appendSaveConflictEditorTitleAction('workbench.files.action.revertLocalChanges', nls.localize('revertLocalChanges', "Discard your changes and revert to content on disk"), { + light: URI.parse(require.toUrl(`vs/workbench/parts/files/electron-browser/media/undo.svg`)).fsPath, + dark: URI.parse(require.toUrl(`vs/workbench/parts/files/electron-browser/media/undo-inverse.svg`)).fsPath +}, -9, revertLocalChangesCommand); -function appendSaveConflictEditorTitleAction(id: string, title: string, iconClass: string, order: number, command: ICommandHandler): void { +function appendSaveConflictEditorTitleAction(id: string, title: string, iconPath: { dark: string; light?: string; }, order: number, command: ICommandHandler): void { // Command CommandsRegistry.registerCommand(id, command); // Action MenuRegistry.appendMenuItem(MenuId.EditorTitle, { - command: { id, title, iconClass }, + command: { id, title, iconPath }, when: ContextKeyExpr.equals(CONFLICT_RESOLUTION_CONTEXT, true), group: 'navigation', order @@ -148,6 +154,7 @@ function appendToCommandPalette(id: string, title: string, category: string, whe appendToCommandPalette(COPY_PATH_COMMAND_ID, nls.localize('copyPathOfActive', "Copy Path of Active File"), category); appendToCommandPalette(SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, category); appendToCommandPalette(SAVE_ALL_IN_GROUP_COMMAND_ID, nls.localize('saveAllInGroup', "Save All in Group"), category); +appendToCommandPalette(SAVE_FILES_COMMAND_ID, nls.localize('saveFiles', "Save All Files"), category); appendToCommandPalette(REVERT_FILE_COMMAND_ID, nls.localize('revert', "Revert File"), category); appendToCommandPalette(COMPARE_WITH_SAVED_COMMAND_ID, nls.localize('compareActiveWithSaved', "Compare Active File with Saved"), category); appendToCommandPalette(REVEAL_IN_OS_COMMAND_ID, REVEAL_IN_OS_LABEL, category); diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.ts index e80a6804eb1..952968f7641 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.ts @@ -318,7 +318,7 @@ class RenameFileAction extends BaseRenameAction { const model = this.textFileService.models.get(d); - return this.backupFileService.backupResource(renamed, model.getValue(), model.getVersionId()); + return this.backupFileService.backupResource(renamed, model.createSnapshot(), model.getVersionId()); })) // 2. soft revert all dirty since we have backed up their contents diff --git a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts index 23f1b15a206..b562912f181 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts @@ -68,7 +68,6 @@ export const SAVE_ALL_LABEL = nls.localize('saveAll', "Save All"); export const SAVE_ALL_IN_GROUP_COMMAND_ID = 'workbench.files.action.saveAllInGroup'; export const SAVE_FILES_COMMAND_ID = 'workbench.action.files.saveFiles'; -export const SAVE_FILES_LABEL = nls.localize('saveFiles', "Save All Files"); export const OpenEditorsGroupContext = new RawContextKey('groupFocusedInOpenEditors', false); export const DirtyEditorContext = new RawContextKey('dirtyEditor', false); @@ -475,6 +474,11 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: (accessor, resource: URI) => { const editorService = accessor.get(IWorkbenchEditorService); const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService); + + if (resources.length === 1) { + // If only one resource is selected explictly call save since the behavior is a bit different than save all #41841 + return save(resources[0], false, editorService, accessor.get(IFileService), accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupService)); + } return saveAll(resources, editorService, accessor.get(IUntitledEditorService), accessor.get(ITextFileService), accessor.get(IEditorGroupService)); } }); @@ -495,9 +499,9 @@ CommandsRegistry.registerCommand({ saveAllArg = true; } else { const fileService = accessor.get(IFileService); + saveAllArg = []; contexts.forEach(context => { const editorGroup = context.group; - saveAllArg = []; editorGroup.getEditors().forEach(editor => { const resource = toResource(editor, { supportSideBySide: true }); if (resource && (resource.scheme === 'untitled' || fileService.canHandleResource(resource))) { diff --git a/src/vs/workbench/parts/files/electron-browser/media/fileactions.css b/src/vs/workbench/parts/files/electron-browser/media/fileactions.css index a073640bc8f..2eb68b32b03 100644 --- a/src/vs/workbench/parts/files/electron-browser/media/fileactions.css +++ b/src/vs/workbench/parts/files/electron-browser/media/fileactions.css @@ -75,22 +75,6 @@ background-image: url('split-editor-horizontal-inverse.svg'); } -.monaco-workbench .save-conflict-action-accept-changes { - background: url('check.svg') center center no-repeat; -} - -.vs-dark .monaco-workbench .save-conflict-action-accept-changes { - background: url('check-inverse.svg') center center no-repeat; -} - -.monaco-workbench .save-conflict-action-revert-changes { - background: url('undo.svg') center center no-repeat; -} - -.vs-dark .monaco-workbench .save-conflict-action-revert-changes { - background: url('undo-inverse.svg') center center no-repeat; -} - .monaco-workbench .file-editor-action.action-open-preview { background: url('Preview.svg') center center no-repeat; } diff --git a/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts b/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts index 379a2a53d81..3a0864e2ea7 100644 --- a/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts +++ b/src/vs/workbench/parts/files/electron-browser/saveErrorHandler.ts @@ -31,6 +31,7 @@ import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEdi import { IModelService } from 'vs/editor/common/services/modelService'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { SAVE_FILE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL } from 'vs/workbench/parts/files/electron-browser/fileCommands'; +import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; export const CONFLICT_RESOLUTION_CONTEXT = 'saveConflictResolutionContext'; export const CONFLICT_RESOLUTION_SCHEME = 'conflictResolution'; @@ -262,7 +263,7 @@ export const acceptLocalChangesCommand = (accessor: ServicesAccessor, resource: resolverService.createModelReference(resource).then(reference => { const model = reference.object as ITextFileEditorModel; - const localModelValue = model.getValue(); + const localModelSnapshot = model.createSnapshot(); clearPendingResolveSaveConflictMessages(); // hide any previously shown message about how to use these actions @@ -270,7 +271,7 @@ export const acceptLocalChangesCommand = (accessor: ServicesAccessor, resource: return model.revert().then(() => { // Restore user value (without loosing undo stack) - modelService.updateModel(model.textEditorModel, localModelValue); + modelService.updateModel(model.textEditorModel, createTextBufferFactoryFromSnapshot(localModelSnapshot)); // Trigger save return model.save().then(() => { diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts index f2cb5c1ca89..9d28ff82fa4 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts @@ -39,10 +39,9 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ResourceGlobMatcher } from 'vs/workbench/electron-browser/resources'; -import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { isLinux } from 'vs/base/common/platform'; import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; export interface IExplorerViewOptions extends IViewletViewOptions { viewletState: FileViewletState; @@ -84,14 +83,12 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView @IEditorGroupService private editorGroupService: IEditorGroupService, @IWorkspaceContextService private contextService: IWorkspaceContextService, @IProgressService private progressService: IProgressService, - @IListService private listService: IListService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IFileService private fileService: IFileService, @IPartService private partService: IPartService, @IKeybindingService keybindingService: IKeybindingService, - @IContextKeyService private contextKeyService: IContextKeyService, + @IContextKeyService contextKeyService: IContextKeyService, @IConfigurationService private configurationService: IConfigurationService, - @IWorkbenchThemeService private themeService: IWorkbenchThemeService, @IDecorationsService decorationService: IDecorationsService ) { super({ ...(options as IViewOptions), ariaHeaderLabel: nls.localize('explorerSection', "Files Explorer Section") }, keybindingService, contextMenuService); @@ -396,7 +393,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView const dnd = this.instantiationService.createInstance(FileDragAndDrop); const accessibilityProvider = this.instantiationService.createInstance(FileAccessibilityProvider); - this.explorerViewer = new FileIconThemableWorkbenchTree(container.getHTMLElement(), { + this.explorerViewer = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, container.getHTMLElement(), { dataSource, renderer, controller, @@ -408,7 +405,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView autoExpandSingleChildren: true, ariaLabel: nls.localize('treeAriaLabel', "Files Explorer"), keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); // Bind context keys FilesExplorerFocusedContext.bindTo(this.explorerViewer.contextKeyService); @@ -780,6 +777,16 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView isDirectory: true }, root); + const setInputAndExpand = (input: FileStat | Model, statsToExpand: FileStat[]) => { + // Make sure to expand all folders that where expanded in the previous session + // Special case: we are switching to multi workspace view, thus expand all the roots (they might just be added) + if (input === this.model && statsToExpand.every(fs => !fs.isRoot)) { + statsToExpand = this.model.roots.concat(statsToExpand); + } + + return this.explorerViewer.setInput(input).then(() => this.explorerViewer.expandAll(statsToExpand)); + }; + if (targetsToResolve.every(t => t.root.resource.scheme === 'file')) { // All the roots are local, resolve them in parallel return this.fileService.resolveFiles(targetsToResolve).then(results => { @@ -795,17 +802,11 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView modelStats.forEach((modelStat, index) => FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index])); const statsToExpand: FileStat[] = this.explorerViewer.getExpandedElements().concat(targetsToExpand.map(expand => this.model.findClosest(expand))); - if (input === this.explorerViewer.getInput()) { - return this.explorerViewer.refresh().then(() => statsToExpand.length ? this.explorerViewer.expandAll(statsToExpand) : undefined); + return this.explorerViewer.refresh().then(() => this.explorerViewer.expandAll(statsToExpand)); } - // Make sure to expand all folders that where expanded in the previous session - // Special case: there is nothing to expand, thus expand all the roots (they might just be added) - if (statsToExpand.length === 0) { - statsToExpand.push(...this.model.roots); - } - return this.explorerViewer.setInput(input).then(() => statsToExpand.length ? this.explorerViewer.expandAll(statsToExpand) : undefined); + return setInputAndExpand(input, statsToExpand); }); } @@ -832,13 +833,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView return delayerPromise; } - // Display roots only when multi folder workspace - // Make sure to expand all folders that where expanded in the previous session - if (input === this.model) { - // We have transitioned into workspace view -> expand all roots - toExpand = this.model.roots.concat(toExpand); - } - return this.explorerViewer.setInput(input).then(() => this.explorerViewer.expandAll(toExpand)); + return setInputAndExpand(input, statsToExpand); }))); } diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts index 1105d96bf3f..b5f34511a47 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts @@ -56,6 +56,7 @@ import { extractResources } from 'vs/workbench/browser/editor'; import { relative } from 'path'; import { DataTransfers } from 'vs/base/browser/dnd'; import { distinctParents } from 'vs/base/common/resources'; +import { WorkbenchTree, multiSelectModifierSettingKey } from 'vs/platform/list/browser/listService'; export class FileDataSource implements IDataSource { constructor( @@ -279,16 +280,15 @@ export class FileRenderer implements IRenderer { inputBox.select({ start: 0, end: lastDot > 0 && !stat.isDirectory ? lastDot : value.length }); inputBox.focus(); - const done = once((commit: boolean) => { + const done = once((commit: boolean, blur: boolean) => { tree.clearHighlight(); if (commit && inputBox.value) { editableData.action.run({ value: inputBox.value }); } - const restoreFocus = document.activeElement === inputBox.inputElement; // https://github.com/Microsoft/vscode/issues/20269 setTimeout(() => { - if (restoreFocus) { + if (!blur) { // https://github.com/Microsoft/vscode/issues/20269 tree.DOMFocus(); } lifecycle.dispose(toDispose); @@ -301,14 +301,14 @@ export class FileRenderer implements IRenderer { DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => { if (e.equals(KeyCode.Enter)) { if (inputBox.validate()) { - done(true); + done(true, false); } } else if (e.equals(KeyCode.Escape)) { - done(false); + done(false, false); } }), DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => { - done(inputBox.isInputValid()); + done(inputBox.isInputValid(), true); }), label, styler @@ -330,18 +330,30 @@ export class FileController extends DefaultController implements IDisposable { private contributedContextMenu: IMenu; private toDispose: IDisposable[]; private previousSelectionRangeStop: FileStat; + private useAltAsMultiSelectModifier: boolean; - constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + constructor( + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IContextMenuService private contextMenuService: IContextMenuService, @ITelemetryService private telemetryService: ITelemetryService, - @IMenuService menuService: IMenuService, - @IContextKeyService contextKeyService: IContextKeyService + @IMenuService private menuService: IMenuService, + @IContextKeyService contextKeyService: IContextKeyService, + @IConfigurationService private configurationService: IConfigurationService ) { super({ clickBehavior: ClickBehavior.ON_MOUSE_UP /* do not change to not break DND */, keyboardSupport: false /* handled via IListService */ }); + this.useAltAsMultiSelectModifier = configurationService.getValue(multiSelectModifierSettingKey) === 'alt'; this.toDispose = []; - this.contributedContextMenu = menuService.createMenu(MenuId.ExplorerContext, contextKeyService); - this.toDispose.push(this.contributedContextMenu); + + this.registerListeners(); + } + + private registerListeners(): void { + this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(multiSelectModifierSettingKey)) { + this.useAltAsMultiSelectModifier = this.configurationService.getValue(multiSelectModifierSettingKey) === 'alt'; + } + })); } public onLeftClick(tree: ITree, stat: FileStat | Model, event: IMouseEvent, origin: string = 'mouse'): boolean { @@ -381,7 +393,8 @@ export class FileController extends DefaultController implements IDisposable { return true; } - if (event.ctrlKey || event.metaKey) { + // Allow to multiselect + if ((this.useAltAsMultiSelectModifier && event.altKey) || !this.useAltAsMultiSelectModifier && (event.ctrlKey || event.metaKey)) { const selection = tree.getSelection(); this.previousSelectionRangeStop = undefined; if (selection.indexOf(stat) >= 0) { @@ -420,14 +433,19 @@ export class FileController extends DefaultController implements IDisposable { tree.setSelection([stat], payload); if (!stat.isDirectory) { - this.openEditor(stat, { preserveFocus, sideBySide: event && event.altKey, pinned: isDoubleClick }); + let sideBySide = false; + if (event) { + sideBySide = this.useAltAsMultiSelectModifier ? (event.ctrlKey || event.metaKey) : event.altKey; + } + + this.openEditor(stat, { preserveFocus, sideBySide, pinned: isDoubleClick }); } } return true; } - public onContextMenu(tree: ITree, stat: FileStat | Model, event: ContextMenuEvent): boolean { + public onContextMenu(tree: WorkbenchTree, stat: FileStat | Model, event: ContextMenuEvent): boolean { if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') { return false; } @@ -437,13 +455,18 @@ export class FileController extends DefaultController implements IDisposable { tree.setFocus(stat); + if (!this.contributedContextMenu) { + this.contributedContextMenu = this.menuService.createMenu(MenuId.ExplorerContext, tree.contextKeyService); + this.toDispose.push(this.contributedContextMenu); + } + const anchor = { x: event.posx, y: event.posy }; const selection = tree.getSelection(); this.contextMenuService.showContextMenu({ getAnchor: () => anchor, getActions: () => { const actions = []; - fillInActions(this.contributedContextMenu, { arg: stat instanceof FileStat ? stat.resource : undefined, shouldForwardArgs: true }, actions, this.contextMenuService); + fillInActions(this.contributedContextMenu, { arg: stat instanceof FileStat ? stat.resource : {}, shouldForwardArgs: true }, actions, this.contextMenuService); return TPromise.as(actions); }, onHide: (wasCancelled?: boolean) => { @@ -451,7 +474,9 @@ export class FileController extends DefaultController implements IDisposable { tree.DOMFocus(); } }, - getActionsContext: () => selection && selection.indexOf(stat) >= 0 ? selection.map((fs: FileStat) => fs.resource) : [stat] + getActionsContext: () => selection && selection.indexOf(stat) >= 0 + ? selection.map((fs: FileStat) => fs.resource) + : stat instanceof FileStat ? [stat.resource] : [] }); return true; @@ -945,7 +970,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { const model = this.textFileService.models.get(d); - return this.backupFileService.backupResource(moved, model.getValue(), model.getVersionId()); + return this.backupFileService.backupResource(moved, model.createSnapshot(), model.getVersionId()); })) // 2. soft revert all dirty since we have backed up their contents diff --git a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts index 4e2016ba3cc..d411f925e09 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts @@ -28,7 +28,7 @@ import { EditorGroup } from 'vs/workbench/common/editor/editorStacksModel'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { badgeBackground, badgeForeground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IListService, WorkbenchList } from 'vs/platform/list/browser/listService'; +import { WorkbenchList, useAltAsMultipleSelectionModifier } from 'vs/platform/list/browser/listService'; import { IDelegate, IRenderer, IListContextMenuEvent, IListMouseEvent } from 'vs/base/browser/ui/list/list'; import { EditorLabel } from 'vs/workbench/browser/labels'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -74,12 +74,11 @@ export class OpenEditorsView extends ViewsViewletPanel { @IEditorGroupService private editorGroupService: IEditorGroupService, @IConfigurationService private configurationService: IConfigurationService, @IKeybindingService keybindingService: IKeybindingService, - @IListService private listService: IListService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService, @IContextKeyService private contextKeyService: IContextKeyService, @IThemeService private themeService: IThemeService, @ITelemetryService private telemetryService: ITelemetryService, - @IMenuService menuService: IMenuService + @IMenuService private menuService: IMenuService ) { super({ ...(options as IViewOptions), @@ -98,8 +97,6 @@ export class OpenEditorsView extends ViewsViewletPanel { } this.needsRefresh = false; }, this.structuralRefreshDelay); - this.contributedContextMenu = menuService.createMenu(MenuId.OpenEditorsContext, contextKeyService); - this.disposables.push(this.contributedContextMenu); // update on model changes this.disposables.push(this.model.onModelChanged(e => this.onEditorStacksModelChanged(e))); @@ -152,13 +149,16 @@ export class OpenEditorsView extends ViewsViewletPanel { return focused; }; - this.list = new WorkbenchList(container, delegate, [ + this.list = this.instantiationService.createInstance(WorkbenchList, container, delegate, [ new EditorGroupRenderer(this.keybindingService, this.instantiationService, this.editorGroupService), new OpenEditorRenderer(getSelectedElements, this.instantiationService, this.keybindingService, this.configurationService, this.editorGroupService) ], { keyboardSupport: false, identityProvider: element => element instanceof OpenEditor ? element.getId() : element.id.toString() - }, this.contextKeyService, this.listService, this.themeService); + }); + + this.contributedContextMenu = this.menuService.createMenu(MenuId.OpenEditorsContext, this.list.contextKeyService); + this.disposables.push(this.contributedContextMenu); this.updateSize(); @@ -193,7 +193,7 @@ export class OpenEditorsView extends ViewsViewletPanel { const focused = this.list.getFocusedElements(); const element = focused.length ? focused[0] : undefined; if (element instanceof OpenEditor) { - this.openEditor(element, { pinned: false, sideBySide: !!event.altKey, preserveFocus: false }); + this.openEditor(element, { pinned: false, sideBySide: !!(event.altKey || event.ctrlKey || event.metaKey), preserveFocus: false }); } } })); @@ -275,10 +275,11 @@ export class OpenEditorsView extends ViewsViewletPanel { } if (event.browserEvent && event.browserEvent.button === 1 /* Middle Button */) { - const position = this.model.positionOfGroup(element.editorGroup); - this.editorService.closeEditor(position, element.editorInput).done(null, errors.onUnexpectedError); + const position = this.model.positionOfGroup(element.group); + this.editorService.closeEditor(position, element.editor).done(null, errors.onUnexpectedError); } else { - this.openEditor(element, { preserveFocus: !isDoubleClick, pinned: isDoubleClick, sideBySide: event.browserEvent.altKey }); + const sideBySide = useAltAsMultipleSelectionModifier(this.configurationService) ? event.browserEvent.altKey : (event.browserEvent.ctrlKey || event.browserEvent.metaKey); + this.openEditor(element, { preserveFocus: !isDoubleClick, pinned: isDoubleClick, sideBySide }); } } @@ -291,12 +292,12 @@ export class OpenEditorsView extends ViewsViewletPanel { } */ this.telemetryService.publicLog('workbenchActionExecuted', { id: 'workbench.files.openFile', from: 'openEditors' }); - let position = this.model.positionOfGroup(element.editorGroup); + let position = this.model.positionOfGroup(element.group); if (options.sideBySide && position !== Position.THREE) { position++; } this.editorGroupService.activateGroup(this.model.groupAt(position)); - this.editorService.openEditor(element.editorInput, options, position) + this.editorService.openEditor(element.editor, options, position) .done(() => this.editorGroupService.activateGroup(this.model.groupAt(position)), errors.onUnexpectedError); } } @@ -307,10 +308,10 @@ export class OpenEditorsView extends ViewsViewletPanel { getAnchor: () => e.anchor, getActions: () => { const actions = []; - fillInActions(this.contributedContextMenu, { shouldForwardArgs: true, arg: element instanceof OpenEditor ? element.editorInput.getResource() : {} }, actions, this.contextMenuService); + fillInActions(this.contributedContextMenu, { shouldForwardArgs: true, arg: element instanceof OpenEditor ? element.editor.getResource() : {} }, actions, this.contextMenuService); return TPromise.as(actions); }, - getActionsContext: () => element instanceof OpenEditor ? { group: element.editorGroup, editor: element.editorInput } : { group: element } + getActionsContext: () => element instanceof OpenEditor ? { group: element.group, editor: element.editor } : { group: element } }); } @@ -481,7 +482,7 @@ class EditorGroupRenderer implements IRenderer - this.editorGroupService.moveEditor(oe.editorInput, model.positionOfGroup(oe.editorGroup), positionOfTargetGroup, { preserveFocus: true })); + this.editorGroupService.moveEditor(oe.editor, model.positionOfGroup(oe.group), positionOfTargetGroup, { preserveFocus: true })); this.editorGroupService.activateGroup(positionOfTargetGroup); } })); @@ -538,7 +539,7 @@ class OpenEditorRenderer implements IRenderer document.body.removeChild(dragImage), 0); @@ -546,7 +547,7 @@ class OpenEditorRenderer implements IRendererthis.getSelectedElements().filter(e => e instanceof OpenEditor); OpenEditorRenderer.DRAGGED_OPEN_EDITORS = dragged; - if (editorTemplate.openEditor && editorTemplate.openEditor.editorInput) { + if (editorTemplate.openEditor && editorTemplate.openEditor.editor) { // enables dropping editor resource path into text controls e.dataTransfer.setData(DataTransfers.TEXT, dragged.map(d => d.getResource()).map(resource => resource.scheme === 'file' ? getPathLabel(resource) : resource.toString()).join('\n')); @@ -573,11 +574,11 @@ class OpenEditorRenderer implements IRenderer - this.editorGroupService.moveEditor(oe.editorInput, model.positionOfGroup(oe.editorGroup), positionOfTargetGroup, { index, preserveFocus: true })); + this.editorGroupService.moveEditor(oe.editor, model.positionOfGroup(oe.group), positionOfTargetGroup, { index, preserveFocus: true })); this.editorGroupService.activateGroup(positionOfTargetGroup); } })); @@ -591,12 +592,12 @@ class OpenEditorRenderer implements IRenderer().explorer.decorations }); - templateData.actionBar.context = { group: editor.editorGroup, editor: editor.editorInput }; + templateData.actionBar.context = { group: editor.group, editor: editor.editor }; } disposeTemplate(templateData: IOpenEditorTemplateData): void { diff --git a/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts b/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts index 4b9590f037f..a76038659ec 100644 --- a/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts +++ b/src/vs/workbench/parts/files/test/browser/fileEditorTracker.test.ts @@ -16,7 +16,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { FileOperation, FileOperationEvent, FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/files/common/files'; +import { FileOperation, FileOperationEvent, FileChangesEvent, FileChangeType, IFileService, snapshotToString } from 'vs/platform/files/common/files'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { once } from 'vs/base/common/event'; @@ -191,14 +191,14 @@ suite('Files - FileEditorTracker', () => { accessor.textFileService.models.loadOrCreate(resource).then((model: TextFileEditorModel) => { model.textEditorModel.setValue('Super Good'); - assert.equal(model.getValue(), 'Super Good'); + assert.equal(snapshotToString(model.createSnapshot()), 'Super Good'); model.save().then(() => { // change event (watcher) accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource, type: FileChangeType.UPDATED }])); - assert.equal(model.getValue(), 'Hello Html'); + assert.equal(snapshotToString(model.createSnapshot()), 'Hello Html'); tracker.dispose(); diff --git a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts index 9674b857ced..edee199e773 100644 --- a/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts +++ b/src/vs/workbench/parts/html/browser/htmlPreviewPart.ts @@ -25,6 +25,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import Webview, { WebviewOptions } from './webview'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { WebviewEditor } from './webviewEditor'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; /** @@ -46,13 +47,14 @@ export class HtmlPreviewPart extends WebviewEditor { constructor( @ITelemetryService telemetryService: ITelemetryService, - @ITextModelService private textModelResolverService: ITextModelService, @IThemeService themeService: IThemeService, - @IOpenerService private readonly openerService: IOpenerService, - @IPartService private partService: IPartService, @IStorageService storageService: IStorageService, - @IContextViewService private _contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextKeyService contextKeyService: IContextKeyService, + @ITextModelService private readonly textModelResolverService: ITextModelService, + @IOpenerService private readonly openerService: IOpenerService, + @IPartService private readonly partService: IPartService, + @IContextViewService private readonly _contextViewService: IContextViewService, + @IEnvironmentService private readonly _environmentService: IEnvironmentService ) { super(HtmlPreviewPart.ID, telemetryService, themeService, storageService, contextKeyService); } @@ -84,7 +86,7 @@ export class HtmlPreviewPart extends WebviewEditor { webviewOptions = this.input.options; } - this._webview = new Webview(this.content, this.partService.getContainer(Parts.EDITOR_PART), this._contextViewService, this.contextKey, this.findInputFocusContextKey, webviewOptions); + this._webview = new Webview(this.content, this.partService.getContainer(Parts.EDITOR_PART), this._environmentService, this._contextViewService, this.contextKey, this.findInputFocusContextKey, webviewOptions, true); if (this.input && this.input instanceof HtmlInput) { const state = this.loadViewState(this.input.getResource()); this.scrollYPercentage = state ? state.scrollYPercentage : 0; diff --git a/src/vs/workbench/parts/html/browser/webview-pre.js b/src/vs/workbench/parts/html/browser/webview-pre.js index ebb69c9bd46..17c09cdc32f 100644 --- a/src/vs/workbench/parts/html/browser/webview-pre.js +++ b/src/vs/workbench/parts/html/browser/webview-pre.js @@ -264,7 +264,7 @@ contentWindow.addEventListener('scroll', handleInnerScroll); pendingMessages.forEach(function (data) { - contentWindow.postMessage(data, document.location.origin); + contentWindow.postMessage(data, '*'); }); pendingMessages = []; } @@ -303,7 +303,7 @@ } else { const target = getActiveFrame(); if (target) { - target.contentWindow.postMessage(data, document.location.origin); + target.contentWindow.postMessage(data, '*'); } } }); diff --git a/src/vs/workbench/parts/html/browser/webview.ts b/src/vs/workbench/parts/html/browser/webview.ts index c4954e1f376..4010801932e 100644 --- a/src/vs/workbench/parts/html/browser/webview.ts +++ b/src/vs/workbench/parts/html/browser/webview.ts @@ -14,6 +14,9 @@ import { ITheme, LIGHT, DARK } from 'vs/platform/theme/common/themeService'; import { WebviewFindWidget } from './webviewFindWidget'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { normalize, nativeSep } from 'vs/base/common/paths'; +import { startsWith } from 'vs/base/common/strings'; export interface WebviewElementFindInPageOptions { forward?: boolean; @@ -39,8 +42,6 @@ export interface WebviewOptions { } export default class Webview { - private static index: number = 0; - private readonly _webview: Electron.WebviewTag; private _ready: Promise; private _disposables: IDisposable[] = []; @@ -55,13 +56,15 @@ export default class Webview { constructor( private readonly parent: HTMLElement, private readonly _styleElement: Element, - @IContextViewService private readonly _contextViewService: IContextViewService, + private readonly _environmentService: IEnvironmentService, + private readonly _contextViewService: IContextViewService, private readonly _contextKey: IContextKey, private readonly _findInputContextKey: IContextKey, - private _options: WebviewOptions = {}, + private _options: WebviewOptions, + useSameOriginForRoot: boolean ) { this._webview = document.createElement('webview'); - this._webview.setAttribute('partition', this._options.allowSvgs ? 'webview' : `webview${Webview.index++}`); + this._webview.setAttribute('partition', this._options.allowSvgs ? 'webview' : `webview${Date.now()}`); // disable auxclick events (see https://developers.google.com/web/updates/2016/10/auxclick) this._webview.setAttribute('disableblinkfeatures', 'Auxclick'); @@ -75,7 +78,7 @@ export default class Webview { this._webview.style.outline = '0'; this._webview.preload = require.toUrl('./webview-pre.js'); - this._webview.src = require.toUrl('./webview.html'); + this._webview.src = useSameOriginForRoot ? require.toUrl('./webview.html') : 'data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E'; this._ready = new Promise(resolve => { const subscription = addDisposableListener(this._webview, 'ipc-message', (event) => { @@ -89,9 +92,24 @@ export default class Webview { }); }); + if (!useSameOriginForRoot) { + let loaded = false; + this._disposables.push(addDisposableListener(this._webview, 'did-start-loading', () => { + if (loaded) { + return; + } + loaded = true; + + const contents = this._webview.getWebContents(); + if (contents && !contents.isDestroyed()) { + registerFileProtocol(contents, 'vscode-core-resource', [this._environmentService.appRoot]); + } + })); + } + if (!this._options.allowSvgs) { let loaded = false; - const subscription = addDisposableListener(this._webview, 'did-start-loading', () => { + this._disposables.push(addDisposableListener(this._webview, 'did-start-loading', () => { if (loaded) { return; } @@ -124,9 +142,7 @@ export default class Webview { } return callback({ cancel: false, responseHeaders: details.responseHeaders }); }); - }); - - this._disposables.push(subscription); + })); } this._disposables.push( @@ -397,3 +413,25 @@ export default class Webview { this._webviewFindWidget.showPreviousFindTerm(); } } + +function registerFileProtocol( + contents: Electron.WebContents, + protocol: string, + roots: string[] +) { + contents.session.protocol.registerFileProtocol(protocol, (request, callback: any) => { + const requestPath = URI.parse(request.url).fsPath; + for (const root of roots) { + const normalizedPath = normalize(requestPath, true); + if (startsWith(normalizedPath, root + nativeSep)) { + callback({ path: normalizedPath }); + return; + } + } + callback({ error: 'Cannot load resource outside of protocol root' }); + }, (error) => { + if (error) { + console.error('Failed to register protocol ' + protocol); + } + }); +} \ No newline at end of file diff --git a/src/vs/workbench/parts/logs/electron-browser/logsActions.ts b/src/vs/workbench/parts/logs/electron-browser/logsActions.ts index e9bac087e2f..3807db0519a 100644 --- a/src/vs/workbench/parts/logs/electron-browser/logsActions.ts +++ b/src/vs/workbench/parts/logs/electron-browser/logsActions.ts @@ -10,7 +10,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import { TPromise } from 'vs/base/common/winjs.base'; import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; -import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel, DEFAULT_LOG_LEVEL } from 'vs/platform/log/common/log'; import { IOutputService, COMMAND_OPEN_LOG_VIEWER } from 'vs/workbench/parts/output/common/output'; import * as Constants from 'vs/workbench/parts/logs/common/logConstants'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -108,14 +108,15 @@ export class SetLogLevelAction extends Action { } run(): TPromise { + const current = this.logService.getLevel(); const entries = [ - { label: nls.localize('trace', "Trace"), level: LogLevel.Trace }, - { label: nls.localize('debug', "Debug"), level: LogLevel.Debug }, - { label: nls.localize('info', "Info"), level: LogLevel.Info }, - { label: nls.localize('warn', "Warning"), level: LogLevel.Warning }, - { label: nls.localize('err', "Error"), level: LogLevel.Error }, - { label: nls.localize('critical', "Critical"), level: LogLevel.Critical }, - { label: nls.localize('off', "Off"), level: LogLevel.Off } + { label: nls.localize('trace', "Trace"), level: LogLevel.Trace, description: this.getDescription(LogLevel.Trace, current) }, + { label: nls.localize('debug', "Debug"), level: LogLevel.Debug, description: this.getDescription(LogLevel.Debug, current) }, + { label: nls.localize('info', "Info"), level: LogLevel.Info, description: this.getDescription(LogLevel.Info, current) }, + { label: nls.localize('warn', "Warning"), level: LogLevel.Warning, description: this.getDescription(LogLevel.Warning, current) }, + { label: nls.localize('err', "Error"), level: LogLevel.Error, description: this.getDescription(LogLevel.Error, current) }, + { label: nls.localize('critical', "Critical"), level: LogLevel.Critical, description: this.getDescription(LogLevel.Critical, current) }, + { label: nls.localize('off', "Off"), level: LogLevel.Off, description: this.getDescription(LogLevel.Off, current) }, ]; return this.quickOpenService.pick(entries, { placeHolder: nls.localize('selectLogLevel', "Select log level"), autoFocus: { autoFocusIndex: this.logService.getLevel() } }).then(entry => { @@ -124,4 +125,17 @@ export class SetLogLevelAction extends Action { } }); } + + private getDescription(level: LogLevel, current: LogLevel): string { + if (DEFAULT_LOG_LEVEL === level && current === level) { + return nls.localize('default and current', "Default & Current"); + } + if (DEFAULT_LOG_LEVEL === level) { + return nls.localize('default', "Default"); + } + if (current === level) { + return nls.localize('current', "Current"); + } + return void 0; + } } \ No newline at end of file diff --git a/src/vs/workbench/parts/markers/browser/markersPanel.ts b/src/vs/workbench/parts/markers/browser/markersPanel.ts index 99ef58222f1..6767bce8c4f 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanel.ts @@ -27,13 +27,12 @@ import { CollapseAllAction, FilterAction, FilterInputBoxActionItem } from 'vs/wo import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import Messages from 'vs/workbench/parts/markers/common/messages'; import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import FileResultsNavigation from 'vs/workbench/parts/files/browser/fileResultsNavigation'; import { debounceEvent } from 'vs/base/common/event'; import { SimpleFileResourceDragAndDrop } from 'vs/base/parts/tree/browser/treeDnd'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { localize } from 'vs/nls'; @@ -66,9 +65,7 @@ export class MarkersPanel extends Panel { @IEditorGroupService private editorGroupService: IEditorGroupService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IConfigurationService private configurationService: IConfigurationService, - @IContextKeyService private contextKeyService: IContextKeyService, @ITelemetryService telemetryService: ITelemetryService, - @IListService private listService: IListService, @IThemeService themeService: IThemeService, @IActivityService private activityService: IActivityService ) { @@ -215,7 +212,7 @@ export class MarkersPanel extends Panel { const renderer = this.instantiationService.createInstance(Viewer.Renderer); const dnd = new SimpleFileResourceDragAndDrop(obj => obj instanceof Resource ? obj.uri : void 0); let controller = this.instantiationService.createInstance(Controller); - this.tree = new WorkbenchTree(this.treeContainer, { + this.tree = this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new Viewer.DataSource(), renderer, controller, @@ -227,7 +224,7 @@ export class MarkersPanel extends Panel { twistiePixels: 20, ariaLabel: Messages.MARKERS_PANEL_ARIA_LABEL_PROBLEMS_TREE, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService); diff --git a/src/vs/workbench/parts/markers/browser/markersTreeController.ts b/src/vs/workbench/parts/markers/browser/markersTreeController.ts index 4bcde1d43f1..07e688331c8 100644 --- a/src/vs/workbench/parts/markers/browser/markersTreeController.ts +++ b/src/vs/workbench/parts/markers/browser/markersTreeController.ts @@ -75,7 +75,9 @@ export class Controller extends treedefaults.DefaultController { private _getMenuActions(tree: WorkbenchTree): IAction[] { const result: IAction[] = []; - const groups = this.menuService.createMenu(MenuId.ProblemsPanelContext, tree.contextKeyService).getActions(); + const menu = this.menuService.createMenu(MenuId.ProblemsPanelContext, tree.contextKeyService); + const groups = menu.getActions(); + menu.dispose(); for (let group of groups) { const [, actions] = group; diff --git a/src/vs/workbench/parts/output/electron-browser/outputServices.ts b/src/vs/workbench/parts/output/electron-browser/outputServices.ts index dd6381475e9..3fdc76fcf9f 100644 --- a/src/vs/workbench/parts/output/electron-browser/outputServices.ts +++ b/src/vs/workbench/parts/output/electron-browser/outputServices.ts @@ -40,6 +40,7 @@ import { binarySearch } from 'vs/base/common/arrays'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Schemas } from 'vs/base/common/network'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel'; @@ -128,7 +129,8 @@ abstract class AbstractFileOutputChannel extends Disposable { protected modelUpdater: RunOnceScheduler; protected model: ITextModel; readonly file: URI; - protected startOffset: number = 0; + + private startOffset: number = 0; protected endOffset: number = 0; constructor( @@ -201,7 +203,6 @@ abstract class AbstractFileOutputChannel extends Disposable { const lastLine = this.model.getLineCount(); const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine); this.model.applyEdits([EditOperation.insert(new Position(lastLine, lastLineMaxColumn), content)]); - this.endOffset = this.endOffset + new Buffer(content).byteLength; this._onDidAppendedContent.fire(); } } @@ -225,26 +226,33 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out private appendedMessage = ''; private loadingFromFileInProgress: boolean = false; private resettingDelayer: ThrottledDelayer; + private readonly rotatingFilePath: string; constructor( outputChannelIdentifier: IOutputChannelIdentifier, + outputDir: string, modelUri: URI, @IFileService fileService: IFileService, @IModelService modelService: IModelService, @IModeService modeService: IModeService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @IConfigurationService configurationService: IConfigurationService ) { - super(outputChannelIdentifier, modelUri, fileService, modelService, modeService); + super({ ...outputChannelIdentifier, file: URI.file(paths.join(outputDir, `${outputChannelIdentifier.id}.log`)) }, modelUri, fileService, modelService, modeService); // Use one rotating file to check for main file reset - this.outputWriter = new RotatingLogger(this.id, this.file.fsPath, 1024 * 1024 * 30, 1); + const threshold = configurationService.getValue('output.threshold'); + this.outputWriter = new RotatingLogger(this.id, this.file.fsPath, threshold && typeof threshold === 'number' ? threshold : 1024 * 1024 * 30, 1); this.outputWriter.clearFormatters(); + this.rotatingFilePath = `${outputChannelIdentifier.id}.1.log`; this._register(watchOutputDirectory(paths.dirname(this.file.fsPath), logService, (eventType, file) => this.onFileChangedInOutputDirector(eventType, file))); this.resettingDelayer = new ThrottledDelayer(50); } append(message: string): void { + // update end offset always as message is read + this.endOffset = this.endOffset + new Buffer(message).byteLength; if (this.loadingFromFileInProgress) { this.appendedMessage += message; } else { @@ -299,7 +307,7 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannel implements Out private onFileChangedInOutputDirector(eventType: string, fileName: string): void { // Check if rotating file has changed. It changes only when the main file exceeds its limit. - if (`${paths.basename(this.file.fsPath)}.1` === fileName) { + if (this.rotatingFilePath === fileName) { this.resettingDelayer.trigger(() => this.resetModel()); } } @@ -371,7 +379,10 @@ class FileOutputChannel extends AbstractFileOutputChannel implements OutputChann if (this.model) { this.fileService.resolveContent(this.file, { position: this.endOffset }) .then(content => { - this.appendToModel(content.value); + if (content.value) { + this.endOffset = this.endOffset + new Buffer(content.value).byteLength; + this.appendToModel(content.value); + } this.updateInProgress = false; }, () => this.updateInProgress = false); } else { @@ -549,9 +560,8 @@ export class OutputService extends Disposable implements IOutputService, ITextMo if (channelData && channelData.file) { return this.instantiationService.createInstance(FileOutputChannel, channelData, uri); } - const file = URI.file(paths.join(this.outputDir, `${id}.log`)); try { - return this.instantiationService.createInstance(OutputChannelBackedByFile, { id, label: channelData ? channelData.label : '', file }, uri); + return this.instantiationService.createInstance(OutputChannelBackedByFile, { id, label: channelData ? channelData.label : '' }, this.outputDir, uri); } catch (e) { this.logService.error(e); this.telemetryService.publicLog('output.used.bufferedChannel'); diff --git a/src/vs/workbench/parts/performance/electron-browser/performance.contribution.ts b/src/vs/workbench/parts/performance/electron-browser/performance.contribution.ts index 4850d22984f..dcff24f801f 100644 --- a/src/vs/workbench/parts/performance/electron-browser/performance.contribution.ts +++ b/src/vs/workbench/parts/performance/electron-browser/performance.contribution.ts @@ -6,3 +6,4 @@ 'use strict'; import './startupProfiler'; +import './stats'; diff --git a/src/vs/workbench/parts/performance/electron-browser/stats.ts b/src/vs/workbench/parts/performance/electron-browser/stats.ts new file mode 100644 index 00000000000..397935d4179 --- /dev/null +++ b/src/vs/workbench/parts/performance/electron-browser/stats.ts @@ -0,0 +1,126 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + + +interface IRequire { + (...a: any[]): any; + getStats(): ILoaderEvent[]; +} + +declare var require: IRequire; + +/* Copied from loader.ts */ +enum LoaderEventType { + LoaderAvailable = 1, + + BeginLoadingScript = 10, + EndLoadingScriptOK = 11, + EndLoadingScriptError = 12, + + BeginInvokeFactory = 21, + EndInvokeFactory = 22, + + NodeBeginEvaluatingScript = 31, + NodeEndEvaluatingScript = 32, + + NodeBeginNativeRequire = 33, + NodeEndNativeRequire = 34 +} + +interface ILoaderEvent { + type: LoaderEventType; + timestamp: number; + detail: string; +} + +class Tick { + + public readonly duration: number; + public readonly detail: string; + + constructor(public readonly start: ILoaderEvent, public readonly end: ILoaderEvent) { + console.assert(start.detail === end.detail); + + this.duration = this.end.timestamp - this.start.timestamp; + this.detail = start.detail; + } + + static compareUsingStartTimestamp(a: Tick, b: Tick): number { + if (a.start.timestamp < b.start.timestamp) { + return -1; + } else if (a.start.timestamp > b.start.timestamp) { + return 1; + } else { + return 0; + } + } +} + +function getStats(): Map { + + const stats = require.getStats().slice(0).sort((a: ILoaderEvent, b: ILoaderEvent) => { + if (a.detail < b.detail) { + return -1; + } else if (a.detail > b.detail) { + return 1; + } else if (a.type < b.type) { + return -1; + } else if (a.type > b.type) { + return 1; + } else { + return 0; + } + }); + + const ticks = new Map(); + ticks.set(LoaderEventType.BeginLoadingScript, []); + ticks.set(LoaderEventType.BeginInvokeFactory, []); + ticks.set(LoaderEventType.NodeBeginEvaluatingScript, []); + ticks.set(LoaderEventType.NodeBeginNativeRequire, []); + + for (let i = 1; i < stats.length - 1; i++) { + const stat = stats[i]; + const nextStat = stats[i + 1]; + + if (nextStat.type - stat.type > 2) { + //bad?! + break; + } + + i += 1; + ticks.get(stat.type).push(new Tick(stat, nextStat)); + } + + ticks.get(LoaderEventType.BeginLoadingScript).sort(Tick.compareUsingStartTimestamp); + ticks.get(LoaderEventType.BeginInvokeFactory).sort(Tick.compareUsingStartTimestamp); + ticks.get(LoaderEventType.NodeBeginEvaluatingScript).sort(Tick.compareUsingStartTimestamp); + ticks.get(LoaderEventType.NodeBeginNativeRequire).sort(Tick.compareUsingStartTimestamp); + + return ticks; +} + +CommandsRegistry.registerCommand('dev.stats.loader', accessor => { + + const clipboard = accessor.get(IClipboardService); + const env = accessor.get(IEnvironmentService); + + if (!env.performance) { + console.warn('no loader stats, start with `--performance`'); + return; + } + + let value = `Name\tDuration\n`; + for (let tick of getStats().get(LoaderEventType.BeginInvokeFactory)) { + value += `${tick.detail}\t${tick.duration.toPrecision(2)}\n`; + } + console.log(value); + clipboard.writeText(value); +}); diff --git a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts index abb6c66afd1..4171d03edc2 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts @@ -26,7 +26,7 @@ import { SearchWidget } from 'vs/workbench/parts/preferences/browser/preferences import { DefineKeybindingWidget } from 'vs/workbench/parts/preferences/browser/keybindingWidgets'; import { IPreferencesService, IKeybindingsEditor, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_COPY, - KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS + KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS } from 'vs/workbench/parts/preferences/common/preferences'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing'; @@ -40,7 +40,7 @@ import { KeyCode, ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { listHighlightForeground } from 'vs/platform/theme/common/colorRegistry'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; -import { WorkbenchList, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchList } from 'vs/platform/list/browser/listService'; let $ = DOM.$; @@ -104,7 +104,6 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor @IContextMenuService private contextMenuService: IContextMenuService, @IPreferencesService private preferencesService: IPreferencesService, @IKeybindingEditingService private keybindingEditingService: IKeybindingEditingService, - @IListService private listService: IListService, @IContextKeyService private contextKeyService: IContextKeyService, @IMessageService private messageService: IMessageService, @IClipboardService private clipboardService: IClipboardService, @@ -245,6 +244,13 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor return TPromise.as(null); } + copyKeybindingCommand(keybinding: IKeybindingItemEntry): TPromise { + this.selectEntry(keybinding); + this.reportKeybindingAction(KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, keybinding.keybindingItem.command, keybinding.keybindingItem.keybinding); + this.clipboardService.writeText(keybinding.keybindingItem.command); + return TPromise.as(null); + } + search(filter: string): void { this.searchWidget.focus(); } @@ -326,8 +332,8 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor private createList(parent: HTMLElement): void { this.keybindingsListContainer = DOM.append(parent, $('.keybindings-list-container')); - this.keybindingsList = this._register(new WorkbenchList(this.keybindingsListContainer, new Delegate(), [new KeybindingHeaderRenderer(), new KeybindingItemRenderer(this, this.keybindingsService)], - { identityProvider: e => e.id, keyboardSupport: false, mouseSupport: true, ariaLabel: localize('keybindingsLabel', "Keybindings") }, this.contextKeyService, this.listService, this.themeService)); + this.keybindingsList = this._register(this.instantiationService.createInstance(WorkbenchList, this.keybindingsListContainer, new Delegate(), [new KeybindingHeaderRenderer(), new KeybindingItemRenderer(this, this.keybindingsService)], + { identityProvider: e => e.id, keyboardSupport: false, mouseSupport: true, ariaLabel: localize('keybindingsLabel', "Keybindings") })); this._register(this.keybindingsList.onContextMenu(e => this.onContextMenu(e))); this._register(this.keybindingsList.onFocusChange(e => this.onFocusChange(e))); this._register(this.keybindingsList.onDidFocus(() => { @@ -456,6 +462,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor getAnchor: () => e.anchor, getActions: () => TPromise.as([ this.createCopyAction(e.element), + this.createCopyCommandAction(e.element), new Separator(), this.createDefineAction(e.element), this.createRemoveAction(e.element), @@ -526,6 +533,15 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor }; } + private createCopyCommandAction(keybinding: IKeybindingItemEntry): IAction { + return { + label: localize('copyCommandLabel', "Copy Command"), + enabled: true, + id: KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, + run: () => this.copyKeybindingCommand(keybinding) + }; + } + private reportFilteringUsed(filter: string): void { if (filter) { let data = { @@ -644,6 +660,7 @@ class KeybindingItemRenderer implements IRenderer .keybindings-body > .keybindings-list-container .monaco-list-row:nth-child(even):not(.focused):not(.selected):not(:hover), -.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list:not(:focus) .monaco-list-row.focused:nth-child(even):not(.selected):not(:hover), -.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list:not(.focused) .monaco-list-row.focused:nth-child(even):not(.selected):not(:hover) { +.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row.odd:not(.focused):not(.selected):not(:hover), +.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list:not(:focus) .monaco-list-row.focused.odd:not(.selected):not(:hover), +.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list:not(.focused) .monaco-list-row.focused.odd:not(.selected):not(:hover) { background-color: rgba(130, 130, 130, 0.04); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index bc1516350e7..8d937005e84 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -9,8 +9,9 @@ import URI from 'vs/base/common/uri'; import { onUnexpectedError, isPromiseCanceledError, getErrorMessage } from 'vs/base/common/errors'; import * as DOM from 'vs/base/browser/dom'; import { Delayer, ThrottledDelayer } from 'vs/base/common/async'; +import * as arrays from 'vs/base/common/arrays'; import { Dimension, Builder } from 'vs/base/browser/builder'; -import { ArrayNavigator, INavigator } from 'vs/base/common/iterator'; +import { ArrayNavigator } from 'vs/base/common/iterator'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { SideBySideEditorInput, EditorOptions, EditorInput } from 'vs/workbench/common/editor'; @@ -24,7 +25,7 @@ import { CodeEditor } from 'vs/editor/browser/codeEditor'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IPreferencesService, ISettingsGroup, ISetting, IFilterResult, IPreferencesSearchService, - CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, IFilterMetadata, ISearchProvider, ISearchResult + CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, ISettingsEditorModel, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, IFilterMetadata, ISearchProvider, ISearchResult, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING } from 'vs/workbench/parts/preferences/common/preferences'; import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -57,6 +58,8 @@ import { MessageController } from 'vs/editor/contrib/message/messageController'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; +import { IStringDictionary } from 'vs/base/common/collections'; +import { IProgressService } from 'vs/platform/progress/common/progress'; export class PreferencesEditorInput extends SideBySideEditorInput { public static ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -111,18 +114,18 @@ export class PreferencesEditor extends BaseEditor { private delayedFilterLogging: Delayer; private remoteSearchThrottle: ThrottledDelayer; + private _lastReportedFilter: string; - private latestEmptyFilters: string[] = []; private lastFocusedWidget: SearchWidget | SideBySidePreferencesWidget = null; constructor( @IPreferencesService private preferencesService: IPreferencesService, - @IPreferencesSearchService private preferencesSearchService: IPreferencesSearchService, @ITelemetryService telemetryService: ITelemetryService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IContextKeyService private contextKeyService: IContextKeyService, @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService + @IThemeService themeService: IThemeService, + @IProgressService private progressService: IProgressService ) { super(PreferencesEditor.ID, telemetryService, themeService); this.defaultSettingsEditorContextKey = CONTEXT_SETTINGS_EDITOR.bindTo(this.contextKeyService); @@ -152,7 +155,7 @@ export class PreferencesEditor extends BaseEditor { this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget)); this._register(this.sideBySidePreferencesWidget.onDidSettingsTargetChange(target => this.switchSettings(target))); - this.preferencesRenderers = this._register(new PreferencesRenderersController(this.preferencesSearchService, this.telemetryService)); + this.preferencesRenderers = this._register(this.instantiationService.createInstance(PreferencesRenderersController)); this._register(this.preferencesRenderers.onDidFilterResultsCountChange(count => this.showSearchResultsMessage(count))); } @@ -175,6 +178,10 @@ export class PreferencesEditor extends BaseEditor { } } + public editFocusedPreference(): void { + this.preferencesRenderers.editFocusedPreference(); + } + public setInput(newInput: PreferencesEditorInput, options?: EditorOptions): TPromise { this.defaultSettingsEditorContextKey.set(true); const oldInput = this.input; @@ -237,16 +244,28 @@ export class PreferencesEditor extends BaseEditor { } private onInputChanged(): void { - this.triggerThrottledSearch(); - this.localFilterPreferences(); + const query = this.searchWidget.getValue().trim(); + this.delayedFilterLogging.cancel(); + this.progressService.showWhile(TPromise.join([ + this.preferencesRenderers.localFilterPreferences(query), + this.triggerThrottledSearch(query) + ]), 250).then(() => { + const result = this.preferencesRenderers.lastFilterResult; + if (result) { + this.delayedFilterLogging.trigger(() => this.reportFilteringUsed( + query, + result.defaultSettingsGroupCounts, + result.metadata)); + } + }); } - private triggerThrottledSearch(): void { - if (this.searchWidget.getValue()) { - this.remoteSearchThrottle.trigger(() => this.remoteSearchPreferences()); + private triggerThrottledSearch(query: string): TPromise { + if (query) { + return this.remoteSearchThrottle.trigger(() => this.preferencesRenderers.remoteSearchPreferences(query)); } else { // When clearing the input, update immediately to clear it - this.remoteSearchPreferences(); + return this.preferencesRenderers.remoteSearchPreferences(query); } } @@ -267,115 +286,73 @@ export class PreferencesEditor extends BaseEditor { }); } - private remoteSearchPreferences(): TPromise { - const query = this.searchWidget.getValue().trim(); - return this.preferencesRenderers.remoteSearchPreferences(query).then(result => { - this.onSearchResult(query, result); - }, onUnexpectedError); - } - - private localFilterPreferences(): TPromise { - const query = this.searchWidget.getValue().trim(); - return this.preferencesRenderers.localFilterPreferences(query).then(result => { - this.onSearchResult(query, result); - }, onUnexpectedError); - } - - private onSearchResult(filter: string, result: { count: number, metadata: IFilterMetadata }): void { - if (result) { - this.showSearchResultsMessage(result.count); - if (result.count === 0) { - this.latestEmptyFilters.push(filter); - } - - this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(filter, result.metadata)); - } - } - - private showSearchResultsMessage(count: number): void { - if (this.searchWidget.getValue()) { - if (count === 0) { - this.searchWidget.showMessage(nls.localize('noSettingsFound', "No Results"), count); - } else if (count === 1) { - this.searchWidget.showMessage(nls.localize('oneSettingFound', "1 Setting matched"), count); + private showSearchResultsMessage(count: IPreferencesCount): void { + const countValue = count.count; + if (count.target) { + this.sideBySidePreferencesWidget.setResultCount(count.target, count.count); + } else if (this.searchWidget.getValue()) { + if (countValue === 0) { + this.searchWidget.showMessage(nls.localize('noSettingsFound', "No Results"), countValue); + } else if (countValue === 1) { + this.searchWidget.showMessage(nls.localize('oneSettingFound', "1 Setting Found"), countValue); } else { - this.searchWidget.showMessage(nls.localize('settingsFound', "{0} Settings matched", count), count); + this.searchWidget.showMessage(nls.localize('settingsFound', "{0} Settings Found", countValue), countValue); } } else { - this.searchWidget.showMessage(nls.localize('totalSettingsMessage', "Total {0} Settings", count), count); + this.searchWidget.showMessage(nls.localize('totalSettingsMessage', "Total {0} Settings", countValue), countValue); } } - private reportFilteringUsed(filter: string, metadata?: IFilterMetadata): void { - if (filter) { + private reportFilteringUsed(filter: string, counts: IStringDictionary, metadata?: IStringDictionary): void { + if (filter && filter !== this._lastReportedFilter) { + let durations: any; + if (metadata) { + durations = Object.create(null); + Object.keys(metadata).forEach(key => durations[key] = metadata[key].duration); + } + let data = { filter, - emptyFilters: this.getLatestEmptyFiltersForTelemetry(), - fuzzy: !!metadata, - duration: metadata ? metadata.duration : undefined, - context: metadata ? metadata.context : undefined + durations, + counts }; - this.latestEmptyFilters = []; /* __GDPR__ "defaultSettings.filter" : { "filter": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "emptyFilters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "fuzzy" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "context" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "durations" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "counts" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ this.telemetryService.publicLog('defaultSettings.filter', data); + this._lastReportedFilter = filter; } } - - /** - * Put a rough limit on the size of the telemetry data, since otherwise it could be an unbounded large amount - * of data. 8192 is the max size of a property value. This is rough since that probably includes ""s, etc. - */ - private getLatestEmptyFiltersForTelemetry(): string[] { - let cumulativeSize = 0; - return this.latestEmptyFilters.filter(filterText => (cumulativeSize += filterText.length) <= 8192); - } } -class SettingsNavigator implements INavigator { - - private iterator: ArrayNavigator; - - constructor(settings: ISetting[]) { - this.iterator = new ArrayNavigator(settings); - } +class SettingsNavigator extends ArrayNavigator { public next(): ISetting { - return this.iterator.next() || this.iterator.first(); + return super.next() || super.first(); } public previous(): ISetting { - return this.iterator.previous() || this.iterator.last(); + return super.previous() || super.last(); } - public parent(): ISetting { - return this.iterator.parent(); - } - - public first(): ISetting { - return this.iterator.first(); - } - - public last(): ISetting { - return this.iterator.last(); - } - - public current(): ISetting { - return this.iterator.current(); + public reset(): void { + this.index = this.start - 1; } } interface IFilterOrSearchResult { + defaultSettingsGroupCounts: IStringDictionary; + metadata: IStringDictionary; +} + +interface IPreferencesCount { + target?: SettingsTarget; count: number; - metadata: IFilterMetadata; } class PreferencesRenderersController extends Disposable { @@ -387,22 +364,30 @@ class PreferencesRenderersController extends Disposable { private _editablePreferencesRendererDisposables: IDisposable[] = []; private _settingsNavigator: SettingsNavigator; - private _filtersInProgress: TPromise[]; + private _remoteFilterInProgress: TPromise; + private _prefsModelsForSearch = new Map(); private _currentLocalSearchProvider: ISearchProvider; private _currentRemoteSearchProvider: ISearchProvider; private _lastQuery: string; + private _lastFilterResult: IFilterOrSearchResult; - private _onDidFilterResultsCountChange: Emitter = this._register(new Emitter()); - public onDidFilterResultsCountChange: Event = this._onDidFilterResultsCountChange.event; + private _onDidFilterResultsCountChange: Emitter = this._register(new Emitter()); + public onDidFilterResultsCountChange: Event = this._onDidFilterResultsCountChange.event; constructor( - private preferencesSearchService: IPreferencesSearchService, - private telemetryService: ITelemetryService + @IPreferencesSearchService private preferencesSearchService: IPreferencesSearchService, + @ITelemetryService private telemetryService: ITelemetryService, + @IPreferencesService private preferencesService: IPreferencesService, + @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(); } + get lastFilterResult(): IFilterOrSearchResult { + return this._lastFilterResult; + } + get defaultPreferencesRenderer(): IPreferencesRenderer { return this._defaultPreferencesRenderer; } @@ -418,7 +403,7 @@ class PreferencesRenderersController extends Disposable { this._defaultPreferencesRendererDisposables = dispose(this._defaultPreferencesRendererDisposables); if (this._defaultPreferencesRenderer) { - this._defaultPreferencesRenderer.onUpdatePreference(({ key, value, source, index }) => this._updatePreference(key, value, source, index, this._editablePreferencesRenderer), this, this._defaultPreferencesRendererDisposables); + this._defaultPreferencesRenderer.onUpdatePreference(({ key, value, source }) => this._updatePreference(key, value, source, this._editablePreferencesRenderer), this, this._defaultPreferencesRendererDisposables); this._defaultPreferencesRenderer.onFocusPreference(preference => this._focusPreference(preference, this._editablePreferencesRenderer), this, this._defaultPreferencesRendererDisposables); this._defaultPreferencesRenderer.onClearFocusPreference(preference => this._clearFocus(preference, this._editablePreferencesRenderer), this, this._defaultPreferencesRendererDisposables); } @@ -436,41 +421,110 @@ class PreferencesRenderersController extends Disposable { } } - async _onEditableContentDidChange(): TPromise { + private async _onEditableContentDidChange(): TPromise { await this.localFilterPreferences(this._lastQuery, true); await this.remoteSearchPreferences(this._lastQuery, true); } - remoteSearchPreferences(query: string, updateCurrentResults?: boolean): TPromise { - this._currentRemoteSearchProvider = (updateCurrentResults && this._currentRemoteSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query); - return this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results")); - } - - localFilterPreferences(query: string, updateCurrentResults?: boolean): TPromise { - this._currentLocalSearchProvider = (updateCurrentResults && this._currentLocalSearchProvider) || this.preferencesSearchService.getLocalSearchProvider(query); - return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results")); - } - - filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string): TPromise { - this._lastQuery = query; - if (this._filtersInProgress) { + remoteSearchPreferences(query: string, updateCurrentResults?: boolean): TPromise { + if (this._remoteFilterInProgress && this._remoteFilterInProgress.cancel) { // Resolved/rejected promises have no .cancel() - this._filtersInProgress.forEach(p => p.cancel && p.cancel()); + this._remoteFilterInProgress.cancel(); } - this._filtersInProgress = [ - this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel), - this._filterOrSearchPreferences(query, this.editablePreferencesRenderer, searchProvider, groupId, groupLabel)]; + this._currentRemoteSearchProvider = (updateCurrentResults && this._currentRemoteSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query); - return TPromise.join(this._filtersInProgress).then(results => { - this._filtersInProgress = null; + this._remoteFilterInProgress = this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results"), 1, updateCurrentResults); + + return this._remoteFilterInProgress.then(() => { + this._remoteFilterInProgress = null; + }, err => { + if (isPromiseCanceledError(err)) { + return null; + } else { + onUnexpectedError(err); + } + }); + } + + localFilterPreferences(query: string, updateCurrentResults?: boolean): TPromise { + if (this._settingsNavigator) { + this._settingsNavigator.reset(); + } + + this._currentLocalSearchProvider = (updateCurrentResults && this._currentLocalSearchProvider) || this.preferencesSearchService.getLocalSearchProvider(query); + return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results"), 0, updateCurrentResults); + } + + private filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number, editableContentOnly?: boolean): TPromise { + this._lastQuery = query; + + const filterPs = []; + if (!editableContentOnly) { + filterPs.push( + this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel, groupOrder)); + } + + filterPs.push(this._filterOrSearchPreferences(query, this.editablePreferencesRenderer, searchProvider, groupId, groupLabel, groupOrder), + this.updateSettingsTargetCounts(query, searchProvider, groupId, groupLabel, groupOrder)); + + return TPromise.join(filterPs).then(results => { const [defaultFilterResult, editableFilterResult] = results; - const count = this.consolidateAndUpdate(defaultFilterResult, editableFilterResult); - return { count, metadata: defaultFilterResult && defaultFilterResult.metadata }; + this.consolidateAndUpdate(defaultFilterResult, editableFilterResult); + const result = { + metadata: defaultFilterResult && defaultFilterResult.metadata, + defaultSettingsGroupCounts: defaultFilterResult && this._countById(defaultFilterResult.filteredGroups) + }; + + this._lastFilterResult = result; }); } + private updateSettingsTargetCounts(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number): TPromise { + const searchPs = [ + this.searchSettingsTarget(searchProvider, ConfigurationTarget.WORKSPACE, groupId, groupLabel, groupOrder), + this.searchSettingsTarget(searchProvider, ConfigurationTarget.USER, groupId, groupLabel, groupOrder) + ]; + + for (const folder of this.workspaceContextService.getWorkspace().folders) { + const folderSettingsResource = this.preferencesService.getFolderSettingsResource(folder.uri); + searchPs.push(this.searchSettingsTarget(searchProvider, folderSettingsResource, groupId, groupLabel, groupOrder)); + } + + + return TPromise.join(searchPs).then(() => { }); + } + + private searchSettingsTarget(provider: ISearchProvider, target: SettingsTarget, groupId: string, groupLabel: string, groupOrder: number): TPromise { + return this.getPreferencesEditorModel(target).then(model => { + return this._filterOrSearchPreferencesModel('', model, provider, groupId, groupLabel, groupOrder); + }).then(result => { + const count = result ? this._flatten(result.filteredGroups).length : 0; + this._onDidFilterResultsCountChange.fire({ target, count }); + }, err => { + if (!isPromiseCanceledError(err)) { + return TPromise.wrapError(err); + } + + return null; + }); + } + + private async getPreferencesEditorModel(target: SettingsTarget): TPromise { + const resource = target === ConfigurationTarget.USER ? this.preferencesService.userSettingsResource : + target === ConfigurationTarget.WORKSPACE ? this.preferencesService.workspaceSettingsResource : + target; + + const targetKey = resource.toString(); + if (!this._prefsModelsForSearch.has(targetKey)) { + const model = this._register(await this.preferencesService.createPreferencesEditorModel(resource)); + this._prefsModelsForSearch.set(targetKey, model); + } + + return this._prefsModelsForSearch.get(targetKey); + } + focusNextPreference(forward: boolean = true) { if (!this._settingsNavigator) { return; @@ -481,55 +535,91 @@ class PreferencesRenderersController extends Disposable { this._focusPreference(setting, this._editablePreferencesRenderer); } - private _filterOrSearchPreferences(filter: string, preferencesRenderer: IPreferencesRenderer, provider: ISearchProvider, groupId: string, groupLabel: string): TPromise { - if (preferencesRenderer) { - const model = preferencesRenderer.preferencesModel; - const searchP = provider ? provider.searchModel(model) : TPromise.wrap(null); - return searchP - .then(null, err => { - if (isPromiseCanceledError(err)) { - return null; - } else { - /* __GDPR__ - "defaultSettings.searchError" : { - "message": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - const message = getErrorMessage(err); - this.telemetryService.publicLog('defaultSettings.searchError', { message }); - return null; - } - }) - .then(searchResult => { - const filterResult = searchResult ? - model.updateResultGroup(groupId, { - id: groupId, - label: groupLabel, - result: searchResult - }) : - model.updateResultGroup(groupId, null); - - if (filterResult) { - filterResult.query = filter; - } - - preferencesRenderer.filterPreferences(filterResult); - return filterResult; - }); + editFocusedPreference(): void { + if (!this._settingsNavigator || !this._settingsNavigator.current()) { + return; } - return TPromise.wrap(null); + const setting = this._settingsNavigator.current(); + const shownInEditableRenderer = this._editablePreferencesRenderer.editPreference(setting); + if (!shownInEditableRenderer) { + this.defaultPreferencesRenderer.editPreference(setting); + } } - private consolidateAndUpdate(defaultFilterResult: IFilterResult, editableFilterResult: IFilterResult): number { + private _filterOrSearchPreferences(filter: string, preferencesRenderer: IPreferencesRenderer, provider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number): TPromise { + if (!preferencesRenderer) { + return TPromise.wrap(null); + } + + const model = preferencesRenderer.preferencesModel; + return this._filterOrSearchPreferencesModel(filter, model, provider, groupId, groupLabel, groupOrder).then(filterResult => { + preferencesRenderer.filterPreferences(filterResult); + return filterResult; + }); + } + + private _filterOrSearchPreferencesModel(filter: string, model: ISettingsEditorModel, provider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number): TPromise { + const searchP = provider ? provider.searchModel(model) : TPromise.wrap(null); + return searchP + .then(null, err => { + if (isPromiseCanceledError(err)) { + return TPromise.wrapError(err); + } else { + /* __GDPR__ + "defaultSettings.searchError" : { + "message": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + const message = getErrorMessage(err).trim(); + if (message) { + // Empty message = any generic network error + this.telemetryService.publicLog('defaultSettings.searchError', { message }); + } + return null; + } + }) + .then(searchResult => { + const filterResult = searchResult ? + model.updateResultGroup(groupId, { + id: groupId, + label: groupLabel, + result: searchResult, + order: groupOrder + }) : + model.updateResultGroup(groupId, null); + + if (filterResult) { + filterResult.query = filter; + } + + return filterResult; + }); + } + + private consolidateAndUpdate(defaultFilterResult: IFilterResult, editableFilterResult: IFilterResult): void { const defaultPreferencesFilteredGroups = defaultFilterResult ? defaultFilterResult.filteredGroups : this._getAllPreferences(this._defaultPreferencesRenderer); const editablePreferencesFilteredGroups = editableFilterResult ? editableFilterResult.filteredGroups : this._getAllPreferences(this._editablePreferencesRenderer); const consolidatedSettings = this._consolidateSettings(editablePreferencesFilteredGroups, defaultPreferencesFilteredGroups); - this._settingsNavigator = new SettingsNavigator(this._lastQuery ? consolidatedSettings : []); - const count = consolidatedSettings.length; - this._onDidFilterResultsCountChange.fire(count); - return count; + // Maintain the current navigation position when updating SettingsNavigator + const current = this._settingsNavigator && this._settingsNavigator.current(); + const navigatorSettings = this._lastQuery ? consolidatedSettings : []; + const currentIndex = current ? + arrays.firstIndex(navigatorSettings, s => s.key === current.key) : + -1; + + this._settingsNavigator = new SettingsNavigator(navigatorSettings, Math.max(currentIndex, 0)); + + if (currentIndex >= 0) { + this._settingsNavigator.next(); + const newCurrent = this._settingsNavigator.current(); + this._focusPreference(newCurrent, this._defaultPreferencesRenderer); + this._focusPreference(newCurrent, this._editablePreferencesRenderer); + } + + const totalCount = consolidatedSettings.length; + this._onDidFilterResultsCountChange.fire({ count: totalCount }); } private _getAllPreferences(preferencesRenderer: IPreferencesRenderer): ISettingsGroup[] { @@ -548,15 +638,15 @@ class PreferencesRenderersController extends Disposable { } } - private _updatePreference(key: string, value: any, source: ISetting, index: number, preferencesRenderer: IPreferencesRenderer): void { + private _updatePreference(key: string, value: any, source: ISetting, preferencesRenderer: IPreferencesRenderer): void { if (preferencesRenderer) { - preferencesRenderer.updatePreference(key, value, source, index); + preferencesRenderer.updatePreference(key, value, source); } } private _consolidateSettings(editableSettingsGroups: ISettingsGroup[], defaultSettingsGroups: ISettingsGroup[]): ISetting[] { - const editableSettings = this._flatten(editableSettingsGroups); - const defaultSettings = this._flatten(defaultSettingsGroups).filter(secondarySetting => editableSettings.every(primarySetting => primarySetting.key !== secondarySetting.key)); + const defaultSettings = this._flatten(defaultSettingsGroups); + const editableSettings = this._flatten(editableSettingsGroups).filter(secondarySetting => defaultSettings.every(primarySetting => primarySetting.key !== secondarySetting.key)); return [...defaultSettings, ...editableSettings]; } @@ -571,6 +661,21 @@ class PreferencesRenderersController extends Disposable { return settings; } + private _countById(settingsGroups: ISettingsGroup[]): IStringDictionary { + const result = {}; + + for (const group of settingsGroups) { + let i = 0; + for (const section of group.sections) { + i += section.settings.length; + } + + result[group.id] = i; + } + + return result; + } + public dispose(): void { dispose(this._defaultPreferencesRendererDisposables); dispose(this._editablePreferencesRendererDisposables); @@ -663,6 +768,10 @@ class SideBySidePreferencesWidget extends Widget { }); } + public setResultCount(settingsTarget: SettingsTarget, count: number): void { + this.settingsTargetsWidget.setResultCount(settingsTarget, count); + } + public layout(dimension: Dimension): void { this.dimension = dimension; this.sash.setDimenesion(this.dimension); @@ -909,7 +1018,8 @@ abstract class AbstractSettingsEditorContribution extends Disposable implements private _hasAssociatedPreferencesModelChanged(associatedPreferencesModelUri: URI): TPromise { return this.preferencesRendererCreationPromise.then(preferencesRenderer => { - return !(preferencesRenderer && preferencesRenderer.associatedPreferencesModel && preferencesRenderer.associatedPreferencesModel.uri.toString() === associatedPreferencesModelUri.toString()); + const associatedPreferencesModel = preferencesRenderer.getAssociatedPreferencesModel(); + return !(preferencesRenderer && associatedPreferencesModel && associatedPreferencesModel.uri.toString() === associatedPreferencesModelUri.toString()); }); } @@ -918,10 +1028,11 @@ abstract class AbstractSettingsEditorContribution extends Disposable implements .then(associatedPreferencesEditorModel => { return this.preferencesRendererCreationPromise.then(preferencesRenderer => { if (preferencesRenderer) { - if (preferencesRenderer.associatedPreferencesModel) { - preferencesRenderer.associatedPreferencesModel.dispose(); + const associatedPreferencesModel = preferencesRenderer.getAssociatedPreferencesModel(); + if (associatedPreferencesModel) { + associatedPreferencesModel.dispose(); } - preferencesRenderer.associatedPreferencesModel = associatedPreferencesEditorModel; + preferencesRenderer.setAssociatedPreferencesModel(associatedPreferencesEditorModel); } return preferencesRenderer; }); @@ -932,8 +1043,9 @@ abstract class AbstractSettingsEditorContribution extends Disposable implements if (this.preferencesRendererCreationPromise) { this.preferencesRendererCreationPromise.then(preferencesRenderer => { if (preferencesRenderer) { - if (preferencesRenderer.associatedPreferencesModel) { - preferencesRenderer.associatedPreferencesModel.dispose(); + const associatedPreferencesModel = preferencesRenderer.getAssociatedPreferencesModel(); + if (associatedPreferencesModel) { + associatedPreferencesModel.dispose(); } preferencesRenderer.preferencesModel.dispose(); preferencesRenderer.dispose(); @@ -1140,3 +1252,20 @@ const focusPreviousSearchResultCommand = new FocusPreviousSearchResultCommand({ kbOpts: { primary: KeyMod.Shift | KeyCode.Enter } }); KeybindingsRegistry.registerCommandAndKeybindingRule(focusPreviousSearchResultCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib())); + +class EditFocusedSettingCommand extends SettingsCommand { + + public runCommand(accessor: ServicesAccessor, args: any): void { + const preferencesEditor = this.getPreferencesEditor(accessor); + if (preferencesEditor) { + preferencesEditor.editFocusedPreference(); + } + } + +} +const editFocusedSettingCommand = new EditFocusedSettingCommand({ + id: SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, + precondition: CONTEXT_SETTINGS_SEARCH_FOCUS, + kbOpts: { primary: KeyMod.CtrlCmd | KeyCode.US_DOT } +}); +KeybindingsRegistry.registerCommandAndKeybindingRule(editFocusedSettingCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib())); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 1ae612e71fd..ebfb9efbaae 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -6,8 +6,10 @@ import { TPromise } from 'vs/base/common/winjs.base'; import * as nls from 'vs/nls'; import { Delayer } from 'vs/base/common/async'; +import * as arrays from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Position } from 'vs/editor/common/core/position'; import { IAction } from 'vs/base/common/actions'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import Event, { Emitter } from 'vs/base/common/event'; @@ -16,7 +18,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { Range, IRange } from 'vs/editor/common/core/range'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IScoredResults, IWorkbenchSettingsConfiguration } from 'vs/workbench/parts/preferences/common/preferences'; +import { IPreferencesService, ISettingsGroup, ISetting, IPreferencesEditorModel, IFilterResult, ISettingsEditorModel, IScoredResults, IWorkbenchSettingsConfiguration, IExtensionSetting } from 'vs/workbench/parts/preferences/common/preferences'; import { SettingsEditorModel, DefaultSettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView'; @@ -33,20 +35,26 @@ import { MarkdownString } from 'vs/base/common/htmlContent'; import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextModel, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/model'; +import { CodeLensProviderRegistry, CodeLensProvider, ICodeLensSymbol } from 'vs/editor/common/modes'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { getDomNodePagePosition } from 'vs/base/browser/dom'; export interface IPreferencesRenderer extends IDisposable { - preferencesModel: IPreferencesEditorModel; - associatedPreferencesModel: IPreferencesEditorModel; + readonly preferencesModel: IPreferencesEditorModel; + + getAssociatedPreferencesModel(): IPreferencesEditorModel; + setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel): void; onFocusPreference: Event; onClearFocusPreference: Event; - onUpdatePreference?: Event<{ key: string, value: any, source: T, index: number }>; + onUpdatePreference?: Event<{ key: string, value: any, source: T }>; render(): void; - updatePreference(key: string, value: any, source: T, index: number): void; + updatePreference(key: string, value: any, source: T): void; focusPreference(setting: T): void; clearFocus(setting: T): void; filterPreferences(filterResult: IFilterResult): void; + editPreference(setting: T): boolean; } export class UserSettingsRenderer extends Disposable implements IPreferencesRenderer { @@ -55,7 +63,7 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend private editSettingActionRenderer: EditSettingRenderer; private highlightMatchesRenderer: HighlightMatchesRenderer; private modelChangeDelayer: Delayer = new Delayer(200); - private _associatedPreferencesModel: IPreferencesEditorModel; + private associatedPreferencesModel: IPreferencesEditorModel; private _onFocusPreference: Emitter = new Emitter(); public readonly onFocusPreference: Event = this._onFocusPreference.event; @@ -75,18 +83,18 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference)); this.highlightMatchesRenderer = this._register(instantiationService.createInstance(HighlightMatchesRenderer, editor)); this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.preferencesModel, this.settingHighlighter)); - this._register(this.editSettingActionRenderer.onUpdateSetting(({ key, value, source, index }) => this.updatePreference(key, value, source, index, true))); + this._register(this.editSettingActionRenderer.onUpdateSetting(({ key, value, source }) => this.updatePreference(key, value, source, true))); this._register(this.editor.getModel().onDidChangeContent(() => this.modelChangeDelayer.trigger(() => this.onModelChanged()))); this.createHeader(); } - public get associatedPreferencesModel(): IPreferencesEditorModel { - return this._associatedPreferencesModel; + public getAssociatedPreferencesModel(): IPreferencesEditorModel { + return this.associatedPreferencesModel; } - public set associatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel) { - this._associatedPreferencesModel = associatedPreferencesModel; + public setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel): void { + this.associatedPreferencesModel = associatedPreferencesModel; this.editSettingActionRenderer.associatedPreferencesModel = associatedPreferencesModel; } @@ -101,16 +109,15 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend } } - public updatePreference(key: string, value: any, source: ISetting, index: number, fromEditableSettings?: boolean): void { + public updatePreference(key: string, value: any, source: IIndexedSetting, fromEditableSettings?: boolean): void { const data = { userConfigurationKeys: [key] }; if (this.filterResult) { data['query'] = this.filterResult.query; - data['fuzzy'] = !!this.filterResult.metadata; - data['duration'] = this.filterResult.metadata && this.filterResult.metadata.duration; - data['index'] = index; + data['index'] = source.index; + data['groupId'] = source.groupId; data['editableSide'] = !!fromEditableSettings; } @@ -118,9 +125,8 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend "defaultSettingsActions.copySetting" : { "userConfigurationKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "query" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "fuzzy" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "index" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "editableSide" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ @@ -183,6 +189,10 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend public clearFocus(setting: ISetting): void { this.settingHighlighter.clear(true); } + + public editPreference(setting: ISetting): boolean { + return this.editSettingActionRenderer.activateOnSetting(setting); + } } export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer { @@ -205,10 +215,15 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I this._register(new SettingsHeaderWidget(this.editor, '')).setMessage(nls.localize('emptyWorkspaceSettingsHeader', "Place your settings here to overwrite the User Settings.")); } + public setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel): void { + super.setAssociatedPreferencesModel(associatedPreferencesModel); + this.workspaceConfigurationRenderer.render(this.getAssociatedPreferencesModel()); + } + public render(): void { super.render(); this.unsupportedSettingsRenderer.render(); - this.workspaceConfigurationRenderer.render(); + this.workspaceConfigurationRenderer.render(this.getAssociatedPreferencesModel()); } } @@ -247,10 +262,11 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR private editSettingActionRenderer: EditSettingRenderer; private feedbackWidgetRenderer: FeedbackWidgetRenderer; private bracesHidingRenderer: BracesHidingRenderer; + private extensionCodelensRenderer: ExtensionCodelensRenderer; private filterResult: IFilterResult; - private _onUpdatePreference: Emitter<{ key: string, value: any, source: ISetting, index: number }> = new Emitter<{ key: string, value: any, source: ISetting, index: number }>(); - public readonly onUpdatePreference: Event<{ key: string, value: any, source: ISetting, index: number }> = this._onUpdatePreference.event; + private _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); + public readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event; private _onFocusPreference: Emitter = new Emitter(); public readonly onFocusPreference: Event = this._onFocusPreference.event; @@ -271,17 +287,18 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR this.feedbackWidgetRenderer = this._register(instantiationService.createInstance(FeedbackWidgetRenderer, editor)); this.bracesHidingRenderer = this._register(instantiationService.createInstance(BracesHidingRenderer, editor, preferencesModel)); this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, this.bracesHidingRenderer])); + this.extensionCodelensRenderer = this._register(instantiationService.createInstance(ExtensionCodelensRenderer, editor)); this._register(this.editSettingActionRenderer.onUpdateSetting(e => this._onUpdatePreference.fire(e))); this._register(this.settingsGroupTitleRenderer.onHiddenAreasChanged(() => this.hiddenAreasRenderer.render())); this._register(preferencesModel.onDidChangeGroups(() => this.render())); } - public get associatedPreferencesModel(): IPreferencesEditorModel { + public getAssociatedPreferencesModel(): IPreferencesEditorModel { return this._associatedPreferencesModel; } - public set associatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel) { + public setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel): void { this._associatedPreferencesModel = associatedPreferencesModel; this.editSettingActionRenderer.associatedPreferencesModel = associatedPreferencesModel; } @@ -298,14 +315,16 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR public filterPreferences(filterResult: IFilterResult): void { this.filterResult = filterResult; + if (filterResult) { this.filteredMatchesRenderer.render(filterResult, this.preferencesModel.settingsGroups); - this.settingsGroupTitleRenderer.render(filterResult.filteredGroups); + this.settingsGroupTitleRenderer.render(null); this.feedbackWidgetRenderer.render(filterResult); this.settingsHeaderRenderer.render(filterResult); this.settingHighlighter.clear(true); this.bracesHidingRenderer.render(filterResult, this.preferencesModel.settingsGroups); this.editSettingActionRenderer.render(filterResult.filteredGroups, this._associatedPreferencesModel); + this.extensionCodelensRenderer.render(filterResult); } else { this.settingHighlighter.clear(true); this.filteredMatchesRenderer.render(null, this.preferencesModel.settingsGroups); @@ -315,6 +334,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR this.settingsGroupTitleRenderer.showGroup(0); this.bracesHidingRenderer.render(null, this.preferencesModel.settingsGroups); this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel); + this.extensionCodelensRenderer.render(null); } this.hiddenAreasRenderer.render(); @@ -364,6 +384,10 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR public updatePreference(key: string, value: any, source: ISetting): void { } + + public editPreference(setting: ISetting): boolean { + return this.editSettingActionRenderer.activateOnSetting(setting); + } } export interface HiddenAreasProvider { @@ -394,12 +418,12 @@ export class BracesHidingRenderer extends Disposable implements HiddenAreasProvi } ]; - const hideBraces = group => { + const hideBraces = (group: ISettingsGroup, hideExtraLine?: boolean) => { // Opening curly brace hiddenAreas.push({ startLineNumber: group.range.startLineNumber - 3, startColumn: 1, - endLineNumber: group.range.startLineNumber - 3, + endLineNumber: group.range.startLineNumber - (hideExtraLine ? 1 : 3), endColumn: 1 }); @@ -412,9 +436,9 @@ export class BracesHidingRenderer extends Disposable implements HiddenAreasProvi }); }; - this._settingsGroups.forEach(hideBraces); + this._settingsGroups.forEach(g => hideBraces(g)); if (this._result) { - this._result.filteredGroups.forEach(hideBraces); + this._result.filteredGroups.forEach((g, i) => hideBraces(g, true)); } // Closing square brace @@ -607,28 +631,38 @@ export class FeedbackWidgetRenderer extends Disposable { } const result = this._currentResult; - const actualResults = result.metadata.scoredResults; - const actualResultNames = Object.keys(actualResults); + const metadata = result.metadata['nlpResult']; // Feedback only on nlpResult set for now + const actualResults = metadata ? metadata.scoredResults : {}; + const actualResultIds = Object.keys(actualResults); const feedbackQuery: any = {}; feedbackQuery['comment'] = FeedbackWidgetRenderer.DEFAULT_COMMENT_TEXT; feedbackQuery['queryString'] = result.query; - feedbackQuery['resultScores'] = {}; - actualResultNames.forEach(settingKey => { - feedbackQuery['resultScores'][settingKey] = 10; + feedbackQuery['resultScores'] = []; + actualResultIds.forEach(settingId => { + feedbackQuery['resultScores'].push({ + packageID: actualResults[settingId].packageId, + key: actualResults[settingId].key, + score: 10 + }); }); feedbackQuery['alts'] = []; + const groupCountsText = result.filteredGroups + .map(group => `// ${group.id}: ${group.sections[0].settings.length}`) + .join('\n'); + const contents = FeedbackWidgetRenderer.INSTRUCTION_TEXT + '\n' + JSON.stringify(feedbackQuery, undefined, ' ') + '\n\n' + - actualResultNames.map(name => `// ${name}: ${result.metadata.scoredResults[name]}`).join('\n'); + this.getScoreText(actualResults) + '\n\n' + + groupCountsText + '\n'; this.editorService.openEditor({ contents, language: 'jsonc' }, /*sideBySide=*/true).then(feedbackEditor => { const sendFeedbackWidget = this._register(this.instantiationService.createInstance(FloatingClickWidget, feedbackEditor.getControl(), 'Send feedback', null)); sendFeedbackWidget.render(); this._register(sendFeedbackWidget.onClick(() => { - this.sendFeedback(feedbackEditor.getControl() as ICodeEditor, result, result.metadata.scoredResults).then(() => { + this.sendFeedback(feedbackEditor.getControl() as ICodeEditor, result, metadata.scoredResults).then(() => { sendFeedbackWidget.dispose(); this.messageService.show(Severity.Info, 'Feedback sent successfully'); }, err => { @@ -638,6 +672,17 @@ export class FeedbackWidgetRenderer extends Disposable { }); } + private getScoreText(results?: IScoredResults): string { + if (!results) { + return ''; + } + + return Object.keys(results) + .map(name => { + return `// ${results[name].key}: ${results[name].score}`; + }).join('\n'); + } + private sendFeedback(feedbackEditor: ICodeEditor, result: IFilterResult, actualResults: IScoredResults): TPromise { const model = feedbackEditor.getModel(); const expectedQueryLines = model.getLinesContent() @@ -667,11 +712,9 @@ export class FeedbackWidgetRenderer extends Disposable { "settingsSearchResultFeedback" : { "query" : { "classification": "CustomContent", "purpose": "FeatureInsight" }, "userComment" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, - "actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "expectedResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "url" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, + "actualResults" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "timestamp" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ return this.telemetryService.publicLog('settingsSearchResultFeedback', { @@ -679,9 +722,7 @@ export class FeedbackWidgetRenderer extends Disposable { userComment, actualResults, expectedResults: expectedQuery.resultScores, - url: result.metadata.remoteUrl, - duration: result.metadata.duration, - timestamp: result.metadata.timestamp, + duration: result.metadata['nlpResult'].duration, buildNumber: this.environmentService.settingsSearchBuildId, alts, autoIngest @@ -828,8 +869,54 @@ export class HighlightMatchesRenderer extends Disposable { } } -interface IIndexedSetting extends ISetting { +export class ExtensionCodelensRenderer extends Disposable implements CodeLensProvider { + private filterResult: IFilterResult; + + constructor() { + super(); + this._register(CodeLensProviderRegistry.register({ pattern: '**/settings.json' }, this)); + } + + public render(filterResult: IFilterResult): void { + this.filterResult = filterResult; + } + + public provideCodeLenses(model: ITextModel, token: CancellationToken): ICodeLensSymbol[] { + if (!this.filterResult || !this.filterResult.filteredGroups) { + return []; + } + + const newExtensionGroup = arrays.first(this.filterResult.filteredGroups, g => g.id === 'newExtensionsResult'); + if (!newExtensionGroup) { + return []; + } + + return newExtensionGroup.sections[0].settings + .filter((s: IExtensionSetting) => { + // Skip any non IExtensionSettings that somehow got in here + return s.extensionName && s.extensionPublisher; + }) + .map((s: IExtensionSetting) => { + const extId = s.extensionPublisher + '.' + s.extensionName; + return { + command: { + title: nls.localize('newExtensionLabel', "Show Extension \"{0}\"", extId), + id: 'workbench.extensions.action.showExtensionsWithId', + arguments: [extId.toLowerCase()] + }, + range: new Range(s.keyRange.startLineNumber, 1, s.keyRange.startLineNumber, 1) + }; + }); + } + + public resolveCodeLens(model: ITextModel, codeLens: ICodeLensSymbol, token: CancellationToken): ICodeLensSymbol { + return codeLens; + } +} + +export interface IIndexedSetting extends ISetting { index: number; + groupId: string; } class EditSettingRenderer extends Disposable { @@ -841,8 +928,8 @@ class EditSettingRenderer extends Disposable { public associatedPreferencesModel: IPreferencesEditorModel; private toggleEditPreferencesForMouseMoveDelayer: Delayer; - private _onUpdateSetting: Emitter<{ key: string, value: any, source: ISetting, index: number }> = new Emitter<{ key: string, value: any, source: ISetting, index: number }>(); - public readonly onUpdateSetting: Event<{ key: string, value: any, source: ISetting, index: number }> = this._onUpdateSetting.event; + private _onUpdateSetting: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>(); + public readonly onUpdateSetting: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdateSetting.event; constructor(private editor: ICodeEditor, private masterSettingsModel: ISettingsEditorModel, private settingHighlighter: SettingHighlighter, @@ -978,7 +1065,7 @@ class EditSettingRenderer extends Disposable { // index of setting, across all groups/sections let index = 0; - const settings = []; + const settings: IIndexedSetting[] = []; for (const group of this.settingsGroups) { if (group.range.startLineNumber > lineNumber) { break; @@ -994,11 +1081,11 @@ class EditSettingRenderer extends Disposable { // Only one level because override settings cannot have override settings for (const overrideSetting of setting.overrides) { if (lineNumber >= overrideSetting.range.startLineNumber && lineNumber <= overrideSetting.range.endLineNumber) { - settings.push({ ...overrideSetting, index }); + settings.push({ ...overrideSetting, index, groupId: group.id }); } } } else { - settings.push({ ...setting, index }); + settings.push({ ...setting, index, groupId: group.id }); } } @@ -1024,6 +1111,32 @@ class EditSettingRenderer extends Disposable { }); } + public activateOnSetting(setting: ISetting): boolean { + const startLine = setting.keyRange.startLineNumber; + const settings = this.getSettings(startLine); + if (!settings.length) { + return false; + } + + this.editPreferenceWidgetForMouseMove.show(startLine, '', settings); + const actions = this.getActions(this.editPreferenceWidgetForMouseMove.preferences[0], this.getConfigurationsMap()[this.editPreferenceWidgetForMouseMove.preferences[0].key]); + this.contextMenuService.showContextMenu({ + getAnchor: () => this.toAbsoluteCoords(new Position(startLine, 1)), + getActions: () => TPromise.wrap(actions) + }); + + return true; + } + + private toAbsoluteCoords(position: Position): { x: number, y: number } { + const positionCoords = this.editor.getScrolledVisiblePosition(position); + const editorCoords = getDomNodePagePosition(this.editor.getDomNode()); + const x = editorCoords.left + positionCoords.left; + const y = editorCoords.top + positionCoords.top + positionCoords.height; + + return { x, y: y + 10 }; + } + private getConfigurationsMap(): { [qualifiedKey: string]: IConfigurationPropertySchema } { return Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); } @@ -1069,7 +1182,7 @@ class EditSettingRenderer extends Disposable { } private updateSetting(key: string, value: any, source: IIndexedSetting): void { - this._onUpdateSetting.fire({ key, value, source, index: source.index }); + this._onUpdateSetting.fire({ key, value, source }); } } @@ -1214,17 +1327,20 @@ class UnsupportedSettingsRenderer extends Disposable { class WorkspaceConfigurationRenderer extends Disposable { private decorationIds: string[] = []; + private associatedSettingsEditorModel: IPreferencesEditorModel; private renderingDelayer: Delayer = new Delayer(200); constructor(private editor: ICodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel, @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(); - this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render()))); + this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render(this.associatedSettingsEditorModel)))); } - public render(): void { - if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceSettingsEditorModel instanceof WorkspaceConfigurationEditorModel) { + public render(associatedSettingsEditorModel: IPreferencesEditorModel): void { + this.associatedSettingsEditorModel = associatedSettingsEditorModel; + // Dim other configurations in workspace configuration file only in the context of Settings Editor + if (this.associatedSettingsEditorModel && this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceSettingsEditorModel instanceof WorkspaceConfigurationEditorModel) { this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, [])); const ranges: IRange[] = []; diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 78cba03e94d..54e0f675b06 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -281,6 +281,7 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { export class FolderSettingsActionItem extends BaseActionItem { private _folder: IWorkspaceFolder; + private _count: number; private container: HTMLElement; private anchorElement: HTMLElement; @@ -310,6 +311,11 @@ export class FolderSettingsActionItem extends BaseActionItem { this.update(); } + public setCount(value: number): void { + this._count = value; + this.update(); + } + public render(container: HTMLElement): void { this.builder = $(container); @@ -381,10 +387,18 @@ export class FolderSettingsActionItem extends BaseActionItem { if (this._folder) { this.labelElement.textContent = this._folder.name; this.anchorElement.title = this._folder.name; - this.detailsElement.textContent = this._action.label; + let detailsText = this._action.label; + if (this._count) { + detailsText += ` (${this._count})`; + } + this.detailsElement.textContent = detailsText; DOM.toggleClass(this.dropDownElement, 'hide', workspace.folders.length === 1 || !this._action.checked); } else { - this.labelElement.textContent = this._action.label; + let labelText = this._action.label; + if (this._count) { + labelText += ` (${this._count})`; + } + this.labelElement.textContent = labelText; this.detailsElement.textContent = ''; this.anchorElement.title = this._action.label; DOM.removeClass(this.dropDownElement, 'hide'); @@ -436,6 +450,7 @@ export class SettingsTargetsWidget extends Widget { private userSettings: Action; private workspaceSettings: Action; private folderSettings: FolderSettingsActionItem; + private folderSettingCounts = new Map(); private _settingsTarget: SettingsTarget; @@ -492,6 +507,30 @@ export class SettingsTargetsWidget extends Widget { } } + public setResultCount(settingsTarget: SettingsTarget, count: number): void { + if (settingsTarget === ConfigurationTarget.WORKSPACE) { + let label = localize('workspaceSettings', "Workspace Settings"); + if (count) { + label += ` (${count})`; + } + + this.workspaceSettings.label = label; + } else if (settingsTarget === ConfigurationTarget.USER) { + let label = localize('userSettings', "User Settings"); + if (count) { + label += ` (${count})`; + } + + this.userSettings.label = label; + } else if (settingsTarget instanceof URI) { + this.folderSettingCounts.set(settingsTarget.toString(), count); + + let total = 0; + this.folderSettingCounts.forEach(count => total += count); + this.folderSettings.setCount(total); + } + } + private onWorkbenchStateChanged(): void { this.folderSettings.folder = null; this.update(); diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index 1c3024c9db1..89ec595b52e 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -16,6 +16,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { join } from 'vs/base/common/paths'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import Event from 'vs/base/common/event'; +import { IStringDictionary } from 'vs/base/common/collections'; export interface IWorkbenchSettingsConfiguration { workbench: { @@ -24,6 +25,7 @@ export interface IWorkbenchSettingsConfiguration { naturalLanguageSearchEndpoint: string; naturalLanguageSearchKey: string; naturalLanguageSearchAutoIngestFeedback: boolean; + useNaturalLanguageSearchPost: boolean; enableNaturalLanguageSearch: boolean; enableNaturalLanguageSearchFeedback: boolean; } @@ -56,6 +58,11 @@ export interface ISetting { overrideOf?: ISetting; } +export interface IExtensionSetting extends ISetting { + extensionName: string; + extensionPublisher: string; +} + export interface ISearchResult { filterMatches: ISettingMatch[]; metadata?: IFilterMetadata; @@ -65,6 +72,7 @@ export interface ISearchResultGroup { id: string; label: string; result: ISearchResult; + order: number; } export interface IFilterResult { @@ -72,7 +80,7 @@ export interface IFilterResult { filteredGroups: ISettingsGroup[]; allGroups: ISettingsGroup[]; matches: IRange[]; - metadata?: IFilterMetadata; + metadata?: IStringDictionary; } export interface ISettingMatch { @@ -82,11 +90,23 @@ export interface ISettingMatch { } export interface IScoredResults { - [key: string]: number; + [key: string]: IRemoteSetting; +} + +export interface IRemoteSetting { + score: number; + key: string; + id: string; + defaultValue: string; + description: string; + packageId: string; + extensionName?: string; + extensionPublisher?: string; } export interface IFilterMetadata { - remoteUrl: string; + requestUrl: string; + requestBody: string; timestamp: number; duration: number; scoredResults: IScoredResults; @@ -102,7 +122,7 @@ export interface IPreferencesEditorModel { } export type IGroupFilter = (group: ISettingsGroup) => boolean; -export type ISettingMatcher = (setting: ISetting) => { matches: IRange[], score: number }; +export type ISettingMatcher = (setting: ISetting, group: ISettingsGroup) => { matches: IRange[], score: number }; export interface ISettingsEditorModel extends IPreferencesEditorModel { readonly onDidChangeGroups: Event; @@ -149,6 +169,7 @@ export interface IKeybindingsEditor extends IEditor { removeKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; resetKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; copyKeybinding(keybindingEntry: IKeybindingItemEntry): TPromise; + copyKeybindingCommand(keybindingEntry: IKeybindingItemEntry): TPromise; showConflicts(keybindingEntry: IKeybindingItemEntry): TPromise; } @@ -175,10 +196,8 @@ export const IPreferencesSearchService = createDecorator(); - this._currentResultGroups.forEach((group, id) => { - group.result.filterMatches = group.result.filterMatches.filter(s => !settingKeys.has(s.setting.key)); - group.result.filterMatches.forEach(s => settingKeys.add(s.setting.key)); - }); + map.keys(this._currentResultGroups) + .sort((a, b) => this._currentResultGroups.get(a).order - this._currentResultGroups.get(b).order) + .forEach(groupId => { + const group = this._currentResultGroups.get(groupId); + group.result.filterMatches = group.result.filterMatches.filter(s => !settingKeys.has(s.setting.key)); + group.result.filterMatches.forEach(s => settingKeys.add(s.setting.key)); + }); } public filterSettings(filter: string, groupFilter: IGroupFilter, settingMatcher: ISettingMatcher): ISettingMatch[] { @@ -57,7 +60,7 @@ export abstract class AbstractSettingsModel extends EditorModel { const groupMatched = groupFilter(group); for (const section of group.sections) { for (const setting of section.settings) { - const settingMatchResult = settingMatcher(setting); + const settingMatchResult = settingMatcher(setting, group); if (groupMatched || settingMatchResult) { filterMatches.push({ @@ -86,6 +89,20 @@ export abstract class AbstractSettingsModel extends EditorModel { return null; } + protected collectMetadata(groups: ISearchResultGroup[]): IStringDictionary { + const metadata = Object.create(null); + let hasMetadata = false; + groups.forEach(g => { + if (g.result.metadata) { + metadata[g.id] = g.result.metadata; + hasMetadata = true; + } + }); + + return hasMetadata ? metadata : null; + } + + protected get filterGroups(): ISettingsGroup[] { return this.settingsGroups; } @@ -176,12 +193,12 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti }; } - const groupWithMetadata = first(resultGroups, group => !!group.result.metadata); + const metadata = this.collectMetadata(resultGroups); return { allGroups: this.settingsGroups, filteredGroups: filteredGroup ? [filteredGroup] : [], matches, - metadata: groupWithMetadata && groupWithMetadata.result.metadata + metadata }; } } @@ -611,19 +628,21 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements protected update(): IFilterResult { // Grab current result groups, only render non-empty groups - const resultGroups = map.values(this._currentResultGroups); + const resultGroups = map + .values(this._currentResultGroups) + .sort((a, b) => a.order - b.order); const nonEmptyResultGroups = resultGroups.filter(group => group.result.filterMatches.length); const startLine = tail(this.settingsGroups).range.endLineNumber + 2; const { settingsGroups: filteredGroups, matches } = this.writeResultGroups(nonEmptyResultGroups, startLine); - const groupWithMetadata = first(resultGroups, group => !!group.result.metadata); + const metadata = this.collectMetadata(resultGroups); return resultGroups.length ? { allGroups: this.settingsGroups, filteredGroups, matches, - metadata: groupWithMetadata && groupWithMetadata.result.metadata + metadata } : null; } @@ -665,20 +684,21 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements } private writeSettingsGroupToBuilder(builder: SettingsContentBuilder, settingsGroup: ISettingsGroup, filterMatches: ISettingMatch[]): IRange[] { - // Fix match ranges to offset from setting start line - filterMatches = filterMatches.map(filteredMatch => { - return { - setting: filteredMatch.setting, - score: filteredMatch.score, - matches: filteredMatch.matches && filteredMatch.matches.map(match => { - return new Range( - match.startLineNumber - filteredMatch.setting.range.startLineNumber, - match.startColumn, - match.endLineNumber - filteredMatch.setting.range.startLineNumber, - match.endColumn); - }) - }; - }); + filterMatches = filterMatches + .map(filteredMatch => { + // Fix match ranges to offset from setting start line + return { + setting: filteredMatch.setting, + score: filteredMatch.score, + matches: filteredMatch.matches && filteredMatch.matches.map(match => { + return new Range( + match.startLineNumber - filteredMatch.setting.range.startLineNumber, + match.startColumn, + match.endLineNumber - filteredMatch.setting.range.startLineNumber, + match.endColumn); + }) + }; + }); builder.pushGroup(settingsGroup); builder.pushLine(','); @@ -701,6 +721,17 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements return fixedMatches; } + private copySetting(setting: ISetting): ISetting { + return { + description: setting.description, + key: setting.key, + value: setting.value, + range: setting.range, + overrides: [], + overrideOf: setting.overrideOf + }; + } + public findValueMatches(filter: string, setting: ISetting): IRange[] { return []; } @@ -718,19 +749,6 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements return null; } - private copySettings(settings: ISetting[]): ISetting[] { - return settings.map(setting => { - return { - description: setting.description, - key: setting.key, - value: setting.value, - range: null, - valueRange: null, - overrides: [] - }; - }); - } - private getGroup(resultGroup: ISearchResultGroup): ISettingsGroup { return { id: resultGroup.id, @@ -739,7 +757,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements titleRange: null, sections: [ { - settings: this.copySettings(resultGroup.result.filterMatches.map(m => m.setting)) + settings: resultGroup.result.filterMatches.map(m => this.copySetting(m.setting)) } ] }; diff --git a/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts index 24b637b2cea..986c46a2e34 100644 --- a/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferences.contribution.ts @@ -19,7 +19,7 @@ import { KeybindingsEditor, KeybindingsEditorInput } from 'vs/workbench/parts/pr import { OpenRawDefaultSettingsAction, OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenWorkspaceSettingsAction, OpenFolderSettingsAction, ConfigureLanguageBasedSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND } from 'vs/workbench/parts/preferences/browser/preferencesActions'; import { IPreferencesService, IKeybindingsEditor, IPreferencesSearchService, CONTEXT_KEYBINDING_FOCUS, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_SEARCH, - KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS + KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_SHOW_CONFLICTS, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/parts/preferences/common/preferences'; import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -238,6 +238,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, + weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), + when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS), + primary: null, + handler: (accessor, args: any) => { + const editor = accessor.get(IWorkbenchEditorService).getActiveEditor() as IKeybindingsEditor; + editor.copyKeybindingCommand(editor.activeKeybindingEntry); + } +}); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), diff --git a/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts index fb8dac50a05..5c7d45b1c92 100644 --- a/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/preferencesSearch.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { TPromise } from 'vs/base/common/winjs.base'; -import { ISettingsEditorModel, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService, ISearchResult, ISearchProvider, IGroupFilter, ISettingMatcher, IScoredResults } from 'vs/workbench/parts/preferences/common/preferences'; +import { ISettingsEditorModel, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService, ISearchResult, ISearchProvider, IGroupFilter, ISettingMatcher, IScoredResults, ISettingMatch, IRemoteSetting, IExtensionSetting } from 'vs/workbench/parts/preferences/common/preferences'; import { IRange } from 'vs/editor/common/core/range'; import { distinct, top } from 'vs/base/common/arrays'; import * as strings from 'vs/base/common/strings'; @@ -18,6 +18,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IRequestService } from 'vs/platform/request/node/request'; import { asJson } from 'vs/base/node/request'; import { Disposable } from 'vs/base/common/lifecycle'; +import { IExtensionManagementService, LocalExtensionType, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { ILogService } from 'vs/platform/log/common/log'; export interface IEndpointDetails { urlBase: string; @@ -27,12 +29,16 @@ export interface IEndpointDetails { export class PreferencesSearchService extends Disposable implements IPreferencesSearchService { _serviceBrand: any; + private _installedExtensions: TPromise; + constructor( @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, @IEnvironmentService private environmentService: IEnvironmentService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IExtensionManagementService private extensionManagementService: IExtensionManagementService ) { super(); + this._installedExtensions = this.extensionManagementService.getInstalled(LocalExtensionType.User); } private get remoteSearchAllowed(): boolean { @@ -45,10 +51,10 @@ export class PreferencesSearchService extends Disposable implements IPreferences return false; } - return !!this.endpoint.urlBase; + return !!this._endpoint.urlBase; } - get endpoint(): IEndpointDetails { + private get _endpoint(): IEndpointDetails { const workbenchSettings = this.configurationService.getValue().workbench.settings; if (workbenchSettings.naturalLanguageSearchEndpoint) { return { @@ -62,8 +68,14 @@ export class PreferencesSearchService extends Disposable implements IPreferences } } - getRemoteSearchProvider(filter: string): RemoteSearchProvider { - return this.remoteSearchAllowed && this.instantiationService.createInstance(RemoteSearchProvider, filter, this.endpoint); + getRemoteSearchProvider(filter: string, newExtensionsOnly = false): ISearchProvider { + const opts: IRemoteSearchProviderOptions = { + filter, + newExtensionsOnly, + endpoint: this._endpoint + }; + + return this.remoteSearchAllowed && this.instantiationService.createInstance(RemoteSearchProvider, opts, this._installedExtensions); } getLocalSearchProvider(filter: string): LocalSearchProvider { @@ -85,7 +97,7 @@ export class LocalSearchProvider implements ISearchProvider { let score = 1000; // Sort is not stable const settingMatcher = (setting: ISetting) => { - const matches = new SettingMatches(this._filter, setting, true, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches; + const matches = new SettingMatches(this._filter, setting, true, false, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches; return matches && matches.length ? { matches, @@ -101,119 +113,228 @@ export class LocalSearchProvider implements ISearchProvider { } private getGroupFilter(filter: string): IGroupFilter { - if (strings.startsWith(filter, '@')) { - const groupId = filter.replace(/^@/, ''); - return (group: ISettingsGroup) => { - return group.id.toLowerCase() === groupId.toLowerCase(); - }; - } else { - const regex = strings.createRegExp(this._filter, false, { global: true }); - return (group: ISettingsGroup) => { - return regex.test(group.title); - }; - } + const regex = strings.createRegExp(this._filter, false, { global: true }); + return (group: ISettingsGroup) => { + return regex.test(group.title); + }; } } -export class RemoteSearchProvider implements ISearchProvider { - private _filter: string; +interface IRemoteSearchProviderOptions { + filter: string; + endpoint: IEndpointDetails; + newExtensionsOnly: boolean; +} + +class RemoteSearchProvider implements ISearchProvider { + // Must keep extension filter size under 8kb. 42 extension filters + core buildnum filter puts us there. + private static MAX_EXTENSION_FILTERS = 42; + private _remoteSearchP: TPromise; - constructor(filter: string, endpoint: IEndpointDetails, + constructor(private options: IRemoteSearchProviderOptions, private installedExtensions: TPromise, @IEnvironmentService private environmentService: IEnvironmentService, - @IRequestService private requestService: IRequestService + @IRequestService private requestService: IRequestService, + @ILogService private logService: ILogService ) { - this._filter = filter; - - // @queries are always handled by local filter - this._remoteSearchP = filter && !strings.startsWith(filter, '@') ? - this.getSettingsFromBing(filter, endpoint) : + this._remoteSearchP = this.options.filter ? + this.getSettingsFromBing(this.options.filter) : TPromise.wrap(null); } searchModel(preferencesModel: ISettingsEditorModel): TPromise { return this._remoteSearchP.then(remoteResult => { - if (remoteResult) { - const highScoreKey = top(Object.keys(remoteResult.scoredResults), (a, b) => remoteResult.scoredResults[b] - remoteResult.scoredResults[a], 1)[0]; - const highScore = highScoreKey ? remoteResult.scoredResults[highScoreKey] : 0; - const minScore = highScore / 5; + if (!remoteResult) { + return null; + } + + const resultKeys = Object.keys(remoteResult.scoredResults); + const highScoreKey = top(resultKeys, (a, b) => remoteResult.scoredResults[b].score - remoteResult.scoredResults[a].score, 1)[0]; + const highScore = highScoreKey ? remoteResult.scoredResults[highScoreKey].score : 0; + const minScore = highScore / 5; + if (this.options.newExtensionsOnly) { + const passingScoreKeys = resultKeys.filter(k => remoteResult.scoredResults[k].score >= minScore); + const filterMatches: ISettingMatch[] = passingScoreKeys.map(k => { + const remoteSetting = remoteResult.scoredResults[k]; + const setting = remoteSettingToISetting(remoteSetting); + return { + setting, + score: remoteSetting.score, + matches: [] // TODO + }; + }); - const settingMatcher = this.getRemoteSettingMatcher(remoteResult.scoredResults, minScore, preferencesModel); - const filterMatches = preferencesModel.filterSettings(this._filter, group => null, settingMatcher); return { filterMatches, metadata: remoteResult }; } else { - return null; + const settingMatcher = this.getRemoteSettingMatcher(remoteResult.scoredResults, minScore, preferencesModel); + const filterMatches = preferencesModel.filterSettings(this.options.filter, group => null, settingMatcher); + return { + filterMatches, + metadata: remoteResult + }; } }); } - private getSettingsFromBing(filter: string, endpoint: IEndpointDetails): TPromise { - const url = prepareUrl(filter, endpoint, this.environmentService.settingsSearchBuildId); + private getSettingsFromBing(filter: string): TPromise { const start = Date.now(); - const p = this.requestService.request({ - url, - headers: { - 'User-Agent': 'request', - 'Content-Type': 'application/json; charset=utf-8', - 'api-key': endpoint.key - }, - timeout: 5000 - }) - .then(context => { + return this.prepareRequest(filter).then(details => { + this.logService.debug(`Searching settings via ${details.url}`); + if (details.body) { + this.logService.debug(`Body: ${details.body}`); + } + + const requestType = details.body ? 'post' : 'get'; + return this.requestService.request({ + type: requestType, + url: details.url, + data: details.body, + headers: { + 'User-Agent': 'request', + 'Content-Type': 'application/json; charset=utf-8', + 'api-key': this.options.endpoint.key + }, + timeout: 5000 + }).then(context => { if (context.res.statusCode >= 300) { - throw new Error(`${url} returned status code: ${context.res.statusCode}`); + throw new Error(`${details} returned status code: ${context.res.statusCode}`); } return asJson(context); - }) - .then((result: any) => { + }).then((result: any) => { const timestamp = Date.now(); const duration = timestamp - start; - const suggestions = (result.value || []) - .map(r => ({ - name: r.setting || r.Setting, - score: r['@search.score'] - })); + const remoteSettings: IRemoteSetting[] = (result.value || []) + .map(r => { + const key = JSON.parse(r.setting || r.Setting); + const packageId = r['packageid']; + const id = getSettingKey(key, packageId); + + const value = r['value']; + const defaultValue = value ? JSON.parse(value) : value; + + const packageName = r['packagename']; + let extensionName: string; + let extensionPublisher: string; + if (packageName && packageName.indexOf('##') >= 0) { + [extensionPublisher, extensionName] = packageName.split('##'); + } + + return { + key, + id, + defaultValue, + score: r['@search.score'], + description: JSON.parse(r['details']), + packageId, + extensionName, + extensionPublisher + }; + }); const scoredResults = Object.create(null); - suggestions.forEach(s => { - const name = s.name - .replace(/^"/, '') - .replace(/"$/, ''); - scoredResults[name] = s.score; + remoteSettings.forEach(s => { + scoredResults[s.id] = s; }); return { - remoteUrl: url, + requestUrl: details.url, + requestBody: details.body, duration, timestamp, scoredResults, context: result['@odata.context'] }; }); - - return TPromise.as(p as any); + }); } private getRemoteSettingMatcher(scoredResults: IScoredResults, minScore: number, preferencesModel: ISettingsEditorModel): ISettingMatcher { - return (setting: ISetting) => { - const score = scoredResults[setting.key]; - if (typeof score === 'number' && score >= minScore) { - const settingMatches = new SettingMatches(this._filter, setting, false, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches; - return { matches: settingMatches, score: scoredResults[setting.key] }; + return (setting: ISetting, group: ISettingsGroup) => { + const remoteSetting = scoredResults[getSettingKey(setting.key, group.id)] || // extension setting + scoredResults[getSettingKey(setting.key, 'core')] || // core setting + scoredResults[getSettingKey(setting.key)]; // core setting from original prod endpoint + if (remoteSetting && remoteSetting.score >= minScore) { + const settingMatches = new SettingMatches(this.options.filter, setting, false, true, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches; + return { matches: settingMatches, score: remoteSetting.score }; } return null; }; } + + private async prepareRequest(query: string): TPromise<{ url: string, body?: string }> { + query = escapeSpecialChars(query); + const boost = 10; + const userQuery = `(${query})^${boost}`; + + // Appending Fuzzy after each word. + query = query.replace(/\ +/g, '~ ') + '~'; + + const encodedQuery = encodeURIComponent(userQuery + ' || ' + query); + let url = `${this.options.endpoint.urlBase}?`; + + const buildNumber = this.environmentService.settingsSearchBuildId; + if (this.options.endpoint.key) { + url += `${API_VERSION}&${QUERY_TYPE}`; + } + + const filters = this.options.newExtensionsOnly ? + [`diminish eq 'latest'`] : + await this.getVersionFilters(buildNumber); + + const filterStr = filters + .slice(0, RemoteSearchProvider.MAX_EXTENSION_FILTERS) + .join(' or '); + + const body = JSON.stringify({ + query: encodedQuery, + filters: encodeURIComponent(filterStr) + }); + + return { + url, + body + }; + } + + private getVersionFilters(buildNumber?: number): TPromise { + return this.installedExtensions.then(exts => { + // Only search extensions that contribute settings + const filters = exts + .filter(ext => ext.manifest.contributes && ext.manifest.contributes.configuration) + .map(ext => this.getExtensionFilter(ext)); + + if (buildNumber) { + filters.push(`(packageid eq 'core' and startbuildno le '${buildNumber}' and endbuildno ge '${buildNumber}')`); + } + + return filters; + }); + } + + private getExtensionFilter(ext: ILocalExtension): string { + const uuid = ext.identifier.uuid; + const versionString = ext.manifest.version + .split('.') + .map(versionPart => strings.pad(versionPart, 10)) + .join(''); + + return `(packageid eq '${uuid}' and startbuildno le '${versionString}' and endbuildno ge '${versionString}')`; + } +} + +function getSettingKey(name: string, packageId?: string): string { + return packageId ? + packageId + '##' + name : + name; } const API_VERSION = 'api-version=2016-09-01-Preview'; const QUERY_TYPE = 'querytype=full'; -const SCORING_PROFILE = 'scoringProfile=ranking'; function escapeSpecialChars(query: string): string { return query.replace(/\./g, ' ') @@ -222,32 +343,19 @@ function escapeSpecialChars(query: string): string { .trim(); } -function prepareUrl(query: string, endpoint: IEndpointDetails, buildNumber: number): string { - query = escapeSpecialChars(query); - const boost = 10; - const userQuery = `(${query})^${boost}`; - - // Appending Fuzzy after each word. - query = query.replace(/\ +/g, '~ ') + '~'; - - const encodedQuery = encodeURIComponent(userQuery + ' || ' + query); - let url = `${endpoint.urlBase}?`; - if (endpoint.key) { - url += `search=${encodedQuery}`; - url += `&${API_VERSION}&${QUERY_TYPE}&${SCORING_PROFILE}`; - - if (buildNumber) { - url += `&$filter startbuildno le ${buildNumber} and endbuildno ge ${buildNumber}`; - } - } else { - url += `query=${encodedQuery}`; - - if (buildNumber) { - url += `&build=${buildNumber}`; - } - } - - return url; +function remoteSettingToISetting(remoteSetting: IRemoteSetting): IExtensionSetting { + return { + description: remoteSetting.description.split('\n'), + descriptionRanges: null, + key: remoteSetting.key, + keyRange: null, + value: remoteSetting.defaultValue, + range: null, + valueRange: null, + overrides: [], + extensionName: remoteSetting.extensionName, + extensionPublisher: remoteSetting.extensionPublisher + }; } class SettingMatches { @@ -258,7 +366,7 @@ class SettingMatches { public readonly matches: IRange[]; - constructor(searchString: string, setting: ISetting, private requireFullQueryMatch: boolean, private valuesMatcher: (filter: string, setting: ISetting) => IRange[]) { + constructor(searchString: string, setting: ISetting, private requireFullQueryMatch: boolean, private searchDescription, private valuesMatcher: (filter: string, setting: ISetting) => IRange[]) { this.matches = distinct(this._findMatchesInSetting(searchString, setting), (match) => `${match.startLineNumber}_${match.startColumn}_${match.endLineNumber}_${match.endColumn}_`); } @@ -266,7 +374,7 @@ class SettingMatches { const result = this._doFindMatchesInSetting(searchString, setting); if (setting.overrides && setting.overrides.length) { for (const subSetting of setting.overrides) { - const subSettingMatches = new SettingMatches(searchString, subSetting, this.requireFullQueryMatch, this.valuesMatcher); + const subSettingMatches = new SettingMatches(searchString, subSetting, this.requireFullQueryMatch, this.searchDescription, this.valuesMatcher); let words = searchString.split(' '); const descriptionRanges: IRange[] = this.getRangesForWords(words, this.descriptionMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]); const keyRanges: IRange[] = this.getRangesForWords(words, this.keyMatchingWords, [subSettingMatches.descriptionMatchingWords, subSettingMatches.keyMatchingWords, subSettingMatches.valueMatchingWords]); @@ -287,10 +395,12 @@ class SettingMatches { const settingKeyAsWords: string = setting.key.split('.').join(' '); for (const word of words) { - for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) { - const descriptionMatches = matchesWords(word, setting.description[lineIndex], true); - if (descriptionMatches) { - this.descriptionMatchingWords.set(word, descriptionMatches.map(match => this.toDescriptionRange(setting, match, lineIndex))); + if (this.searchDescription) { + for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) { + const descriptionMatches = matchesWords(word, setting.description[lineIndex], true); + if (descriptionMatches) { + this.descriptionMatchingWords.set(word, descriptionMatches.map(match => this.toDescriptionRange(setting, match, lineIndex))); + } } } @@ -308,12 +418,14 @@ class SettingMatches { } const descriptionRanges: IRange[] = []; - for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) { - const matches = or(matchesContiguousSubString)(searchString, setting.description[lineIndex] || '') || []; - descriptionRanges.push(...matches.map(match => this.toDescriptionRange(setting, match, lineIndex))); - } - if (descriptionRanges.length === 0) { - descriptionRanges.push(...this.getRangesForWords(words, this.descriptionMatchingWords, [this.keyMatchingWords, this.valueMatchingWords])); + if (this.searchDescription) { + for (let lineIndex = 0; lineIndex < setting.description.length; lineIndex++) { + const matches = or(matchesContiguousSubString)(searchString, setting.description[lineIndex] || '') || []; + descriptionRanges.push(...matches.map(match => this.toDescriptionRange(setting, match, lineIndex))); + } + if (descriptionRanges.length === 0) { + descriptionRanges.push(...this.getRangesForWords(words, this.descriptionMatchingWords, [this.keyMatchingWords, this.valueMatchingWords])); + } } const keyMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.key); @@ -324,7 +436,7 @@ class SettingMatches { const valueMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.value); valueRanges = valueMatches ? valueMatches.map(match => this.toValueRange(setting, match)) : this.getRangesForWords(words, this.valueMatchingWords, [this.keyMatchingWords, this.descriptionMatchingWords]); } else { - valueRanges = this.valuesMatcher(searchString, setting); + valueRanges = this.valuesMatcher ? this.valuesMatcher(searchString, setting) : []; } return [...descriptionRanges, ...keyRanges, ...valueRanges]; diff --git a/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts b/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts index 2c1c4186639..7b41004a587 100644 --- a/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/viewPickerHandler.ts @@ -11,8 +11,8 @@ import { Mode, IEntryRunContext, IAutoFocus, IQuickNavigateConfiguration, IModel import { QuickOpenModel, QuickOpenEntryGroup, QuickOpenEntry } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { QuickOpenHandler, QuickOpenAction } from 'vs/workbench/browser/quickopen'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { IOutputService, OUTPUT_PANEL_ID } from 'vs/workbench/parts/output/common/output'; -import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; +import { IOutputService } from 'vs/workbench/parts/output/common/output'; +import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { Action } from 'vs/base/common/actions'; @@ -138,40 +138,27 @@ export class ViewPickerHandler extends QuickOpenHandler { // Viewlets const viewlets = this.viewletService.getViewlets(); + viewlets.forEach((viewlet, index) => viewEntries.push(new ViewEntry(viewlet.name, nls.localize('views', "Views"), () => this.viewletService.openViewlet(viewlet.id, true).done(null, errors.onUnexpectedError)))); + + // Panels + const panels = this.panelService.getPanels(); + panels.forEach((panel, index) => viewEntries.push(new ViewEntry(panel.name, nls.localize('panels', "Panels"), () => this.panelService.openPanel(panel.id, true).done(null, errors.onUnexpectedError)))); + + // Views viewlets.forEach((viewlet, index) => { const viewLocation: ViewLocation = viewlet.id === EXPLORER_VIEWLET_ID ? ViewLocation.Explorer : viewlet.id === DEBUG_VIEWLET_ID ? ViewLocation.Debug : viewlet.id === EXTENSIONS_VIEWLET_ID ? ViewLocation.Extensions : null; - const viewEntriesForViewlet: ViewEntry[] = viewLocation ? getViewEntriesForViewlet(viewlet, viewLocation) - : [new ViewEntry(viewlet.name, nls.localize('views', "Views"), () => this.viewletService.openViewlet(viewlet.id, true).done(null, errors.onUnexpectedError))]; - - viewEntries.push(...viewEntriesForViewlet); - }); - - const terminals = this.terminalService.terminalInstances; - - // Panels - const panels = this.panelService.getPanels().filter(p => { - if (p.id === OUTPUT_PANEL_ID) { - return false; // since we already show output channels below + if (viewLocation) { + const viewEntriesForViewlet: ViewEntry[] = getViewEntriesForViewlet(viewlet, viewLocation); + viewEntries.push(...viewEntriesForViewlet); } - - if (p.id === TERMINAL_PANEL_ID && terminals.length > 0) { - return false; // since we already show terminal instances below - } - - return true; - }); - panels.forEach((panel, index) => { - const panelsCategory = nls.localize('panels', "Panels"); - const entry = new ViewEntry(panel.name, panelsCategory, () => this.panelService.openPanel(panel.id, true).done(null, errors.onUnexpectedError)); - - viewEntries.push(entry); }); // Terminals + const terminals = this.terminalService.terminalInstances; terminals.forEach((terminal, index) => { const terminalsCategory = nls.localize('terminals', "Terminal"); const entry = new ViewEntry(nls.localize('terminalTitle', "{0}: {1}", index + 1, terminal.title), terminalsCategory, () => { diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 156a7bb20a6..dfdeb0359ed 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -55,7 +55,7 @@ import * as platform from 'vs/base/common/platform'; 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 { WorkbenchList } from 'vs/platform/list/browser/listService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; // TODO@Joao @@ -226,9 +226,7 @@ class MainPanel extends ViewletPanel { @IContextMenuService protected contextMenuService: IContextMenuService, @ISCMService protected scmService: ISCMService, @IInstantiationService private instantiationService: IInstantiationService, - @IThemeService private themeService: IThemeService, @IContextKeyService private contextKeyService: IContextKeyService, - @IListService private listService: IListService, @IMenuService private menuService: IMenuService ) { super(localize('scm providers', "Source Control Providers"), {}, keybindingService, contextMenuService); @@ -260,9 +258,9 @@ class MainPanel extends ViewletPanel { const delegate = new ProvidersListDelegate(); const renderer = this.instantiationService.createInstance(ProviderRenderer); - this.list = new WorkbenchList(container, delegate, [renderer], { + this.list = this.instantiationService.createInstance(WorkbenchList, container, delegate, [renderer], { identityProvider: repository => repository.provider.id - }, this.contextKeyService, this.listService, this.themeService); + }); this.disposables.push(this.list); this.list.onSelectionChange(this.onListSelectionChange, this, this.disposables); @@ -431,6 +429,7 @@ interface ResourceTemplate { fileLabel: FileLabel; decorationIcon: HTMLElement; actionBar: ActionBar; + elementDisposable: IDisposable; dispose: () => void; } @@ -466,7 +465,8 @@ class ResourceRenderer implements IRenderer { private actionItemProvider: IActionItemProvider, private getSelectedResources: () => ISCMResource[], @IThemeService private themeService: IThemeService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IConfigurationService private configurationService: IConfigurationService ) { } renderTemplate(container: HTMLElement): ResourceTemplate { @@ -482,7 +482,7 @@ class ResourceRenderer implements IRenderer { const decorationIcon = append(element, $('.decoration-icon')); return { - element, name, fileLabel, decorationIcon, actionBar, dispose: () => { + element, name, fileLabel, decorationIcon, actionBar, elementDisposable: EmptyDisposable, dispose: () => { actionBar.dispose(); fileLabel.dispose(); } @@ -490,14 +490,22 @@ class ResourceRenderer implements IRenderer { } renderElement(resource: ISCMResource, index: number, template: ResourceTemplate): void { + template.elementDisposable.dispose(); const theme = this.themeService.getTheme(); const icon = theme.type === LIGHT ? resource.decorations.icon : resource.decorations.iconDark; template.fileLabel.setFile(resource.sourceUri, { fileDecorations: { colors: false, badges: !icon, data: resource.decorations } }); - template.actionBar.clear(); template.actionBar.context = resource; - template.actionBar.push(this.scmMenus.getResourceActions(resource), { icon: true, label: false }); + + const updateActions = () => { + template.actionBar.clear(); + template.actionBar.push(this.scmMenus.getResourceActions(resource), { icon: true, label: false }); + }; + + template.elementDisposable = this.configurationService.onDidChangeConfiguration(updateActions); + updateActions(); + toggleClass(template.name, 'strike-through', resource.decorations.strikeThrough); toggleClass(template.element, 'faded', resource.decorations.faded); @@ -509,9 +517,12 @@ class ResourceRenderer implements IRenderer { template.decorationIcon.style.display = 'none'; template.decorationIcon.style.backgroundImage = ''; } + + template.element.setAttribute('data-tooltip', resource.decorations.tooltip); } disposeTemplate(template: ResourceTemplate): void { + template.elementDisposable.dispose(); template.dispose(); } } @@ -690,12 +701,10 @@ export class RepositoryPanel extends ViewletPanel { @IThemeService protected themeService: IThemeService, @IContextMenuService protected contextMenuService: IContextMenuService, @IContextViewService protected contextViewService: IContextViewService, - @IListService protected listService: IListService, @ICommandService protected commandService: ICommandService, @IMessageService protected messageService: IMessageService, @IWorkbenchEditorService protected editorService: IWorkbenchEditorService, @IEditorGroupService protected editorGroupService: IEditorGroupService, - @IContextKeyService protected contextKeyService: IContextKeyService, @IInstantiationService protected instantiationService: IInstantiationService, @IConfigurationService protected configurationService: IConfigurationService ) { @@ -844,10 +853,10 @@ export class RepositoryPanel extends ViewletPanel { this.instantiationService.createInstance(ResourceRenderer, this.menus, actionItemProvider, () => this.getSelectedResources()), ]; - this.list = new WorkbenchList(this.listContainer, delegate, renderers, { + this.list = this.instantiationService.createInstance(WorkbenchList, this.listContainer, delegate, renderers, { identityProvider: scmResourceIdentityProvider, keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); chain(this.list.onOpen) .map(e => e.elements[0]) diff --git a/src/vs/workbench/parts/search/browser/media/searchviewlet.css b/src/vs/workbench/parts/search/browser/media/searchviewlet.css index 3e747e6c15e..d866df8c809 100644 --- a/src/vs/workbench/parts/search/browser/media/searchviewlet.css +++ b/src/vs/workbench/parts/search/browser/media/searchviewlet.css @@ -310,6 +310,15 @@ background: url('clear-search-results-dark.svg') center center no-repeat; } +.monaco-workbench .search-action.cancel-search { + background: url('stop.svg') center center no-repeat; +} + +.vs-dark .monaco-workbench .search-action.cancel-search, +.hc-black .monaco-workbench .search-action.cancel-search { + background: url('stop-inverse.svg') center center no-repeat; +} + .vs .monaco-workbench .search-viewlet .query-details .file-types .controls > .custom-checkbox.pattern { background: url('pattern.svg') center center no-repeat; } diff --git a/src/vs/workbench/parts/search/browser/media/stop-inverse.svg b/src/vs/workbench/parts/search/browser/media/stop-inverse.svg new file mode 100644 index 00000000000..ef79528e9c8 --- /dev/null +++ b/src/vs/workbench/parts/search/browser/media/stop-inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/search/browser/media/stop.svg b/src/vs/workbench/parts/search/browser/media/stop.svg new file mode 100644 index 00000000000..0b36e84ac92 --- /dev/null +++ b/src/vs/workbench/parts/search/browser/media/stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/search/browser/replaceService.ts b/src/vs/workbench/parts/search/browser/replaceService.ts index c93549e85dd..5abd6630a1c 100644 --- a/src/vs/workbench/parts/search/browser/replaceService.ts +++ b/src/vs/workbench/parts/search/browser/replaceService.ts @@ -15,7 +15,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { Match, FileMatch, FileMatchOrMatch, ISearchWorkbenchService } from 'vs/workbench/parts/search/common/searchModel'; -import { BulkEdit, IResourceEdit, createBulkEdit } from 'vs/editor/browser/services/bulkEdit'; +import { BulkEdit } from 'vs/editor/browser/services/bulkEdit'; import { IProgressRunner } from 'vs/platform/progress/common/progress'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService'; @@ -24,6 +24,8 @@ import { ScrollType } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IFileService } from 'vs/platform/files/common/files'; +import { ResourceTextEdit } from 'vs/editor/common/modes'; +import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; const REPLACE_PREVIEW = 'replacePreview'; @@ -70,7 +72,7 @@ class ReplacePreviewModel extends Disposable { ref = this._register(ref); const sourceModel = ref.object.textEditorModel; const sourceModelModeId = sourceModel.getLanguageIdentifier().language; - const replacePreviewModel = this.modelService.createModel(sourceModel.getValue(), this.modeService.getOrCreateMode(sourceModelModeId), replacePreviewUri); + const replacePreviewModel = this.modelService.createModel(createTextBufferFactoryFromSnapshot(sourceModel.createSnapshot()), this.modeService.getOrCreateMode(sourceModelModeId), replacePreviewUri); this._register(fileMatch.onChange(modelChange => this.update(sourceModel, replacePreviewModel, fileMatch, modelChange))); this._register(this.searchWorkbenchService.searchModel.onReplaceTermChanged(() => this.update(sourceModel, replacePreviewModel, fileMatch))); this._register(fileMatch.onDispose(() => replacePreviewModel.dispose())); // TODO@Sandeep we should not dispose a model directly but rather the reference (depends on https://github.com/Microsoft/vscode/issues/17073) @@ -103,8 +105,7 @@ export class ReplaceService implements IReplaceService { public replace(match: FileMatchOrMatch, progress?: IProgressRunner, resource?: URI): TPromise; public replace(arg: any, progress: IProgressRunner = null, resource: URI = null): TPromise { - let bulkEdit: BulkEdit = createBulkEdit(this.textModelResolverService, null, this.fileService); - bulkEdit.progress(progress); + let bulkEdit = new BulkEdit(null, progress, this.textModelResolverService, this.fileService); if (arg instanceof Match) { let match = arg; @@ -126,7 +127,7 @@ export class ReplaceService implements IReplaceService { }); } - return bulkEdit.finish(); + return bulkEdit.perform(); } public openReplacePreview(element: FileMatchOrMatch, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): TPromise { @@ -174,12 +175,14 @@ export class ReplaceService implements IReplaceService { }); } - private createEdit(match: Match, text: string, resource: URI = null): IResourceEdit { + private createEdit(match: Match, text: string, resource: URI = null): ResourceTextEdit { let fileMatch: FileMatch = match.parent(); - let resourceEdit: IResourceEdit = { + let resourceEdit: ResourceTextEdit = { resource: resource !== null ? resource : fileMatch.resource(), - range: match.range(), - newText: text + edits: [{ + range: match.range(), + text: text + }] }; return resourceEdit; } diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index 4145a5cc8b2..ffd61a26620 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -379,6 +379,32 @@ export class ClearSearchResultsAction extends SearchAction { } } +export class CancelSearchAction extends SearchAction { + + static ID: string = 'search.action.cancelSearch'; + static LABEL: string = nls.localize('CancelSearchAction.label', "Cancel Search"); + + constructor(id: string, label: string, @IViewletService viewletService: IViewletService) { + super(id, label, viewletService); + this.class = 'search-action cancel-search'; + this.update(); + } + + update(): void { + const searchViewlet = this.getSearchViewlet(); + this.enabled = searchViewlet && searchViewlet.isSearching(); + } + + public run(): TPromise { + const searchViewlet = this.getSearchViewlet(); + if (searchViewlet) { + searchViewlet.cancelSearch(); + } + + return TPromise.as(null); + } +} + export class FocusNextSearchResultAction extends Action { public static readonly ID = 'search.action.focusNextSearchResult'; public static readonly LABEL = nls.localize('FocusNextSearchResult.label', "Focus Next Search Result"); diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index b47db749deb..eacdc0b2496 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -45,7 +45,7 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { PatternInputWidget, ExcludePatternInputWidget } from 'vs/workbench/parts/search/browser/patternInputWidget'; import { SearchRenderer, SearchDataSource, SearchSorter, SearchAccessibilityProvider, SearchFilter } from 'vs/workbench/parts/search/browser/searchResultsView'; import { SearchWidget, ISearchWidgetOptions } from 'vs/workbench/parts/search/browser/searchWidget'; -import { RefreshAction, CollapseDeepestExpandedLevelAction, ClearSearchResultsAction, SearchAction } from 'vs/workbench/parts/search/browser/searchActions'; +import { RefreshAction, CollapseDeepestExpandedLevelAction, ClearSearchResultsAction, SearchAction, CancelSearchAction } from 'vs/workbench/parts/search/browser/searchActions'; import { IReplaceService } from 'vs/workbench/parts/search/common/replace'; import Severity from 'vs/base/common/severity'; import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; @@ -54,12 +54,11 @@ import * as Constants from 'vs/workbench/parts/search/common/constants'; import { IThemeService, ITheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorFindMatchHighlight, diffInserted, diffRemoved, diffInsertedOutline, diffRemovedOutline, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import FileResultsNavigation from 'vs/workbench/parts/files/browser/fileResultsNavigation'; -import { IOutputService } from 'vs/workbench/parts/output/common/output'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/parts/search/common/search'; import { PreferencesEditor } from 'vs/workbench/parts/preferences/browser/preferencesEditor'; import { SimpleFileResourceDragAndDrop } from 'vs/base/parts/tree/browser/treeDnd'; import { isDiffEditor, isCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService'; +import { WorkbenchTree } from 'vs/platform/list/browser/listService'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; export class SearchViewlet extends Viewlet { @@ -82,6 +81,7 @@ export class SearchViewlet extends Viewlet { private folderMatchFocused: IContextKey; private matchFocused: IContextKey; private searchSubmitted: boolean; + private searching: boolean; private actions: SearchAction[] = []; private tree: ITree; @@ -120,9 +120,7 @@ export class SearchViewlet extends Viewlet { @IReplaceService private replaceService: IReplaceService, @IUntitledEditorService private untitledEditorService: IUntitledEditorService, @IPreferencesService private preferencesService: IPreferencesService, - @IListService private listService: IListService, - @IThemeService protected themeService: IThemeService, - @IOutputService private outputService: IOutputService + @IThemeService protected themeService: IThemeService ) { super(Constants.VIEWLET_ID, telemetryService, themeService); @@ -499,7 +497,7 @@ export class SearchViewlet extends Viewlet { let dnd = new SimpleFileResourceDragAndDrop(obj => obj instanceof FileMatch ? obj.resource() : void 0); - this.tree = new WorkbenchTree(div.getHTMLElement(), { + this.tree = this.instantiationService.createInstance(WorkbenchTree, div.getHTMLElement(), { dataSource: dataSource, renderer: renderer, sorter: new SearchSorter(), @@ -509,7 +507,7 @@ export class SearchViewlet extends Viewlet { }, { ariaLabel: nls.localize('treeAriaLabel', "Search Results"), keyboardSupport: false - }, this.contextKeyService, this.listService, this.themeService); + }); this.tree.setInput(this.viewModel.searchResult); this.toUnbind.push(renderer); @@ -788,6 +786,10 @@ export class SearchViewlet extends Viewlet { return this.searchSubmitted; } + public isSearching(): boolean { + return this.searching; + } + public hasSearchResults(): boolean { return !this.viewModel.searchResult.isEmpty(); } @@ -1069,16 +1071,17 @@ export class SearchViewlet extends Viewlet { this.progressService.show(progressTotal); this.searchWidget.searchInput.clearMessage(); + this.searching = true; + setTimeout(() => { + if (this.searching) { + this.changeActionAtPosition(0, this.instantiationService.createInstance(CancelSearchAction, CancelSearchAction.ID, CancelSearchAction.LABEL)); + } + }, 2000); this.showEmptyStage(); - let isDone = false; - const outputChannel = this.outputService.getChannel(Constants.SEARCH_OUTPUT_CHANNEL_ID); let onComplete = (completed?: ISearchComplete) => { - if (query.useRipgrep) { - outputChannel.append('\n'); - } - - isDone = true; + this.searching = false; + this.changeActionAtPosition(0, this.instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL)); // Complete up to 100% as needed if (completed && !query.useRipgrep) { @@ -1206,14 +1209,11 @@ export class SearchViewlet extends Viewlet { }; let onError = (e: any) => { - if (query.useRipgrep) { - outputChannel.append('\n'); - } - if (errors.isPromiseCanceledError(e)) { onComplete(null); } else { - isDone = true; + this.searching = false; + this.changeActionAtPosition(0, this.instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL)); progressRunner.done(); this.searchWidget.searchInput.showMessage({ content: e.message, type: MessageType.ERROR }); this.viewModel.searchResult.clear(); @@ -1231,15 +1231,11 @@ export class SearchViewlet extends Viewlet { if (p.worked) { worked = p.worked; } - - if (p.message) { - outputChannel.append(p.message); - } }; // Handle UI updates in an interval to show frequent progress and results let uiRefreshHandle = setInterval(() => { - if (isDone) { + if (!this.searching) { window.clearInterval(uiRefreshHandle); return; } @@ -1440,6 +1436,11 @@ export class SearchViewlet extends Viewlet { return this.actions; } + private changeActionAtPosition(index: number, newAction: SearchAction): void { + this.actions.splice(index, 1, newAction); + this.updateTitleArea(); + } + public shutdown(): void { const isRegex = this.searchWidget.searchInput.getRegex(); const isWholeWords = this.searchWidget.searchInput.getWholeWords(); diff --git a/src/vs/workbench/parts/search/common/constants.ts b/src/vs/workbench/parts/search/common/constants.ts index e15486d6ca5..d68fafac729 100644 --- a/src/vs/workbench/parts/search/common/constants.ts +++ b/src/vs/workbench/parts/search/common/constants.ts @@ -6,7 +6,6 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export const VIEWLET_ID = 'workbench.view.search'; -export const SEARCH_OUTPUT_CHANNEL_ID = 'search'; export const FindInFilesActionId = 'workbench.action.findInFiles'; export const FocusActiveEditorCommandId = 'search.action.focusActiveEditor'; diff --git a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts index cee75706fd2..8e6b0fe4bfe 100644 --- a/src/vs/workbench/parts/search/electron-browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/electron-browser/search.contribution.ts @@ -35,7 +35,6 @@ import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKe import { ISearchWorkbenchService, SearchWorkbenchService } from 'vs/workbench/parts/search/common/searchModel'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { SearchViewlet } from 'vs/workbench/parts/search/browser/searchViewlet'; -import { IOutputChannelRegistry, Extensions as OutputExt } from 'vs/workbench/parts/output/common/output'; import { defaultQuickOpenContextKey } from 'vs/workbench/browser/parts/quickopen/quickopen'; import { OpenSymbolHandler } from 'vs/workbench/parts/search/browser/openSymbolHandler'; import { OpenAnythingHandler } from 'vs/workbench/parts/search/browser/openAnythingHandler'; @@ -371,10 +370,6 @@ Registry.as(QuickOpenExtensions.Quickopen).registerQuickOpen ) ); -// Search output channel -const outputChannelRegistry = Registry.as(OutputExt.OutputChannels); -outputChannelRegistry.registerChannel(Constants.SEARCH_OUTPUT_CHANNEL_ID, nls.localize('searchOutputChannelTitle', "Search")); - // Configuration const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index 1aebf6b4018..4d29f195584 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import URI from 'vs/base/common/uri'; +import { UriComponents } from 'vs/base/common/uri'; import * as Types from 'vs/base/common/types'; import { IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import * as Objects from 'vs/base/common/objects'; @@ -246,7 +246,7 @@ export interface ExtensionTaskSource { } export interface ExtensionTaskSourceTransfer { - __workspaceFolder: URI; + __workspaceFolder: UriComponents; } export interface InMemoryTaskSource { diff --git a/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts b/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts index abef17d3d28..17a2eb7f79e 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/jsonSchema_v2.ts @@ -133,10 +133,10 @@ const group: IJSONSchema = { 'none' ], enumDescriptions: [ - nls.localize('JsonSchema.tasks.group.defaultBuild', 'Marks the tasks as the default build task.'), - nls.localize('JsonSchema.tasks.group.defaultTest', 'Marks the tasks as the default test task.'), - nls.localize('JsonSchema.tasks.group.build', 'Marks the tasks as a build task accesible through the \'Run Build Task\' command.'), - nls.localize('JsonSchema.tasks.group.test', 'Marks the tasks as a test task accesible through the \'Run Test Task\' command.'), + nls.localize('JsonSchema.tasks.group.defaultBuild', 'Marks the task as the default build task.'), + nls.localize('JsonSchema.tasks.group.defaultTest', 'Marks the task as the default test task.'), + nls.localize('JsonSchema.tasks.group.build', 'Marks the task as a build task accesible through the \'Run Build Task\' command.'), + nls.localize('JsonSchema.tasks.group.test', 'Marks the task as a test task accesible through the \'Run Test Task\' command.'), nls.localize('JsonSchema.tasks.group.none', 'Assigns the task to no group') ], description: nls.localize('JsonSchema.tasks.group', 'Defines to which execution group this task belongs to. It supports "build" to add it to the build group and "test" to add it to the test group.') diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index cd837dd9be5..3ad222245eb 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -47,6 +47,10 @@ export const TerminalCursorStyle = { UNDERLINE: 'underline' }; +export const TERMINAL_CONFIG_SECTION = 'terminal.integrated'; + +export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + export interface ITerminalConfiguration { shell: { linux: string; @@ -58,11 +62,13 @@ export interface ITerminalConfiguration { osx: string[]; windows: string[]; }; - enableBold: boolean; + macOptionIsMeta: boolean; rightClickCopyPaste: boolean; cursorBlinking: boolean; cursorStyle: string; fontFamily: string; + fontWeight: FontWeight; + fontWeightBold: FontWeight; // fontLigatures: boolean; fontSize: number; lineHeight: number; @@ -170,7 +176,6 @@ export interface ITerminalService { showPreviousFindTermFindWidget(): void; setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; - updateConfig(): void; selectDefaultWindowsShell(): TPromise; setWorkspaceShellAllowed(isAllowed: boolean): void; } @@ -388,4 +393,9 @@ export interface ITerminalInstance { * Sets the title of the terminal instance. */ setTitle(title: string, eventFromProcess: boolean): void; + + /** + * Enter screen reader navigation mode. + */ + enterNavigationMode(): void; } diff --git a/src/vs/workbench/parts/terminal/common/terminalService.ts b/src/vs/workbench/parts/terminal/common/terminalService.ts index 4683d7a6250..806e092c0a6 100644 --- a/src/vs/workbench/parts/terminal/common/terminalService.ts +++ b/src/vs/workbench/parts/terminal/common/terminalService.ts @@ -9,10 +9,8 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITerminalService, ITerminalInstance, IShellLaunchConfig, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/common/terminal'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; export abstract class TerminalService implements ITerminalService { public _serviceBrand: any; @@ -44,7 +42,6 @@ export abstract class TerminalService implements ITerminalService { constructor( @IContextKeyService private _contextKeyService: IContextKeyService, - @IConfigurationService protected _configurationService: IConfigurationService, @IPanelService protected _panelService: IPanelService, @IPartService private _partService: IPartService, @ILifecycleService lifecycleService: ILifecycleService @@ -60,14 +57,6 @@ export abstract class TerminalService implements ITerminalService { this._onInstanceTitleChanged = new Emitter(); this._onInstancesChanged = new Emitter(); - this._configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('terminal.integrated')) { - this.updateConfig(); - } - if (e.affectsConfiguration('editor.accessibilitySupport')) { - this.updateAccessibilitySupport(); - } - }); lifecycleService.onWillShutdown(event => event.veto(this._onWillShutdown())); lifecycleService.onShutdown(() => this._onShutdown()); this._terminalFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_FOCUS.bindTo(this._contextKeyService); @@ -240,15 +229,6 @@ export abstract class TerminalService implements ITerminalService { return terminalIndex; } - public updateConfig(): void { - this.terminalInstances.forEach(instance => instance.updateConfig()); - } - - public updateAccessibilitySupport(): void { - const isEnabled = this._configurationService.getValue('editor').accessibilitySupport === 'on'; - this.terminalInstances.forEach(instance => instance.updateAccessibilitySupport(isEnabled)); - } - public setWorkspaceShellAllowed(isAllowed: boolean): void { this.configHelper.setWorkspaceShellAllowed(isAllowed); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css index aadbf436fc4..6068c9445bd 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/xterm.css @@ -127,7 +127,7 @@ cursor: text; } -.xterm .accessibility { +.xterm .xterm-accessibility { position: absolute; left: 0; top: 0; @@ -136,10 +136,14 @@ z-index: 100; } -.xterm .accessibility-tree { +.xterm .xterm-accessibility-tree { color: transparent; } +.xterm .xterm-accessibility-tree:focus [id^="xterm-active-item-"] { + outline: 1px solid #F80; +} + .xterm .live-region { position: absolute; left: -9999px; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index e4b726a6c83..918ca090df4 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -18,7 +18,7 @@ import { TERMINAL_DEFAULT_SHELL_UNIX_LIKE, TERMINAL_DEFAULT_SHELL_WINDOWS } from import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; +import { KillTerminalAction, CopyTerminalSelectionAction, CreateNewTerminalAction, CreateNewInActiveWorkspaceTerminalAction, FocusActiveTerminalAction, FocusNextTerminalAction, FocusPreviousTerminalAction, SelectDefaultShellWindowsTerminalAction, RunSelectedTextInTerminalAction, RunActiveFileInTerminalAction, ScrollDownTerminalAction, ScrollDownPageTerminalAction, ScrollToBottomTerminalAction, ScrollUpTerminalAction, ScrollUpPageTerminalAction, ScrollToTopTerminalAction, TerminalPasteAction, ToggleTerminalAction, ClearTerminalAction, AllowWorkspaceShellTerminalCommand, DisallowWorkspaceShellTerminalCommand, RenameTerminalAction, SelectAllTerminalAction, FocusTerminalFindWidgetAction, HideTerminalFindWidgetAction, ShowNextFindTermTerminalFindWidgetAction, ShowPreviousFindTermTerminalFindWidgetAction, DeleteWordLeftTerminalAction, DeleteWordRightTerminalAction, QuickOpenActionTermContributor, QuickOpenTermAction, TERMINAL_PICKER_PREFIX, EnterNavigationModeTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; @@ -115,6 +115,11 @@ configurationRegistry.registerConfiguration({ }, 'default': [] }, + 'terminal.integrated.macOptionIsMeta': { + 'description': nls.localize('terminal.integrated.macOptionIsMeta', "Treat the option key as the meta key in the terminal on macOS."), + 'type': 'boolean', + 'default': false + }, 'terminal.integrated.rightClickCopyPaste': { 'description': nls.localize('terminal.integrated.rightClickCopyPaste', "When set, this will prevent the context menu from appearing when right clicking within the terminal, instead it will copy when there is a selection and paste when there is no selection."), 'type': 'boolean', @@ -145,10 +150,17 @@ configurationRegistry.registerConfiguration({ 'type': 'number', 'default': 1 }, - 'terminal.integrated.enableBold': { - 'type': 'boolean', - 'description': nls.localize('terminal.integrated.enableBold', "Whether to enable bold text within the terminal, note that this requires support from the terminal shell."), - 'default': true + 'terminal.integrated.fontWeight': { + 'type': 'string', + 'enum': ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], + 'description': nls.localize('terminal.integrated.fontWeight', "The font weight to use within the termianl for non-bold text."), + 'default': 'normal' + }, + 'terminal.integrated.fontWeightBold': { + 'type': 'string', + 'enum': ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], + 'description': nls.localize('terminal.integrated.fontWeightBold', "The font weight to use within the termianl for bold text."), + 'default': 'bold' }, 'terminal.integrated.cursorBlinking': { 'description': nls.localize('terminal.integrated.cursorBlinking', "Controls whether the terminal cursor blinks."), @@ -181,7 +193,7 @@ configurationRegistry.registerConfiguration({ 'default': false }, 'terminal.integrated.enableBell': { - 'description': nls.localize('terminal.integrated.enableBell', "Whether the terminal bell is enabled on not."), + 'description': nls.localize('terminal.integrated.enableBell', "Whether the terminal bell is enabled or not."), 'type': 'boolean', 'default': false }, @@ -204,6 +216,7 @@ configurationRegistry.registerConfiguration({ FocusActiveTerminalAction.ID, FocusPreviousTerminalAction.ID, FocusNextTerminalAction.ID, + EnterNavigationModeTerminalAction.ID, 'workbench.action.tasks.build', 'workbench.action.tasks.restartTask', 'workbench.action.tasks.runTask', @@ -386,8 +399,10 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DeleteWordRightT primary: KeyMod.CtrlCmd | KeyCode.Delete, mac: { primary: KeyMod.Alt | KeyCode.Delete } }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Delete Word Right', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(EnterNavigationModeTerminalAction, EnterNavigationModeTerminalAction.ID, EnterNavigationModeTerminalAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_N +}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Enter Screen Reader Navigation Mode', category); terminalCommands.setup(); registerColors(); - diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 8ab6467d691..3c1b515e62b 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -196,6 +196,27 @@ export class DeleteWordRightTerminalAction extends Action { } } +export class EnterNavigationModeTerminalAction extends Action { + + public static readonly ID = 'workbench.action.terminal.enterLineNavigationMode'; + public static readonly LABEL = nls.localize('workbench.action.terminal.enterLineNavigationMode', "Enter Screen Reader Navigation Mode"); + + constructor( + id: string, label: string, + @ITerminalService private terminalService: ITerminalService + ) { + super(id, label); + } + + public run(event?: any): TPromise { + let terminalInstance = this.terminalService.getActiveInstance(); + if (terminalInstance) { + terminalInstance.enterNavigationMode(); + } + return TPromise.as(void 0); + } +} + export class CreateNewTerminalAction extends Action { public static readonly ID = 'workbench.action.terminal.new'; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index eaae70691f3..24a10026878 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -11,21 +11,10 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IChoiceService } from 'vs/platform/message/common/message'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY } from 'vs/workbench/parts/terminal/common/terminal'; +import { ITerminalConfiguration, ITerminalConfigHelper, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION } from 'vs/workbench/parts/terminal/common/terminal'; import { TPromise } from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import { isFedora } from 'vs/workbench/parts/terminal/electron-browser/terminal'; -import { deepClone } from 'vs/base/common/objects'; - -interface IEditorConfiguration { - editor: IEditorOptions; -} - -interface IFullTerminalConfiguration { - terminal: { - integrated: ITerminalConfiguration; - }; -} const DEFAULT_LINE_HEIGHT = 1.0; @@ -41,16 +30,24 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { private _charMeasureElement: HTMLElement; private _lastFontMeasurement: ITerminalFont; + public config: ITerminalConfiguration; public constructor( @IConfigurationService private _configurationService: IConfigurationService, @IWorkspaceConfigurationService private _workspaceConfigurationService: IWorkspaceConfigurationService, @IChoiceService private _choiceService: IChoiceService, - @IStorageService private _storageService: IStorageService) { + @IStorageService private _storageService: IStorageService + ) { + this._updateConfig(); + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(TERMINAL_CONFIG_SECTION)) { + this._updateConfig(); + } + }); } - public get config(): ITerminalConfiguration { - return deepClone(this._configurationService.getValue().terminal.integrated); + private _updateConfig(): void { + this.config = this._configurationService.getValue(TERMINAL_CONFIG_SECTION); } private _measureFont(fontFamily: string, fontSize: number, lineHeight: number): ITerminalFont { @@ -89,21 +86,19 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties */ public getFont(excludeDimensions?: boolean): ITerminalFont { - const config = this._configurationService.getValue(); - const editorConfig = (config).editor; - const terminalConfig = this.config; + const editorConfig = this._configurationService.getValue('editor'); - let fontFamily = terminalConfig.fontFamily || editorConfig.fontFamily; + let fontFamily = this.config.fontFamily || editorConfig.fontFamily; // Work around bad font on Fedora - if (!terminalConfig.fontFamily) { + if (!this.config.fontFamily) { if (isFedora) { fontFamily = '\'DejaVu Sans Mono\''; } } - let fontSize = this._toInteger(terminalConfig.fontSize, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize); - const lineHeight = terminalConfig.lineHeight ? Math.max(terminalConfig.lineHeight, 1) : DEFAULT_LINE_HEIGHT; + let fontSize = this._toInteger(this.config.fontSize, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize); + const lineHeight = this.config.lineHeight ? Math.max(this.config.lineHeight, 1) : DEFAULT_LINE_HEIGHT; if (excludeDimensions) { return { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index d9b982340fb..035f619324c 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -171,6 +171,15 @@ export class TerminalInstance implements ITerminalInstance { this.attachToElement(_container); } }); + + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('terminal.integrated')) { + this.updateConfig(); + } + if (e.affectsConfiguration('editor.accessibilitySupport')) { + this.updateAccessibilitySupport(); + } + }); } public addDisposable(disposable: lifecycle.IDisposable): void { @@ -269,11 +278,13 @@ export class TerminalInstance implements ITerminalInstance { scrollback: this._configHelper.config.scrollback, theme: this._getXtermTheme(), fontFamily: font.fontFamily, + fontWeight: this._configHelper.config.fontWeight, + fontWeightBold: this._configHelper.config.fontWeightBold, fontSize: font.fontSize, lineHeight: font.lineHeight, - enableBold: this._configHelper.config.enableBold, bellStyle: this._configHelper.config.enableBell ? 'sound' : 'none', - screenReaderMode: accessibilitySupport === 'on' + screenReaderMode: accessibilitySupport === 'on', + macOptionIsMeta: this._configHelper.config.macOptionIsMeta }); if (this._shellLaunchConfig.initialText) { this._xterm.writeln(this._shellLaunchConfig.initialText); @@ -903,7 +914,13 @@ export class TerminalInstance implements ITerminalInstance { while (lineIndex >= 0 && buffer.lines.get(lineIndex--).isWrapped) { lineData = buffer.translateBufferLineToString(lineIndex, true) + lineData; } - this._onLineDataListeners.forEach(listener => listener(lineData)); + this._onLineDataListeners.forEach(listener => { + try { + listener(lineData); + } catch (err) { + console.error(`onLineData listener threw`, err); + } + }); } public onExit(listener: (exitCode: number) => void): lifecycle.IDisposable { @@ -946,6 +963,7 @@ export class TerminalInstance implements ITerminalInstance { it: 'IT', ja: 'JP', ko: 'KR', + pl: 'PL', ru: 'RU', zh: 'CN' }; @@ -965,10 +983,12 @@ export class TerminalInstance implements ITerminalInstance { this._setCommandsToSkipShell(this._configHelper.config.commandsToSkipShell); this._setScrollback(this._configHelper.config.scrollback); this._setEnableBell(this._configHelper.config.enableBell); + this._setMacOptionIsMeta(this._configHelper.config.macOptionIsMeta); } - public updateAccessibilitySupport(isEnabled: boolean): void { - this._xterm.setOption('screenReaderMode', isEnabled); + public updateAccessibilitySupport(): void { + const value = this._configurationService.getValue('editor.accessibilitySupport'); + this._xterm.setOption('screenReaderMode', value === 'on'); } private _setCursorBlink(blink: boolean): void { @@ -996,6 +1016,12 @@ export class TerminalInstance implements ITerminalInstance { } } + private _setMacOptionIsMeta(value: boolean): void { + if (this._xterm && this._xterm.getOption('macOptionIsMeta') !== value) { + this._xterm.setOption('macOptionIsMeta', value); + } + } + private _setEnableBell(isEnabled: boolean): void { if (this._xterm) { if (this._xterm.getOption('bellStyle') === 'sound') { @@ -1031,8 +1057,11 @@ export class TerminalInstance implements ITerminalInstance { if (this._xterm.getOption('fontFamily') !== font.fontFamily) { this._xterm.setOption('fontFamily', font.fontFamily); } - if (this._xterm.getOption('enableBold') !== this._configHelper.config.enableBold) { - this._xterm.setOption('enableBold', this._configHelper.config.enableBold); + if (this._xterm.getOption('fontWeight') !== this._configHelper.config.fontWeight) { + this._xterm.setOption('fontWeight', this._configHelper.config.fontWeight); + } + if (this._xterm.getOption('fontWeightBold') !== this._configHelper.config.fontWeightBold) { + this._xterm.setOption('fontWeightBold', this._configHelper.config.fontWeightBold); } } @@ -1123,6 +1152,15 @@ export class TerminalInstance implements ITerminalInstance { private _updateTheme(theme?: ITheme): void { this._xterm.setOption('theme', this._getXtermTheme(theme)); } + + public enterNavigationMode(): void { + // Perform this asynchronously as entering navigation mode will override + // the key event handlers which seemed to mess with the keybindings + // system + setTimeout(() => { + this._xterm.enterNavigationMode(); + }, 100); + } } registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index d12de43f06d..797ae1d1a3a 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -27,6 +27,7 @@ import URI from 'vs/base/common/uri'; import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; import { TERMINAL_BACKGROUND_COLOR } from 'vs/workbench/parts/terminal/electron-browser/terminalColorRegistry'; import { DataTransfers } from 'vs/base/browser/dnd'; +import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; export class TerminalPanel extends Panel { @@ -45,6 +46,7 @@ export class TerminalPanel extends Panel { @IContextMenuService private _contextMenuService: IContextMenuService, @IInstantiationService private _instantiationService: IInstantiationService, @ITerminalService private _terminalService: ITerminalService, + @ILifecycleService private _lifecycleService: ILifecycleService, @IThemeService protected themeService: IThemeService, @ITelemetryService telemetryService: ITelemetryService ) { @@ -102,16 +104,20 @@ export class TerminalPanel extends Panel { this._updateTheme(); } else { return super.setVisible(visible).then(() => { - // Allow time for the panel to display if it is being shown - // for the first time. If there is not wait here the initial - // dimensions of the pty could be wrong. - setTimeout(() => { - const instance = this._terminalService.createInstance(); - if (instance) { - this._updateFont(); - this._updateTheme(); - } - }, 0); + // Ensure the "Running" lifecycle face has been reached before creating the + // first terminal. + this._lifecycleService.when(LifecyclePhase.Running).then(() => { + // Allow time for the panel to display if it is being shown + // for the first time. If there is not wait here the initial + // dimensions of the pty could be wrong. + setTimeout(() => { + const instance = this._terminalService.createInstance(); + if (instance) { + this._updateFont(); + this._updateTheme(); + } + }, 0); + }); return TPromise.as(void 0); }); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index 915b0fd5b84..eb2eb94177d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -30,17 +30,17 @@ export class TerminalService extends AbstractTerminalService implements ITermina constructor( @IContextKeyService _contextKeyService: IContextKeyService, - @IConfigurationService _configurationService: IConfigurationService, @IPanelService _panelService: IPanelService, @IPartService _partService: IPartService, @ILifecycleService _lifecycleService: ILifecycleService, + @IConfigurationService private _configurationService: IConfigurationService, @IInstantiationService private _instantiationService: IInstantiationService, @IQuickOpenService private _quickOpenService: IQuickOpenService, @IChoiceService private _choiceService: IChoiceService, @IStorageService private _storageService: IStorageService, @IMessageService private _messageService: IMessageService ) { - super(_contextKeyService, _configurationService, _panelService, _partService, _lifecycleService); + super(_contextKeyService, _panelService, _partService, _lifecycleService); this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper); } diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index caef93152b9..ebd9dbfcdaa 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -6,24 +6,10 @@ 'use strict'; import * as assert from 'assert'; -import { IConfigurationService, getConfigurationValue, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; -import { TPromise } from 'vs/base/common/winjs.base'; import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { isFedora } from 'vs/workbench/parts/terminal/electron-browser/terminal'; - -class MockConfigurationService implements IConfigurationService { - public _serviceBrand: any; - public serviceId = IConfigurationService; - public constructor(private configuration: any = {}) { } - public inspect(key: string, overrides?: IConfigurationOverrides): any { return { value: getConfigurationValue(this.getValue(), key), default: getConfigurationValue(this.getValue(), key), user: getConfigurationValue(this.getValue(), key), workspace: void 0, workspaceFolder: void 0 }; } - public keys() { return { default: [] as string[], user: [] as string[], workspace: [] as string[], workspaceFolder: [] as string[] }; } - public getValue(): any { return this.configuration; } - public updateValue(): TPromise { return null; } - public getConfigurationData(): any { return null; } - public onDidChangeConfiguration() { return { dispose() { } }; } - public reloadConfiguration(): TPromise { return null; } -} +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; suite('Workbench - TerminalConfigHelper', () => { let fixture: HTMLElement; @@ -33,33 +19,17 @@ suite('Workbench - TerminalConfigHelper', () => { }); test('TerminalConfigHelper - getFont fontFamily', function () { - let configurationService: IConfigurationService; - let configHelper: TerminalConfigHelper; + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); + configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: 'bar' } }); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo' - }, - terminal: { - integrated: { - fontFamily: 'bar' - } - } - }); - configHelper = new TerminalConfigHelper(configurationService, null, null, null); + let configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontFamily, 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily'); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo' - }, - terminal: { - integrated: { - fontFamily: 0 - } - } - }); + configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); + + // Recreate config helper as onDidChangeConfiguration isn't implemented in TestConfigurationService configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; if (isFedora) { @@ -70,64 +40,55 @@ suite('Workbench - TerminalConfigHelper', () => { }); test('TerminalConfigHelper - getFont fontSize', function () { - let configurationService: IConfigurationService; - let configHelper: TerminalConfigHelper; + const configurationService = new TestConfigurationService(); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo', - fontSize: 9 - }, - terminal: { - integrated: { - fontFamily: 'bar', - fontSize: 10 - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + fontSize: 9 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 'bar', + fontSize: 10 } }); - configHelper = new TerminalConfigHelper(configurationService, null, null, null); + let configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo' - }, - terminal: { - integrated: { - fontFamily: 0, - fontSize: 0 - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: null, + fontSize: 0 } }); configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo' - }, - terminal: { - integrated: { - fontFamily: 0, - fontSize: 1500 - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + fontSize: 1500 } }); configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it'); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo', - }, - terminal: { - integrated: { - fontFamily: 0, - fontSize: null - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + fontSize: null } }); configHelper = new TerminalConfigHelper(configurationService, null, null, null); @@ -136,35 +97,30 @@ suite('Workbench - TerminalConfigHelper', () => { }); test('TerminalConfigHelper - getFont lineHeight', function () { - let configurationService: IConfigurationService; - let configHelper: TerminalConfigHelper; + const configurationService = new TestConfigurationService(); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo', - lineHeight: 1 - }, - terminal: { - integrated: { - fontFamily: 0, - lineHeight: 2 - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + lineHeight: 1 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + lineHeight: 2 } }); - configHelper = new TerminalConfigHelper(configurationService, null, null, null); + let configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight'); - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo', - lineHeight: 1 - }, - terminal: { - integrated: { - fontFamily: 0, - lineHeight: 0 - } + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + lineHeight: 1 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + lineHeight: 0 } }); configHelper = new TerminalConfigHelper(configurationService, null, null, null); diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts index a7f066b25bd..1dadac1f411 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalInstance.test.ts @@ -21,8 +21,11 @@ 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'; +import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; class TestTerminalInstance extends TerminalInstance { + public _getCwd(shell: IShellLaunchConfig, root: Uri): string { return super._getCwd(shell, root); } @@ -152,6 +155,7 @@ suite('Workbench - TerminalInstance', () => { let keybindingService = new MockKeybindingService(); let terminalFocusContextKey = contextKeyService.createKey('test', false); instantiationService = new TestInstantiationService(); + instantiationService.stub(IConfigurationService, new TestConfigurationService()); instantiationService.stub(IMessageService, new TestMessageService()); instantiationService.stub(IWorkspaceContextService, new TestContextService()); instantiationService.stub(IKeybindingService, keybindingService); diff --git a/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts b/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts index 27632cdde54..b78a3529a97 100644 --- a/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts +++ b/src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts @@ -29,14 +29,18 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { addGAParameters } from 'vs/platform/telemetry/node/telemetryNodeUtils'; import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization'; -function renderBody(body: string, css: string): string { +function renderBody( + body: string, + css: string +): string { + const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-core-resource://'); return ` - - + + ${body} @@ -52,14 +56,14 @@ export class ReleaseNotesEditor extends WebviewEditor { constructor( @ITelemetryService telemetryService: ITelemetryService, - @IEnvironmentService private environmentService: IEnvironmentService, @IThemeService protected themeService: IThemeService, + @IStorageService storageService: IStorageService, + @IContextKeyService contextKeyService: IContextKeyService, + @IEnvironmentService private environmentService: IEnvironmentService, @IOpenerService private openerService: IOpenerService, @IModeService private modeService: IModeService, @IPartService private partService: IPartService, - @IStorageService storageService: IStorageService, - @IContextViewService private _contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextViewService private _contextViewService: IContextViewService ) { super(ReleaseNotesEditor.ID, telemetryService, themeService, storageService, contextKeyService); } @@ -100,7 +104,7 @@ export class ReleaseNotesEditor extends WebviewEditor { const colorMap = TokenizationRegistry.getColorMap(); const css = generateTokensCSSForColorMap(colorMap); const body = renderBody(marked(text, { renderer }), css); - this._webview = new WebView(this.content, this.partService.getContainer(Parts.EDITOR_PART), this._contextViewService, this.contextKey, this.findInputFocusContextKey); + this._webview = new WebView(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.environmentService, this._contextViewService, this.contextKey, this.findInputFocusContextKey, {}, false); if (this.input && this.input instanceof ReleaseNotesInput) { const state = this.loadViewState(this.input.version); if (state) { diff --git a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts index d93239ac3ca..6b6cc303dd5 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.contribution.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.contribution.ts @@ -7,6 +7,7 @@ import * as nls from 'vs/nls'; import 'vs/css!./media/update.contribution'; +import product from 'vs/platform/node/product'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ReleaseNotesEditor } from 'vs/workbench/parts/update/electron-browser/releaseNotesEditor'; @@ -57,6 +58,11 @@ configurationRegistry.registerConfiguration({ 'enum': ['none', 'default'], 'default': 'default', 'description': nls.localize('updateChannel', "Configure whether you receive automatic updates from an update channel. Requires a restart after change.") + }, + 'update.enableWindowsBackgroundUpdates': { + 'type': 'boolean', + 'default': product.quality === 'insider', + 'description': nls.localize('enableWindowsBackgroundUpdates', "Enables Windows background updates.") } } }); diff --git a/src/vs/workbench/parts/update/electron-browser/update.ts b/src/vs/workbench/parts/update/electron-browser/update.ts index a64d44eed6c..380a3c068eb 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.ts @@ -9,7 +9,6 @@ import nls = require('vs/nls'); import severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, Action } from 'vs/base/common/actions'; -import { mapEvent } from 'vs/base/common/event'; import { IDisposable, dispose, empty as EmptyDisposable } from 'vs/base/common/lifecycle'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IMessageService, CloseAction, Severity } from 'vs/platform/message/common/message'; @@ -17,7 +16,7 @@ import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; import URI from 'vs/base/common/uri'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; +import { IActivityService, NumberBadge, IBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput'; import { IGlobalActivity } from 'vs/workbench/common/activity'; @@ -29,21 +28,11 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; +import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update'; import * as semver from 'semver'; -import { OS, isLinux, isWindows } from 'vs/base/common/platform'; +import { OS } from 'vs/base/common/platform'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -class ApplyUpdateAction extends Action { - constructor( @IUpdateService private updateService: IUpdateService) { - super('update.applyUpdate', nls.localize('updateNow', "Update Now"), null, true); - } - - run(): TPromise { - return this.updateService.quitAndInstall(); - } -} - const NotNowAction = new Action( 'update.later', nls.localize('later', "Later"), @@ -178,17 +167,6 @@ export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesActio } } -export class DownloadAction extends Action { - - constructor( @IUpdateService private updateService: IUpdateService) { - super('update.download', nls.localize('downloadNow', "Download Now"), null, true); - } - - run(): TPromise { - return this.updateService.quitAndInstall(); - } -} - const LinkAction = (id: string, message: string, licenseUrl: string) => new Action( id, message, null, true, () => { window.open(licenseUrl); return TPromise.as(null); } @@ -316,6 +294,7 @@ export class UpdateContribution implements IGlobalActivity { get name() { return ''; } get cssClass() { return 'update-activity'; } + private state: UpdateState; private badgeDisposable: IDisposable = EmptyDisposable; private disposables: IDisposable[] = []; @@ -328,13 +307,7 @@ export class UpdateContribution implements IGlobalActivity { @IWorkbenchEditorService editorService: IWorkbenchEditorService, @IActivityService private activityService: IActivityService ) { - const onUpdateAvailable = isLinux - ? mapEvent(updateService.onUpdateAvailable, e => e.version) - : mapEvent(updateService.onUpdateReady, e => e.version); - - onUpdateAvailable(this.onUpdateAvailable, this, this.disposables); - updateService.onError(this.onError, this, this.disposables); - updateService.onUpdateNotAvailable(this.onUpdateNotAvailable, this, this.disposables); + this.state = updateService.state; updateService.onStateChange(this.onUpdateStateChange, this, this.disposables); this.onUpdateStateChange(this.updateService.state); @@ -358,19 +331,116 @@ export class UpdateContribution implements IGlobalActivity { } private onUpdateStateChange(state: UpdateState): void { + switch (state.type) { + case StateType.Idle: + if (this.state.type === StateType.CheckingForUpdates && this.state.explicit) { + this.onUpdateNotAvailable(); + } + break; + + case StateType.AvailableForDownload: + this.onUpdateAvailable(state.update); + break; + + case StateType.Downloaded: + this.onUpdateDownloaded(state.update); + break; + + case StateType.Updating: + this.onUpdateUpdating(state.update); + break; + + case StateType.Ready: + this.onUpdateReady(state.update); + break; + } + + let badge: IBadge | undefined = undefined; + let clazz: string | undefined; + + if (state.type === StateType.AvailableForDownload || state.type === StateType.Downloaded || state.type === StateType.Ready) { + badge = new NumberBadge(1, () => nls.localize('updateIsReady', "New {0} update available.", product.nameShort)); + } else if (state.type === StateType.CheckingForUpdates || state.type === StateType.Downloading || state.type === StateType.Updating) { + badge = new ProgressBadge(() => nls.localize('updateIsReady', "New {0} update available.", product.nameShort)); + clazz = 'progress-badge'; + } + this.badgeDisposable.dispose(); - const isUpdateAvailable = isLinux - ? state === UpdateState.UpdateAvailable - : state === UpdateState.UpdateDownloaded; - - if (isUpdateAvailable) { - const badge = new NumberBadge(1, () => nls.localize('updateIsReady', "New {0} update available.", product.nameShort)); - this.badgeDisposable = this.activityService.showActivity(this.id, badge); + if (badge) { + this.badgeDisposable = this.activityService.showActivity(this.id, badge, clazz); } + + this.state = state; } - private onUpdateAvailable(version: string): void { + private onUpdateNotAvailable(): void { + this.messageService.show(severity.Info, nls.localize('noUpdatesAvailable', "There are no updates currently available.")); + } + + // linux + private onUpdateAvailable(update: IUpdate): void { + if (!this.shouldShowNotification()) { + return; + } + + const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + const downloadAction = new Action('update.downloadNow', nls.localize('download now', "Download Now"), null, true, () => + this.updateService.downloadUpdate()); + + this.messageService.show(severity.Info, { + message: nls.localize('thereIsUpdateAvailable', "There is an available update."), + actions: [downloadAction, NotNowAction, releaseNotesAction] + }); + } + + // windows fast updates + private onUpdateDownloaded(update: IUpdate): void { + if (!this.shouldShowNotification()) { + return; + } + + const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + const installUpdateAction = new Action('update.applyUpdate', nls.localize('installUpdate', "Install Update"), undefined, true, () => + this.updateService.applyUpdate()); + + this.messageService.show(severity.Info, { + message: nls.localize('updateAvailable', "There's an available update: {0} {1}", product.nameLong, update.productVersion), + actions: [installUpdateAction, NotNowAction, releaseNotesAction] + }); + } + + // windows fast updates + private onUpdateUpdating(update: IUpdate): void { + const neverShowAgain = new NeverShowAgain('update/win32-fast-updates', this.storageService); + + if (!neverShowAgain.shouldShow()) { + return; + } + + this.messageService.show(severity.Info, { + message: nls.localize('updateInstalling', "{0} {1} is being installed in the background, we'll let you know when it's done.", product.nameLong, update.productVersion), + actions: [CloseAction, neverShowAgain.action] + }); + } + + // windows and mac + private onUpdateReady(update: IUpdate): void { + if (!this.shouldShowNotification()) { + return; + } + + const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, update.productVersion); + const applyUpdateAction = new Action('update.applyUpdate', nls.localize('updateNow', "Update Now"), undefined, true, () => + this.updateService.quitAndInstall()); + + this.messageService.show(severity.Info, { + message: nls.localize('updateAvailableAfterRestart', "{0} will be updated after it restarts.", product.nameLong), + actions: [applyUpdateAction, NotNowAction, releaseNotesAction] + }); + } + + private shouldShowNotification(): boolean { const currentVersion = product.commit; const currentMillis = new Date().getTime(); const lastKnownVersion = this.storageService.get('update/lastKnownVersion', StorageScope.GLOBAL); @@ -384,48 +454,11 @@ export class UpdateContribution implements IGlobalActivity { const updateNotificationMillis = this.storageService.getInteger('update/updateNotificationTime', StorageScope.GLOBAL, currentMillis); const diffDays = (currentMillis - updateNotificationMillis) / (1000 * 60 * 60 * 24); - // if 5 days have passed from stored date, show message service - if (diffDays > 5) { - this.showUpdateNotification(version); - } - } - - private showUpdateNotification(version: string): void { - const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, version); - - if (isLinux) { - const downloadAction = this.instantiationService.createInstance(DownloadAction); - - this.messageService.show(severity.Info, { - message: nls.localize('thereIsUpdateAvailable', "There is an available update."), - actions: [downloadAction, NotNowAction, releaseNotesAction] - }); - } else { - const applyUpdateAction = this.instantiationService.createInstance(ApplyUpdateAction); - - this.messageService.show(severity.Info, { - message: nls.localize('updateAvailable', "{0} will be updated after it restarts.", product.nameLong), - actions: [applyUpdateAction, NotNowAction, releaseNotesAction] - }); - } - } - - private onUpdateNotAvailable(explicit: boolean): void { - if (!explicit) { - return; - } - - this.messageService.show(severity.Info, nls.localize('noUpdatesAvailable', "There are no updates currently available.")); - } - - private onError(err: any): void { - this.messageService.show(severity.Error, err); + return diffDays > 5; } getActions(): IAction[] { - const updateAction = this.getUpdateAction(); - - return [ + const result: IAction[] = [ new CommandAction(UpdateContribution.showCommandsId, nls.localize('commandPalette', "Command Palette..."), this.commandService), new Separator(), new CommandAction(UpdateContribution.openSettingsId, nls.localize('settings', "Settings"), this.commandService), @@ -434,39 +467,49 @@ export class UpdateContribution implements IGlobalActivity { new CommandAction(UpdateContribution.openUserSnippets, nls.localize('userSnippets', "User Snippets"), this.commandService), new Separator(), new CommandAction(UpdateContribution.selectColorThemeId, nls.localize('selectTheme.label', "Color Theme"), this.commandService), - new CommandAction(UpdateContribution.selectIconThemeId, nls.localize('themes.selectIconTheme.label', "File Icon Theme"), this.commandService), - new Separator(), - updateAction + new CommandAction(UpdateContribution.selectIconThemeId, nls.localize('themes.selectIconTheme.label', "File Icon Theme"), this.commandService) ]; + + const updateAction = this.getUpdateAction(); + + if (updateAction) { + result.push(new Separator(), updateAction); + } + + return result; } - private getUpdateAction(): IAction { - switch (this.updateService.state) { - case UpdateState.Uninitialized: - return new Action('update.notavailable', nls.localize('not available', "Updates Not Available"), undefined, false); + private getUpdateAction(): IAction | null { + const state = this.updateService.state; - case UpdateState.CheckingForUpdate: + switch (state.type) { + case StateType.Uninitialized: + return null; + + case StateType.Idle: + return new Action('update.check', nls.localize('checkForUpdates', "Check for Updates..."), undefined, true, () => + this.updateService.checkForUpdates(true)); + + case StateType.CheckingForUpdates: return new Action('update.checking', nls.localize('checkingForUpdates', "Checking For Updates..."), undefined, false); - case UpdateState.UpdateAvailable: - if (isLinux) { - return new Action('update.linux.available', nls.localize('DownloadUpdate', "Download Available Update"), undefined, true, () => - this.updateService.quitAndInstall()); - } + case StateType.AvailableForDownload: + return new Action('update.downloadNow', nls.localize('download now', "Download Now"), null, true, () => + this.updateService.downloadUpdate()); - const updateAvailableLabel = isWindows - ? nls.localize('DownloadingUpdate', "Downloading Update...") - : nls.localize('InstallingUpdate', "Installing Update..."); + case StateType.Downloading: + return new Action('update.downloading', nls.localize('DownloadingUpdate', "Downloading Update..."), undefined, false); - return new Action('update.available', updateAvailableLabel, undefined, false); + case StateType.Downloaded: + return new Action('update.install', nls.localize('installUpdate...', "Install Update..."), undefined, true, () => + this.updateService.applyUpdate()); - case UpdateState.UpdateDownloaded: + case StateType.Updating: + return new Action('update.updating', nls.localize('installingUpdate', "Installing Update..."), undefined, false); + + case StateType.Ready: return new Action('update.restart', nls.localize('restartToUpdate', "Restart to Update..."), undefined, true, () => this.updateService.quitAndInstall()); - - default: - return new Action('update.check', nls.localize('checkForUpdates', "Check for Updates..."), undefined, this.updateService.state === UpdateState.Idle, () => - this.updateService.checkForUpdates(true)); } } diff --git a/src/vs/workbench/services/backup/common/backup.ts b/src/vs/workbench/services/backup/common/backup.ts index 7228988ab14..86d5326107e 100644 --- a/src/vs/workbench/services/backup/common/backup.ts +++ b/src/vs/workbench/services/backup/common/backup.ts @@ -8,13 +8,13 @@ import Uri from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IResolveContentOptions, IUpdateContentOptions } from 'vs/platform/files/common/files'; +import { IResolveContentOptions, IUpdateContentOptions, ITextSnapshot } from 'vs/platform/files/common/files'; import { ITextBufferFactory } from 'vs/editor/common/model'; export const IBackupFileService = createDecorator('backupFileService'); -export const BACKUP_FILE_RESOLVE_OPTIONS: IResolveContentOptions = { acceptTextOnly: true, encoding: 'utf-8' }; -export const BACKUP_FILE_UPDATE_OPTIONS: IUpdateContentOptions = { encoding: 'utf-8' }; +export const BACKUP_FILE_RESOLVE_OPTIONS: IResolveContentOptions = { acceptTextOnly: true, encoding: 'utf8' }; +export const BACKUP_FILE_UPDATE_OPTIONS: IUpdateContentOptions = { encoding: 'utf8' }; /** * A service that handles any I/O and state associated with the backup system. @@ -52,10 +52,10 @@ export interface IBackupFileService { * Backs up a resource. * * @param resource The resource to back up. - * @param content The content of the resource. + * @param content The content of the resource as snapshot. * @param versionId The version id of the resource to backup. */ - backupResource(resource: Uri, content: string, versionId?: number): TPromise; + backupResource(resource: Uri, content: ITextSnapshot, versionId?: number): TPromise; /** * Gets a list of file backups for the current workspace. @@ -65,13 +65,12 @@ export interface IBackupFileService { getWorkspaceFileBackups(): TPromise; /** - * Parses backup raw text content into the content, removing the metadata that is also stored - * in the file. + * Resolves the backup for the given resource. * - * @param textBufferFactory The ITextBufferFactory from a backup resource. - * @return The backup file's backed up content. + * @param value The contents from a backup resource as stream. + * @return The backup file's backed up content as text buffer factory. */ - parseBackupContent(textBufferFactory: ITextBufferFactory): string; + resolveBackupContent(backup: Uri): TPromise; /** * Discards the backup associated with a resource if it exists.. diff --git a/src/vs/workbench/services/backup/node/backupFileService.ts b/src/vs/workbench/services/backup/node/backupFileService.ts index ff3543726ce..fdeea689752 100644 --- a/src/vs/workbench/services/backup/node/backupFileService.ts +++ b/src/vs/workbench/services/backup/node/backupFileService.ts @@ -10,12 +10,12 @@ import * as crypto from 'crypto'; import * as pfs from 'vs/base/node/pfs'; import Uri from 'vs/base/common/uri'; import { ResourceQueue } from 'vs/base/common/async'; -import { IBackupFileService, BACKUP_FILE_UPDATE_OPTIONS } from 'vs/workbench/services/backup/common/backup'; -import { IFileService } from 'vs/platform/files/common/files'; +import { IBackupFileService, BACKUP_FILE_UPDATE_OPTIONS, BACKUP_FILE_RESOLVE_OPTIONS } from 'vs/workbench/services/backup/common/backup'; +import { IFileService, ITextSnapshot } from 'vs/platform/files/common/files'; import { TPromise } from 'vs/base/common/winjs.base'; import { readToMatchingString } from 'vs/base/node/stream'; -import { Range } from 'vs/editor/common/core/range'; -import { DefaultEndOfLine, ITextBufferFactory, EndOfLinePreference } from 'vs/editor/common/model'; +import { ITextBufferFactory } from 'vs/editor/common/model'; +import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel'; export interface IBackupFilesModel { resolve(backupRoot: string): TPromise; @@ -28,6 +28,28 @@ export interface IBackupFilesModel { clear(): void; } +export class BackupSnapshot implements ITextSnapshot { + private preambleHandled: boolean; + + constructor(private snapshot: ITextSnapshot, private preamble: string) { + } + + public read(): string { + let value = this.snapshot.read(); + if (!this.preambleHandled) { + this.preambleHandled = true; + + if (typeof value === 'string') { + value = this.preamble + value; + } else { + value = this.preamble; + } + } + + return value; + } +} + export class BackupFilesModel implements IBackupFilesModel { private cache: { [resource: string]: number /* version ID */ } = Object.create(null); @@ -149,7 +171,7 @@ export class BackupFileService implements IBackupFileService { }); } - public backupResource(resource: Uri, content: string, versionId?: number): TPromise { + public backupResource(resource: Uri, content: ITextSnapshot, versionId?: number): TPromise { if (this.isShuttingDown) { return TPromise.as(void 0); } @@ -164,11 +186,11 @@ export class BackupFileService implements IBackupFileService { return void 0; // return early if backup version id matches requested one } - // Add metadata to top of file - content = `${resource.toString()}${BackupFileService.META_MARKER}${content}`; - return this.ioOperationQueues.queueFor(backupResource).queue(() => { - return this.fileService.updateContent(backupResource, content, BACKUP_FILE_UPDATE_OPTIONS).then(() => model.add(backupResource, versionId)); + const preamble = `${resource.toString()}${BackupFileService.META_MARKER}`; + + // Update content with value + return this.fileService.updateContent(backupResource, new BackupSnapshot(content, preamble), BACKUP_FILE_UPDATE_OPTIONS).then(() => model.add(backupResource, versionId)); }); }); } @@ -213,12 +235,27 @@ export class BackupFileService implements IBackupFileService { }); } - public parseBackupContent(textBufferFactory: ITextBufferFactory): string { - // The first line of a backup text file is the file name - const textBuffer = textBufferFactory.create(DefaultEndOfLine.LF); - const lineCount = textBuffer.getLineCount(); - const range = new Range(2, 1, lineCount, textBuffer.getLineLength(lineCount) + 1); - return textBuffer.getValueInRange(range, EndOfLinePreference.TextDefined); + public resolveBackupContent(backup: Uri): TPromise { + return this.fileService.resolveStreamContent(backup, BACKUP_FILE_RESOLVE_OPTIONS).then(content => { + + // Add a filter method to filter out everything until the meta marker + let metaFound = false; + const metaPreambleFilter = (chunk: string) => { + if (!metaFound && chunk) { + const metaIndex = chunk.indexOf(BackupFileService.META_MARKER); + if (metaIndex === -1) { + return ''; // meta not yet found, return empty string + } + + metaFound = true; + return chunk.substr(metaIndex + 1); // meta found, return everything after + } + + return chunk; + }; + + return createTextBufferFactoryFromStream(content.value, metaPreambleFilter); + }); } public toBackupResource(resource: Uri): Uri { diff --git a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts index 84ae8794ec7..2b9552200f4 100644 --- a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts @@ -16,10 +16,12 @@ import pfs = require('vs/base/node/pfs'); import Uri from 'vs/base/common/uri'; import { BackupFileService, BackupFilesModel } from 'vs/workbench/services/backup/node/backupFileService'; import { FileService } from 'vs/workbench/services/files/node/fileService'; -import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; +import { TextModel, createTextBufferFactory } from 'vs/editor/common/model/textModel'; import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService } from 'vs/workbench/test/workbenchTestServices'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { DefaultEndOfLine } from 'vs/editor/common/model'; +import { snapshotToString } from 'vs/platform/files/common/files'; const parentDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); const backupHome = path.join(parentDir, 'Backups'); @@ -105,7 +107,7 @@ suite('BackupFileService', () => { suite('backupResource', () => { test('text file', function (done: () => void) { - service.backupResource(fooFile, 'test').then(() => { + service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); assert.equal(fs.existsSync(fooBackupPath), true); assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); @@ -114,18 +116,68 @@ suite('BackupFileService', () => { }); test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, 'test').then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); assert.equal(fs.existsSync(untitledBackupPath), true); assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\ntest`); done(); }); }); + + test('text file (ITextSnapshot)', function (done: () => void) { + const model = TextModel.createFromString('test'); + + service.backupResource(fooFile, model.createSnapshot()).then(() => { + assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); + assert.equal(fs.existsSync(fooBackupPath), true); + assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\ntest`); + model.dispose(); + done(); + }); + }); + + test('untitled file (ITextSnapshot)', function (done: () => void) { + const model = TextModel.createFromString('test'); + + service.backupResource(untitledFile, model.createSnapshot()).then(() => { + assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); + assert.equal(fs.existsSync(untitledBackupPath), true); + assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\ntest`); + model.dispose(); + done(); + }); + }); + + test('text file (large file, ITextSnapshot)', function (done: () => void) { + const largeString = (new Array(10 * 1024)).join('Large String\n'); + const model = TextModel.createFromString(largeString); + + service.backupResource(fooFile, model.createSnapshot()).then(() => { + assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); + assert.equal(fs.existsSync(fooBackupPath), true); + assert.equal(fs.readFileSync(fooBackupPath), `${fooFile.toString()}\n${largeString}`); + model.dispose(); + done(); + }); + }); + + test('untitled file (large file, ITextSnapshot)', function (done: () => void) { + const largeString = (new Array(10 * 1024)).join('Large String\n'); + const model = TextModel.createFromString(largeString); + + service.backupResource(untitledFile, model.createSnapshot()).then(() => { + assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); + assert.equal(fs.existsSync(untitledBackupPath), true); + assert.equal(fs.readFileSync(untitledBackupPath), `${untitledFile.toString()}\n${largeString}`); + model.dispose(); + done(); + }); + }); }); suite('discardResourceBackup', () => { test('text file', function (done: () => void) { - service.backupResource(fooFile, 'test').then(() => { + service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); service.discardResourceBackup(fooFile).then(() => { assert.equal(fs.existsSync(fooBackupPath), false); @@ -136,7 +188,7 @@ suite('BackupFileService', () => { }); test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, 'test').then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); service.discardResourceBackup(untitledFile).then(() => { assert.equal(fs.existsSync(untitledBackupPath), false); @@ -149,9 +201,9 @@ suite('BackupFileService', () => { suite('discardAllWorkspaceBackups', () => { test('text file', function (done: () => void) { - service.backupResource(fooFile, 'test').then(() => { + service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1); - service.backupResource(barFile, 'test').then(() => { + service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 2); service.discardAllWorkspaceBackups().then(() => { assert.equal(fs.existsSync(fooBackupPath), false); @@ -164,7 +216,7 @@ suite('BackupFileService', () => { }); test('untitled file', function (done: () => void) { - service.backupResource(untitledFile, 'test').then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1); service.discardAllWorkspaceBackups().then(() => { assert.equal(fs.existsSync(untitledBackupPath), false); @@ -176,7 +228,7 @@ suite('BackupFileService', () => { test('should disable further backups', function (done: () => void) { service.discardAllWorkspaceBackups().then(() => { - service.backupResource(untitledFile, 'test').then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { assert.equal(fs.existsSync(workspaceBackupPath), false); done(); }); @@ -186,10 +238,10 @@ suite('BackupFileService', () => { suite('getWorkspaceFileBackups', () => { test('("file") - text file', done => { - service.backupResource(fooFile, `test`).then(() => { + service.backupResource(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [fooFile.fsPath]); - service.backupResource(barFile, `test`).then(() => { + service.backupResource(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [fooFile.fsPath, barFile.fsPath]); done(); @@ -200,7 +252,7 @@ suite('BackupFileService', () => { }); test('("file") - untitled file', done => { - service.backupResource(untitledFile, `test`).then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), [untitledFile.fsPath]); done(); @@ -209,7 +261,7 @@ suite('BackupFileService', () => { }); test('("untitled") - untitled file', done => { - service.backupResource(untitledFile, `test`).then(() => { + service.backupResource(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { service.getWorkspaceFileBackups().then(textFiles => { assert.deepEqual(textFiles.map(f => f.fsPath), ['Untitled-1']); done(); @@ -218,10 +270,29 @@ suite('BackupFileService', () => { }); }); - test('parseBackupContent', () => { - test('should separate metadata from content', () => { - const textBufferFactory = createTextBufferFactory('metadata\ncontent'); - assert.equal(service.parseBackupContent(textBufferFactory), 'content'); + test('resolveBackupContent', () => { + test('should restore the original contents (untitled file)', () => { + const contents = 'test\nand more stuff'; + service.backupResource(untitledFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + service.resolveBackupContent(service.toBackupResource(untitledFile)).then(factory => { + assert.equal(contents, snapshotToString(factory.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(true))); + }); + }); + }); + + test('should restore the original contents (text file)', () => { + const contents = [ + 'Lorem ipsum ', + 'dolor öäü sit amet ', + 'consectetur ', + 'adipiscing ßß elit', + ].join(''); + + service.backupResource(fooFile, createTextBufferFactory(contents).create(DefaultEndOfLine.LF).createSnapshot(false)).then(() => { + service.resolveBackupContent(service.toBackupResource(untitledFile)).then(factory => { + assert.equal(contents, snapshotToString(factory.create(platform.isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).createSnapshot(true))); + }); + }); }); }); }); diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index 4ca66967670..3bdae770e7a 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -23,10 +23,11 @@ export const defaultSettingsSchemaId = 'vscode://schemas/settings/default'; export const userSettingsSchemaId = 'vscode://schemas/settings/user'; export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace'; export const folderSettingsSchemaId = 'vscode://schemas/settings/folder'; +export const launchSchemaId = 'vscode://schemas/launch'; export const TASKS_CONFIGURATION_KEY = 'tasks'; export const LAUNCH_CONFIGURATION_KEY = 'launch'; export const WORKSPACE_STANDALONE_CONFIGURATIONS = Object.create(null); WORKSPACE_STANDALONE_CONFIGURATIONS[TASKS_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/tasks.json`; -WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/launch.json`; \ No newline at end of file +WORKSPACE_STANDALONE_CONFIGURATIONS[LAUNCH_CONFIGURATION_KEY] = `${FOLDER_CONFIG_FOLDER_NAME}/launch.json`; diff --git a/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts index bdd9c346c22..a15de28318b 100644 --- a/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts +++ b/src/vs/workbench/services/configuration/common/configurationExtensionPoint.ts @@ -10,7 +10,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ExtensionsRegistry, IExtensionPointUser } from 'vs/platform/extensions/common/extensionsRegistry'; import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import { workspaceSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; +import { workspaceSettingsSchemaId, launchSchemaId } from 'vs/workbench/services/configuration/common/configuration'; const configurationRegistry = Registry.as(Extensions.Configuration); @@ -94,7 +94,7 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint { const configurations: IConfigurationNode[] = []; - function handleConfiguration(node: IConfigurationNode, id: string, extension: IExtensionPointUser) { + function handleConfiguration(node: IConfigurationNode, extension: IExtensionPointUser) { let configuration = objects.deepClone(node); if (configuration.title && (typeof configuration.title !== 'string')) { @@ -103,17 +103,17 @@ configurationExtPoint.setHandler(extensions => { validateProperties(configuration, extension); - configuration.id = id; + configuration.id = extension.description.uuid || extension.description.id; + configuration.title = configuration.title || extension.description.displayName || extension.description.id; configurations.push(configuration); } for (let extension of extensions) { const value = extension.value; - const id = extension.description.id; if (!Array.isArray(value)) { - handleConfiguration(value, id, extension); + handleConfiguration(value, extension); } else { - value.forEach(v => handleConfiguration(v, id, extension)); + value.forEach(v => handleConfiguration(v, extension)); } } configurationRegistry.registerConfigurations(configurations, registeredDefaultConfigurations, false); @@ -201,6 +201,12 @@ jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', { description: nls.localize('workspaceConfig.settings.description', "Workspace settings"), $ref: workspaceSettingsSchemaId }, + 'launch': { + type: 'object', + default: { configurations: [], compounds: [] }, + description: nls.localize('workspaceConfig.launch.description', "Workspace launch configurations"), + $ref: launchSchemaId + }, 'extensions': { type: 'object', default: {}, diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index 2d9b9a6bd33..27be593edfe 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -14,7 +14,7 @@ import { Workspace } from 'vs/platform/workspace/common/workspace'; import { StrictResourceMap } from 'vs/base/common/map'; import URI from 'vs/base/common/uri'; -export class WorkspaceSettingsModel extends ConfigurationModel { +export class SettingsModel extends ConfigurationModel { private _unsupportedKeys: string[]; @@ -32,30 +32,49 @@ export class WorkspaceSettingsModel extends ConfigurationModel { export class WorkspaceConfigurationModelParser extends ConfigurationModelParser { private _folders: IStoredWorkspaceFolder[] = []; - private _workspaceSettingsModelParser: FolderSettingsModelParser; + private _settingsModelParser: FolderSettingsModelParser; + private _launchModel: ConfigurationModel; constructor(name: string) { super(name); - this._workspaceSettingsModelParser = new FolderSettingsModelParser(name); + this._settingsModelParser = new FolderSettingsModelParser(name); + this._launchModel = new ConfigurationModel(); } get folders(): IStoredWorkspaceFolder[] { return this._folders; } - get workspaceSettingsModel(): WorkspaceSettingsModel { - return this._workspaceSettingsModelParser.folderSettingsModel; + get settingsModel(): SettingsModel { + return this._settingsModelParser.settingsModel; + } + + get launchModel(): ConfigurationModel { + return this._launchModel; } reprocessWorkspaceSettings(): void { - this._workspaceSettingsModelParser.reprocess(); + this._settingsModelParser.reprocess(); } protected parseRaw(raw: any): IConfigurationModel { this._folders = (raw['folders'] || []) as IStoredWorkspaceFolder[]; - this._workspaceSettingsModelParser.parse(raw['settings']); + this._settingsModelParser.parse(raw['settings']); + this._launchModel = this.createConfigurationModelFrom(raw, 'launch'); return super.parseRaw(raw); } + + private createConfigurationModelFrom(raw: any, key: string): ConfigurationModel { + const data = raw[key]; + if (data) { + const contents = toValuesTree(data, message => console.error(`Conflict in settings file ${this._name}: ${message}`)); + const scopedContents = Object.create(null); + scopedContents[key] = contents; + const keys = Object.keys(data).map(k => `${key}.${k}`); + return new ConfigurationModel(scopedContents, keys, []); + } + return new ConfigurationModel(); + } } export class StandaloneConfigurationModelParser extends ConfigurationModelParser { @@ -77,7 +96,7 @@ export class StandaloneConfigurationModelParser extends ConfigurationModelParser export class FolderSettingsModelParser extends ConfigurationModelParser { private _raw: any; - private _workspaceSettingsModel: WorkspaceSettingsModel; + private _settingsModel: SettingsModel; constructor(name: string, private configurationScope?: ConfigurationScope) { super(name); @@ -89,11 +108,11 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } get configurationModel(): ConfigurationModel { - return this._workspaceSettingsModel || new WorkspaceSettingsModel({}, [], [], []); + return this._settingsModel || new SettingsModel({}, [], [], []); } - get folderSettingsModel(): WorkspaceSettingsModel { - return this.configurationModel; + get settingsModel(): SettingsModel { + return this.configurationModel; } reprocess(): void { @@ -114,7 +133,7 @@ export class FolderSettingsModelParser extends ConfigurationModelParser { } } const configurationModel = this.parseRaw(rawWorkspaceSettings); - this._workspaceSettingsModel = new WorkspaceSettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys); + this._settingsModel = new SettingsModel(configurationModel.contents, configurationModel.keys, configurationModel.overrides, unsupportedKeys); } private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 983bf2b902f..897e2c0faac 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -16,7 +16,7 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels'; -import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser, WorkspaceSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; +import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels'; import { WORKSPACE_STANDALONE_CONFIGURATIONS, FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import * as extfs from 'vs/base/node/extfs'; @@ -82,6 +82,9 @@ export class WorkspaceConfiguration extends Disposable { private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : ''); + private _cache: ConfigurationModel = new ConfigurationModel(); + load(workspaceConfigPath: URI): TPromise { if (this._workspaceConfigPath && this._workspaceConfigPath.fsPath === workspaceConfigPath.fsPath) { return this.reload(); @@ -98,20 +101,17 @@ export class WorkspaceConfiguration extends Disposable { onError: error => errors.onUnexpectedError(error), defaultConfig, parse: (content: string, parseErrors: any[]) => { - const workspaceConfigurationModel = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath); - workspaceConfigurationModel.parse(content); - parseErrors = [...workspaceConfigurationModel.errors]; - return workspaceConfigurationModel; + this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this._workspaceConfigPath.fsPath); + this._workspaceConfigurationModelParser.parse(content); + parseErrors = [...this._workspaceConfigurationModelParser.errors]; + this.consolidate(); + return this._workspaceConfigurationModelParser; }, initCallback: () => c(null) }); this.listenToWatcher(); }); } - private get workspaceConfigurationModelParser(): WorkspaceConfigurationModelParser { - return this._workspaceConfigurationWatcher ? this._workspaceConfigurationWatcher.getConfig() : new WorkspaceConfigurationModelParser(this._workspaceConfigPath ? this._workspaceConfigPath.fsPath : ''); - } - reload(): TPromise { this.stopListeningToWatcher(); return new TPromise(c => this._workspaceConfigurationWatcher.reload(() => { @@ -121,7 +121,7 @@ export class WorkspaceConfiguration extends Disposable { } getFolders(): IStoredWorkspaceFolder[] { - return this.workspaceConfigurationModelParser.folders; + return this._workspaceConfigurationModelParser.folders; } setFolders(folders: IStoredWorkspaceFolder[], jsonEditingService: JSONEditingService): TPromise { @@ -130,15 +130,16 @@ export class WorkspaceConfiguration extends Disposable { } getConfiguration(): ConfigurationModel { - return this.workspaceConfigurationModelParser.workspaceSettingsModel; + return this._cache; } - getWorkspaceSettings(): WorkspaceSettingsModel { - return this.workspaceConfigurationModelParser.workspaceSettingsModel; + getUnsupportedKeys(): string[] { + return this._workspaceConfigurationModelParser.settingsModel.unsupportedKeys; } reprocessWorkspaceSettings(): ConfigurationModel { - this.workspaceConfigurationModelParser.reprocessWorkspaceSettings(); + this._workspaceConfigurationModelParser.reprocessWorkspaceSettings(); + this.consolidate(); return this.getConfiguration(); } @@ -151,6 +152,10 @@ export class WorkspaceConfiguration extends Disposable { this._workspaceConfigurationWatcherDisposables = dispose(this._workspaceConfigurationWatcherDisposables); } + private consolidate(): void { + this._cache = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel); + } + dispose(): void { dispose(this._workspaceConfigurationWatcherDisposables); super.dispose(); @@ -190,20 +195,20 @@ export class FolderConfiguration extends Disposable { } reprocess(): ConfigurationModel { - const oldContents = this._folderSettingsModelParser.folderSettingsModel.contents; + const oldContents = this._folderSettingsModelParser.settingsModel.contents; this._folderSettingsModelParser.reprocess(); - if (!equals(oldContents, this._folderSettingsModelParser.folderSettingsModel.contents)) { + if (!equals(oldContents, this._folderSettingsModelParser.settingsModel.contents)) { this.consolidate(); } return this._cache; } getUnsupportedKeys(): string[] { - return this._folderSettingsModelParser.folderSettingsModel.unsupportedKeys; + return this._folderSettingsModelParser.settingsModel.unsupportedKeys; } private consolidate(): void { - this._cache = this._folderSettingsModelParser.folderSettingsModel.merge(...this._standAloneConfigurations); + this._cache = this._folderSettingsModelParser.settingsModel.merge(...this._standAloneConfigurations); } private loadWorkspaceConfigFiles(): TPromise<{ [relativeWorkspacePath: string]: ConfigurationModelParser }> { diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index faad43ebd7d..f91fcb78f79 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -390,8 +390,8 @@ export class ConfigurationEditingService { return this.wrapError(ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET, target, operation); } - // Workspace tasks and launches are not supported - if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && operation.target === ConfigurationTarget.WORKSPACE) { + // Workspace tasks are not supported + if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && operation.target === ConfigurationTarget.WORKSPACE) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET, target, operation); } } @@ -432,8 +432,6 @@ export class ConfigurationEditingService { private getConfigurationEditOperation(target: ConfigurationTarget, config: IConfigurationValue, overrides: IConfigurationOverrides): IConfigurationEditOperation { - const workspace = this.contextService.getWorkspace(); - // Check for standalone workspace configurations if (config.key) { const standaloneConfigurationKeys = Object.keys(WORKSPACE_STANDALONE_CONFIGURATIONS); @@ -443,14 +441,14 @@ export class ConfigurationEditingService { // Check for prefix if (config.key === key) { - const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key] : []; + const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key] : []; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target }; } // Check for prefix. const keyPrefix = `${key}.`; if (config.key.indexOf(keyPrefix) === 0) { - const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; + const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target }; } } @@ -463,12 +461,17 @@ export class ConfigurationEditingService { } const resource = this.getConfigurationFileResource(target, FOLDER_SETTINGS_PATH, overrides.resource); - if (workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) { + if (this.isWorkspaceConfigurationResource(resource)) { jsonPath = ['settings', ...jsonPath]; } return { key, jsonPath, value: config.value, resource, target }; } + private isWorkspaceConfigurationResource(resource: URI): boolean { + const workspace = this.contextService.getWorkspace(); + return workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath; + } + private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI): URI { if (target === ConfigurationTarget.USER) { return URI.file(this.environmentService.appSettingsPath); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index d5c3af13b8b..577c4f78dcd 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -110,9 +110,9 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.workspace.getFolder(resource); } - public addFolders(foldersToAdd: IWorkspaceFolderCreationData[]): TPromise { + public addFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number): TPromise { assert.ok(this.jsonEditingService, 'Workbench is not initialized yet'); - return this.workspaceEditingQueue.queue(() => this.doAddFolders(foldersToAdd)); + return this.workspaceEditingQueue.queue(() => this.doAddFolders(foldersToAdd, index)); } public removeFolders(foldersToRemove: URI[]): TPromise { @@ -134,7 +134,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return false; } - private doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[]): TPromise { + private doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number): TPromise { if (this.getWorkbenchState() !== WorkbenchState.WORKSPACE) { return TPromise.as(void 0); // we need a workspace to begin with } @@ -176,7 +176,16 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat }); if (storedFoldersToAdd.length > 0) { - return this.setFolders([...currentStoredFolders, ...storedFoldersToAdd]); + let newStoredWorkspaceFolders: IStoredWorkspaceFolder[] = []; + + if (typeof index === 'number' && index >= 0 && index < currentStoredFolders.length) { + newStoredWorkspaceFolders = currentStoredFolders.slice(0); + newStoredWorkspaceFolders.splice(index, 0, ...storedFoldersToAdd); + } else { + newStoredWorkspaceFolders = [...currentStoredFolders, ...storedFoldersToAdd]; + } + + return this.setFolders(newStoredWorkspaceFolders); } return TPromise.as(void 0); @@ -279,7 +288,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } getUnsupportedWorkspaceKeys(): string[] { - const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getWorkspaceSettings().unsupportedKeys]; + const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getUnsupportedKeys()]; for (const folder of this.workspace.folders) { unsupportedWorkspaceKeys.push(...this.cachedFolderConfigs.get(folder.uri).getUnsupportedKeys()); } diff --git a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts index d41ac767a69..6563fd4a42c 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationService.test.ts @@ -192,6 +192,34 @@ suite('WorkspaceContextService - Workspace', () => { }); }); + test('add folders (at specific index)', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 0) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'd'); + assert.equal(path.basename(actual[1].uri.fsPath), 'c'); + assert.equal(path.basename(actual[2].uri.fsPath), 'a'); + assert.equal(path.basename(actual[3].uri.fsPath), 'b'); + }); + }); + + test('add folders (at specific wrong index)', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 10) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(path.basename(actual[2].uri.fsPath), 'd'); + assert.equal(path.basename(actual[3].uri.fsPath), 'c'); + }); + }); + test('add folders (with name)', () => { const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')), name: 'DDD' }, { uri: URI.file(path.join(workspaceDir, 'c')), name: 'CCC' }]) @@ -1038,6 +1066,56 @@ suite('WorkspaceConfigurationService - Multiroot', () => { }); }); + test('get launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.getValue('launch'); + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + + test('inspect launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.inspect('launch').workspace; + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + test('update user configuration', () => { return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); @@ -1088,10 +1166,10 @@ suite('WorkspaceConfigurationService - Multiroot', () => { .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET)); }); - test('update launch configuration in a workspace is not supported', () => { + test('update launch configuration in a workspace', () => { const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) - .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET)); + .then(() => assert.deepEqual(testObject.getValue('launch'), { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] })); }); test('task configurations are not read from workspace', () => { @@ -1102,13 +1180,4 @@ suite('WorkspaceConfigurationService - Multiroot', () => { assert.equal(actual.workspace, void 0); }); }); - - test('launch configurations are not read from workspace', () => { - return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration, { key: 'launch', value: { 'version': '1.0' } }, true) - .then(() => testObject.reloadConfiguration()) - .then(() => { - const actual = testObject.inspect('launch.version'); - assert.equal(actual.workspace, void 0); - }); - }); }); diff --git a/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts index 1a98e4493eb..99b29ec0e45 100644 --- a/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/electron-browser/configurationResolverService.ts @@ -12,7 +12,7 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { toResource } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -20,92 +20,111 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { relative } from 'path'; import { IProcessEnvironment, isWindows } from 'vs/base/common/platform'; -export class ConfigurationResolverService implements IConfigurationResolverService { - _serviceBrand: any; - private _execPath: string; - private _lastWorkspaceFolder: IWorkspaceFolder; +class VariableResolver { + static VARIABLE_REGEXP = /\$\{(.*?)\}/g; + static ENV_PREFIX = 'env:'; + static CONFIG_PREFIX = 'config:'; + private envVariables: IProcessEnvironment; constructor( envVariables: IProcessEnvironment, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IEnvironmentService environmentService: IEnvironmentService, - @IConfigurationService private configurationService: IConfigurationService, - @ICommandService private commandService: ICommandService, + private configurationService: IConfigurationService, + private editorService: IWorkbenchEditorService, + private environmentService: IEnvironmentService, + private workspaceContextService: IWorkspaceContextService ) { - this._execPath = environmentService.execPath; - Object.keys(envVariables).forEach(key => { - const name = isWindows ? key.toLowerCase() : key; - this[`env:${name}`] = envVariables[key]; + if (isWindows) { + this.envVariables = Object.create(null); + Object.keys(envVariables).forEach(key => { + this.envVariables[key.toLowerCase()] = envVariables[key]; + }); + } else { + this.envVariables = envVariables; + } + } + + resolve(context: IWorkspaceFolder, value: string): string { + const filePath = this.getFilePath(); + return value.replace(VariableResolver.VARIABLE_REGEXP, (match: string, variable: string) => { + const parts = variable.split(':'); + let sufix: string; + if (parts && parts.length > 1) { + variable = parts[0]; + sufix = parts[1]; + } + + switch (variable) { + case 'env': { + if (sufix) { + if (isWindows) { + sufix = sufix.toLowerCase(); + } + + const env = this.envVariables[sufix]; + if (types.isString(env)) { + return env; + } + } + } + case 'config': { + if (sufix) { + const config = this.configurationService.getValue(sufix, context ? { resource: context.uri } : undefined); + if (!types.isUndefinedOrNull(config) && !types.isObject(config)) { + return config; + } + } + } + default: { + if (sufix) { + const folder = this.workspaceContextService.getWorkspace().folders.filter(f => f.name === sufix).pop(); + if (folder) { + context = folder; + } + } + + switch (variable) { + case 'workspaceRoot': + case 'workspaceFolder': + return context ? context.uri.fsPath : match; + case 'cwd': + return context ? context.uri.fsPath : process.cwd(); + case 'workspaceRootFolderName': + case 'workspaceFolderBasename': + return context ? paths.basename(context.uri.fsPath) : match; + case 'lineNumber': + return this.getLineNumber() || match; + case 'selectedText': + return this.getSelectedText() || match; + case 'file': + return filePath || match; + case 'relativeFile': + return context ? paths.normalize(relative(context.uri.fsPath, filePath)) : filePath || match; + case 'fileDirname': + return filePath ? paths.dirname(filePath) : match; + case 'fileExtname': + return filePath ? paths.extname(filePath) : match; + case 'fileBasename': + return filePath ? paths.basename(filePath) : match; + case 'fileBasenameNoExtension': { + if (!filePath) { + return match; + } + + const basename = paths.basename(filePath); + return basename.slice(0, basename.length - paths.extname(basename).length); + } + case 'execPath': + return this.environmentService.execPath; + + default: + return match; + } + } + } }); } - private get execPath(): string { - return this._execPath; - } - - private get cwd(): string { - if (this.workspaceRoot) { - return this.workspaceRoot; - } else { - return process.cwd(); - } - } - - private get workspaceRoot(): string { - return this._lastWorkspaceFolder ? this._lastWorkspaceFolder.uri.fsPath : undefined; - } - - private get workspaceFolder(): string { - return this.workspaceRoot; - } - - private get workspaceRootFolderName(): string { - return this.workspaceFolderBasename; - } - - private get workspaceFolderBasename(): string { - return this.workspaceRoot ? paths.basename(this.workspaceRoot) : ''; - } - - private get file(): string { - return this.getFilePath(); - } - - private get relativeFile(): string { - return (this.workspaceRoot) ? paths.normalize(relative(this.workspaceRoot, this.file)) : this.file; - } - - private get fileBasename(): string { - return paths.basename(this.getFilePath()); - } - - private get fileBasenameNoExtension(): string { - const basename = this.fileBasename; - return basename.slice(0, basename.length - paths.extname(basename).length); - } - - private get fileDirname(): string { - return paths.dirname(this.getFilePath()); - } - - private get fileExtname(): string { - return paths.extname(this.getFilePath()); - } - - private get lineNumber(): string { - const activeEditor = this.editorService.getActiveEditor(); - if (activeEditor) { - const editorControl = (activeEditor.getControl()); - if (editorControl) { - const lineNumber = editorControl.getSelection().positionLineNumber; - return String(lineNumber); - } - } - - return ''; - } - - private get selectedText(): string { + private getSelectedText(): string { const activeEditor = this.editorService.getActiveEditor(); if (activeEditor) { const editorControl = (activeEditor.getControl()); @@ -118,7 +137,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi } } - return ''; + return undefined; } private getFilePath(): string { @@ -126,126 +145,77 @@ export class ConfigurationResolverService implements IConfigurationResolverServi if (input instanceof DiffEditorInput) { input = input.modifiedInput; } - if (!input) { - return ''; - } const fileResource = toResource(input, { filter: 'file' }); if (!fileResource) { - return ''; + return undefined; } + return paths.normalize(fileResource.fsPath, true); } + private getLineNumber(): string { + const activeEditor = this.editorService.getActiveEditor(); + if (activeEditor) { + const editorControl = (activeEditor.getControl()); + if (editorControl) { + const lineNumber = editorControl.getSelection().positionLineNumber; + return String(lineNumber); + } + } + + return undefined; + } +} + +export class ConfigurationResolverService implements IConfigurationResolverService { + _serviceBrand: any; + private resolver: VariableResolver; + + constructor( + envVariables: IProcessEnvironment, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IEnvironmentService environmentService: IEnvironmentService, + @IConfigurationService configurationService: IConfigurationService, + @ICommandService private commandService: ICommandService, + @IWorkspaceContextService workspaceContextService: IWorkspaceContextService + ) { + this.resolver = new VariableResolver(envVariables, configurationService, editorService, environmentService, workspaceContextService); + } + public resolve(root: IWorkspaceFolder, value: string): string; public resolve(root: IWorkspaceFolder, value: string[]): string[]; public resolve(root: IWorkspaceFolder, value: IStringDictionary): IStringDictionary; public resolve(root: IWorkspaceFolder, value: any): any { - try { - this._lastWorkspaceFolder = root; - if (types.isString(value)) { - return this.resolveString(root, value); - } else if (types.isArray(value)) { - return this.resolveArray(root, value); - } else if (types.isObject(value)) { - return this.resolveLiteral(root, value); - } - return value; - } finally { - this._lastWorkspaceFolder = undefined; + if (types.isString(value)) { + return this.resolver.resolve(root, value); + } else if (types.isArray(value)) { + return value.map(s => this.resolver.resolve(root, s)); + } else if (types.isObject(value)) { + let result: IStringDictionary | string[]> = Object.create(null); + Object.keys(value).forEach(key => { + result[key] = this.resolve(root, value[key]); + }); + + return result; } + return value; } - public resolveAny(root: IWorkspaceFolder, value: T): T; public resolveAny(root: IWorkspaceFolder, value: any): any { - try { - this._lastWorkspaceFolder = root; - if (types.isString(value)) { - return this.resolveString(root, value); - } else if (types.isArray(value)) { - return this.resolveAnyArray(root, value); - } else if (types.isObject(value)) { - return this.resolveAnyLiteral(root, value); - } - return value; - } finally { - this._lastWorkspaceFolder = undefined; + if (types.isString(value)) { + return this.resolver.resolve(root, value); + } else if (types.isArray(value)) { + return value.map(s => this.resolveAny(root, s)); + } else if (types.isObject(value)) { + let result: IStringDictionary | string[]> = Object.create(null); + Object.keys(value).forEach(key => { + result[key] = this.resolveAny(root, value[key]); + }); + + return result; } - } - - private resolveString(root: IWorkspaceFolder, value: string): string { - let regexp = /\$\{(.*?)\}/g; - const originalValue = value; - const resolvedString = value.replace(regexp, (match: string, name: string) => { - const key = (isWindows && match.indexOf('env:') > 0) ? name.toLowerCase() : name; - let newValue = (this)[key]; - if (types.isString(newValue)) { - return newValue; - } else { - return match && match.indexOf('env:') > 0 ? '' : match; - } - }); - - return this.resolveConfigVariable(root, resolvedString, originalValue); - } - - private resolveConfigVariable(root: IWorkspaceFolder, value: string, originalValue: string): string { - const replacer = (match: string, name: string) => { - let config = this.configurationService.getValue({ resource: root.uri }); - let newValue: any; - try { - const keys: string[] = name.split('.'); - if (!keys || keys.length <= 0) { - return ''; - } - while (keys.length > 1) { - const key = keys.shift(); - if (!config || !config.hasOwnProperty(key)) { - return ''; - } - config = config[key]; - } - newValue = config && config.hasOwnProperty(keys[0]) ? config[keys[0]] : ''; - } catch (e) { - return ''; - } - if (types.isString(newValue)) { - // Prevent infinite recursion and also support nested references (or tokens) - return newValue === originalValue ? '' : this.resolveString(root, newValue); - } else { - return this.resolve(root, newValue) + ''; - } - }; - - return value.replace(/\$\{config:(.+?)\}/g, replacer); - } - - private resolveLiteral(root: IWorkspaceFolder, values: IStringDictionary | string[]>): IStringDictionary | string[]> { - let result: IStringDictionary | string[]> = Object.create(null); - Object.keys(values).forEach(key => { - let value = values[key]; - result[key] = this.resolve(root, value); - }); - return result; - } - - private resolveAnyLiteral(root: IWorkspaceFolder, values: T): T; - private resolveAnyLiteral(root: IWorkspaceFolder, values: any): any { - let result: IStringDictionary | string[]> = Object.create(null); - Object.keys(values).forEach(key => { - let value = values[key]; - result[key] = this.resolveAny(root, value); - }); - return result; - } - - private resolveArray(root: IWorkspaceFolder, value: string[]): string[] { - return value.map(s => this.resolveString(root, s)); - } - - private resolveAnyArray(root: IWorkspaceFolder, value: T[]): T[]; - private resolveAnyArray(root: IWorkspaceFolder, value: any[]): any[] { - return value.map(s => this.resolveAny(root, s)); + return value; } /** @@ -258,7 +228,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi // We need a map from interactive variables to keys because we only want to trigger an command once per key - // even though it might occur multiple times in configuration #7026. - const interactiveVariablesToSubstitutes: { [interactiveVariable: string]: { object: any, key: string }[] } = {}; + const interactiveVariablesToSubstitutes: { [interactiveVariable: string]: { object: any, key: string }[] } = Object.create(null); const findInteractiveVariables = (object: any) => { Object.keys(object).forEach(key => { if (object[key] && typeof object[key] === 'object') { diff --git a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts index b77215ea758..fd97b00746e 100644 --- a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts @@ -12,7 +12,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { TestEnvironmentService, TestEditorService } from 'vs/workbench/test/workbenchTestServices'; +import { TestEnvironmentService, TestEditorService, TestContextService } from 'vs/workbench/test/workbenchTestServices'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; suite('Configuration Resolver Service', () => { @@ -22,7 +22,6 @@ suite('Configuration Resolver Service', () => { let editorService: TestEditorService; let workspace: IWorkspaceFolder; - setup(() => { mockCommandService = new MockCommandService(); editorService = new TestEditorService(); @@ -32,14 +31,13 @@ suite('Configuration Resolver Service', () => { index: 0, toResource: () => null }; - configurationResolverService = new ConfigurationResolverService(envVariables, editorService, TestEnvironmentService, new TestConfigurationService(), mockCommandService); + configurationResolverService = new ConfigurationResolverService(envVariables, editorService, TestEnvironmentService, new TestConfigurationService(), mockCommandService, new TestContextService()); }); teardown(() => { configurationResolverService = null; }); - test('substitute one', () => { if (platform.isWindows) { assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} xyz'), 'abc \\VSCode\\workspaceLocation xyz'); @@ -88,7 +86,7 @@ suite('Configuration Resolver Service', () => { if (platform.isWindows) { assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - Value for key1'); } else { - assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - '); + assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - ${env:Key1}'); } }); @@ -105,7 +103,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz'); }); @@ -122,52 +120,10 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz'); }); - test('substitute nested configuration variables', () => { - let configurationService: IConfigurationService; - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo ${workspaceFolder} ${config:terminal.integrated.fontFamily}' - }, - terminal: { - integrated: { - fontFamily: 'bar' - } - } - }); - - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); - if (platform.isWindows) { - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz'); - } else { - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz'); - } - }); - - test('substitute accidental self referenced configuration variables', () => { - let configurationService: IConfigurationService; - configurationService = new MockConfigurationService({ - editor: { - fontFamily: 'foo ${workspaceFolder} ${config:terminal.integrated.fontFamily} ${config:editor.fontFamily}' - }, - terminal: { - integrated: { - fontFamily: 'bar' - } - } - }); - - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); - if (platform.isWindows) { - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz'); - } else { - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz'); - } - }); - test('substitute one env variable and a configuration variable', () => { let configurationService: IConfigurationService; configurationService = new MockConfigurationService({ @@ -181,7 +137,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); if (platform.isWindows) { assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for key1 xyz'); } else { @@ -202,7 +158,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); if (platform.isWindows) { assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for key1 - Value for key2'); } else { @@ -236,7 +192,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz'); }); @@ -248,32 +204,21 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc xyz'); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); + assert.strictEqual(service.resolve(workspace, 'abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc ${config:editor[\'abc\'.substr(0)]} xyz'); }); - test('uses empty string as fallback', () => { + test('uses original variable as fallback', () => { let configurationService: IConfigurationService; configurationService = new MockConfigurationService({ editor: {} }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc} xyz'), 'abc xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc.def} xyz'), 'abc xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:panel} xyz'), 'abc xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:panel.abc} xyz'), 'abc xyz'); - }); - - test('is restricted to own properties', () => { - let configurationService: IConfigurationService; - configurationService = new MockConfigurationService({ - editor: {} - }); - - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.__proto__} xyz'), 'abc xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.toString} xyz'), 'abc xyz'); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); + assert.strictEqual(service.resolve(workspace, 'abc ${invalidVariable} xyz'), 'abc ${invalidVariable} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${env:invalidVariable} xyz'), 'abc ${env:invalidVariable} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc.def} xyz'), 'abc ${config:editor.abc.def} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${config:panel.abc} xyz'), 'abc ${config:panel.abc} xyz'); }); test('configuration variables with invalid accessor', () => { @@ -284,10 +229,10 @@ suite('Configuration Resolver Service', () => { } }); - let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService); + let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService()); assert.strictEqual(service.resolve(workspace, 'abc ${config:} xyz'), 'abc ${config:} xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz'), 'abc xyz'); - assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.none.none2} xyz'), 'abc xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz'), 'abc ${config:editor..fontFamily} xyz'); + assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.none.none2} xyz'), 'abc ${config:editor.none.none2} xyz'); }); test('interactive variable simple', () => { @@ -362,7 +307,20 @@ class MockConfigurationService implements IConfigurationService { public constructor(private configuration: any = {}) { } public inspect(key: string, overrides?: IConfigurationOverrides): any { return { value: getConfigurationValue(this.getValue(), key), default: getConfigurationValue(this.getValue(), key), user: getConfigurationValue(this.getValue(), key), workspaceFolder: void 0, folder: void 0 }; } public keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; } - public getValue(): any { return this.configuration; } + public getValue(): any; + public getValue(value: string): any; + public getValue(value?: any): any { + if (!value) { + return this.configuration; + } + const valuePath = (value).split('.'); + let object = this.configuration; + while (valuePath.length && object) { + object = object[valuePath.shift()]; + } + + return object; + } public updateValue(): TPromise { return null; } public getConfigurationData(): any { return null; } public onDidChangeConfiguration() { return { dispose() { } }; } diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 196825b2f11..e5fd893ab73 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -19,6 +19,7 @@ import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorIn import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { ICloseEditorsFilter } from 'vs/workbench/browser/parts/editor/editorPart'; +import { snapshotToString } from 'vs/platform/files/common/files'; let activeEditor: BaseEditor = { getSelection: function () { @@ -163,7 +164,7 @@ suite('WorkbenchEditorService', () => { const untitledInput = openedEditorInput as UntitledEditorInput; untitledInput.resolve().then(model => { - assert.equal(model.getValue(), 'Hello Untitled'); + assert.equal(snapshotToString(model.createSnapshot()), 'Hello Untitled'); }); }); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 62474f4acbc..cb7cb3d37fd 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -35,6 +35,7 @@ import { EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_C import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console'; import { getScopes } from 'vs/platform/configuration/common/configurationRegistry'; +import { ILogService } from 'vs/platform/log/common/log'; export class ExtensionHostProcessWorker { @@ -70,7 +71,8 @@ export class ExtensionHostProcessWorker { @IEnvironmentService private readonly _environmentService: IEnvironmentService, @IWorkspaceConfigurationService private readonly _configurationService: IWorkspaceConfigurationService, @ITelemetryService private readonly _telemetryService: ITelemetryService, - @ICrashReporterService private readonly _crashReporterService: ICrashReporterService + @ICrashReporterService private readonly _crashReporterService: ICrashReporterService, + @ILogService private readonly _logService: ILogService ) { // handle extension host lifecycle a bit special when we know we are developing an extension that runs inside this._isExtensionDevHost = this._environmentService.isExtensionDevelopment; @@ -274,6 +276,8 @@ export class ExtensionHostProcessWorker { let startPort = 9333; if (typeof this._environmentService.debugExtensionHost.port === 'number') { startPort = expected = this._environmentService.debugExtensionHost.port; + } else { + return TPromise.as({ expected: undefined, actual: 0 }); } return new TPromise((c, e) => { return findFreePort(startPort, 10 /* try 10 ports */, 5000 /* try up to 5 seconds */).then(port => { @@ -377,7 +381,8 @@ export class ExtensionHostProcessWorker { telemetryInfo, args: this._environmentService.args, execPath: this._environmentService.execPath, - windowId: this._windowService.getCurrentWindowId() + windowId: this._windowService.getCurrentWindowId(), + logLevel: this._logService.getLevel() }; return r; }); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts index 2b77e490063..0877a0df48a 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts @@ -7,15 +7,8 @@ import { IExtensionService, IExtensionDescription, ProfileSession, IExtensionHostProfile, ProfileSegmentId } from 'vs/platform/extensions/common/extensions'; import { TPromise } from 'vs/base/common/winjs.base'; -import { localize } from 'vs/nls'; import { TernarySearchTree } from 'vs/base/common/map'; import { realpathSync } from 'vs/base/node/extfs'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { IStatusbarService, StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar'; -import { writeFile } from 'vs/base/node/pfs'; -import * as path from 'path'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { setTimeout } from 'timers'; import { Profile, ProfileNode } from 'v8-inspect-profiler'; export class ExtensionHostProfiler { @@ -128,27 +121,3 @@ export class ExtensionHostProfiler { }; } } - - -CommandsRegistry.registerCommand('exthost.profile.start', async accessor => { - const statusbarService = accessor.get(IStatusbarService); - const extensionService = accessor.get(IExtensionService); - const environmentService = accessor.get(IEnvironmentService); - - const handle = statusbarService.addEntry({ text: localize('message', "$(zap) Profiling Extension Host...") }, StatusbarAlignment.LEFT); - - extensionService.startExtensionHostProfile().then(session => { - setTimeout(() => { - session.stop().then(result => { - result.getAggregatedTimes().forEach((val, index) => { - console.log(`${index} : ${Math.round(val / 1000)} ms`); - }); - let profilePath = path.join(environmentService.userHome, 'extHostProfile.cpuprofile'); - console.log(`Saving profile at ${profilePath}`); - return writeFile(profilePath, JSON.stringify(result.data)); - }).then(() => { - handle.dispose(); - }); - }, 5000); - }); -}); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionPoints.ts b/src/vs/workbench/services/extensions/electron-browser/extensionPoints.ts index b0b0f300177..1ce6fdca2c2 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionPoints.ts @@ -334,6 +334,10 @@ export class ExtensionScanner { } const rawFolders = await pfs.readDirsInDir(absoluteFolderPath); + + // Ensure the same extension order + rawFolders.sort(); + let folders: string[] = null; if (isBuiltin) { folders = rawFolders; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 8abc3ff6140..1f32a1e5386 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -44,6 +44,7 @@ import * as strings from 'vs/base/common/strings'; import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; const SystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', 'extensions')); +const ExtraDevSystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', '.build', 'builtInExtensions')); // Enable to see detailed message communication between window and extension host const logExtensionHostCommunication = false; @@ -369,6 +370,10 @@ export class ExtensionService extends Disposable implements IExtensionService { return result; } + public canProfileExtensionHost(): boolean { + return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort()); + } + public startExtensionHostProfile(): TPromise { if (this._extensionHostProcessWorker) { let port = this._extensionHostProcessWorker.getInspectPort(); @@ -624,6 +629,36 @@ export class ExtensionService extends Disposable implements IExtensionService { log ); + let finalBuiltinExtensions: TPromise = builtinExtensions; + + if (devMode) { + const extraBuiltinExtensions = ExtensionScanner.scanExtensions(new ExtensionScannerInput(version, commit, locale, devMode, ExtraDevSystemExtensionsRoot, true), log); + finalBuiltinExtensions = TPromise.join([builtinExtensions, extraBuiltinExtensions]).then(([builtinExtensions, extraBuiltinExtensions]) => { + let resultMap: { [id: string]: IExtensionDescription; } = Object.create(null); + for (let i = 0, len = builtinExtensions.length; i < len; i++) { + resultMap[builtinExtensions[i].id] = builtinExtensions[i]; + } + // Overwrite with extensions found in extra + for (let i = 0, len = extraBuiltinExtensions.length; i < len; i++) { + resultMap[extraBuiltinExtensions[i].id] = extraBuiltinExtensions[i]; + } + + let resultArr = Object.keys(resultMap).map((id) => resultMap[id]); + resultArr.sort((a, b) => { + const aLastSegment = path.basename(a.extensionFolderPath); + const bLastSegment = path.basename(b.extensionFolderPath); + if (aLastSegment < bLastSegment) { + return -1; + } + if (aLastSegment > bLastSegment) { + return 1; + } + return 0; + }); + return resultArr; + }); + } + const userExtensions = ( environmentService.disableExtensions || !environmentService.extensionsPath ? TPromise.as([]) @@ -646,7 +681,7 @@ export class ExtensionService extends Disposable implements IExtensionService { : TPromise.as([]) ); - return TPromise.join([builtinExtensions, userExtensions, developedExtensions]) + return TPromise.join([finalBuiltinExtensions, userExtensions, developedExtensions]) .then((extensionDescriptions: IExtensionDescription[][]) => { const system = extensionDescriptions[0]; const user = extensionDescriptions[1]; diff --git a/src/vs/workbench/services/extensions/node/proxyIdentifier.ts b/src/vs/workbench/services/extensions/node/proxyIdentifier.ts index 5d2c7484abd..3447bd4255f 100644 --- a/src/vs/workbench/services/extensions/node/proxyIdentifier.ts +++ b/src/vs/workbench/services/extensions/node/proxyIdentifier.ts @@ -27,29 +27,22 @@ export class ProxyIdentifier { public readonly isMain: boolean; public readonly id: string; - public readonly isFancy: boolean; - constructor(isMain: boolean, id: string, isFancy: boolean) { + constructor(isMain: boolean, id: string) { this.isMain = isMain; this.id = id; - this.isFancy = isFancy; } } -export const enum ProxyType { - NativeJSON = 0, - CustomMarshaller = 1 -} - /** * Using `isFancy` indicates that arguments or results of type `URI` or `RegExp` * will be serialized/deserialized automatically, but this has a performance cost, * as each argument/result must be visited. */ -export function createMainContextProxyIdentifier(identifier: string, type: ProxyType = ProxyType.NativeJSON): ProxyIdentifier { - return new ProxyIdentifier(true, 'm' + identifier, type === ProxyType.CustomMarshaller); +export function createMainContextProxyIdentifier(identifier: string): ProxyIdentifier { + return new ProxyIdentifier(true, 'm' + identifier); } -export function createExtHostContextProxyIdentifier(identifier: string, type: ProxyType = ProxyType.NativeJSON): ProxyIdentifier { - return new ProxyIdentifier(false, 'e' + identifier, type === ProxyType.CustomMarshaller); +export function createExtHostContextProxyIdentifier(identifier: string): ProxyIdentifier { + return new ProxyIdentifier(false, 'e' + identifier); } diff --git a/src/vs/workbench/services/extensions/node/rpcProtocol.ts b/src/vs/workbench/services/extensions/node/rpcProtocol.ts index d738ab50737..2e1ae6d2ee8 100644 --- a/src/vs/workbench/services/extensions/node/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/node/rpcProtocol.ts @@ -5,7 +5,6 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import * as marshalling from 'vs/base/common/marshalling'; import * as errors from 'vs/base/common/errors'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise'; @@ -46,17 +45,17 @@ export class RPCProtocol implements IRPCProtocol { public getProxy(identifier: ProxyIdentifier): T { if (!this._proxies[identifier.id]) { - this._proxies[identifier.id] = this._createProxy(identifier.id, identifier.isFancy); + this._proxies[identifier.id] = this._createProxy(identifier.id); } return this._proxies[identifier.id]; } - private _createProxy(proxyId: string, isFancy: boolean): T { + private _createProxy(proxyId: string): T { let handler = { get: (target, name: string) => { if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) { target[name] = (...myArgs: any[]) => { - return this._remoteCall(proxyId, name, myArgs, isFancy); + return this._remoteCall(proxyId, name, myArgs); }; } return target[name]; @@ -90,38 +89,27 @@ export class RPCProtocol implements IRPCProtocol { case MessageType.Request: this._receiveRequest(msg); break; - case MessageType.FancyRequest: - this._receiveRequest(marshalling.revive(msg, 0)); - break; case MessageType.Cancel: this._receiveCancel(msg); break; case MessageType.Reply: this._receiveReply(msg); break; - case MessageType.FancyReply: - this._receiveReply(marshalling.revive(msg, 0)); - break; case MessageType.ReplyErr: this._receiveReplyErr(msg); break; } } - private _receiveRequest(msg: RequestMessage | FancyRequestMessage): void { + private _receiveRequest(msg: RequestMessage): void { const callId = msg.id; const proxyId = msg.proxyId; - const isFancy = (msg.type === MessageType.FancyRequest); // a fancy request gets a fancy reply this._invokedHandlers[callId] = this._invokeHandler(proxyId, msg.method, msg.args); this._invokedHandlers[callId].then((r) => { delete this._invokedHandlers[callId]; - if (isFancy) { - this._multiplexor.send(MessageFactory.fancyReplyOK(callId, r)); - } else { - this._multiplexor.send(MessageFactory.replyOK(callId, r)); - } + this._multiplexor.send(MessageFactory.replyOK(callId, r)); }, (err) => { delete this._invokedHandlers[callId]; this._multiplexor.send(MessageFactory.replyErr(callId, err)); @@ -135,7 +123,7 @@ export class RPCProtocol implements IRPCProtocol { } } - private _receiveReply(msg: ReplyMessage | FancyReplyMessage): void { + private _receiveReply(msg: ReplyMessage): void { const callId = msg.id; if (!this._pendingRPCReplies.hasOwnProperty(callId)) { return; @@ -186,7 +174,7 @@ export class RPCProtocol implements IRPCProtocol { return method.apply(actor, args); } - private _remoteCall(proxyId: string, methodName: string, args: any[], isFancy: boolean): TPromise { + private _remoteCall(proxyId: string, methodName: string, args: any[]): TPromise { if (this._isDisposed) { return TPromise.wrapError(errors.canceled()); } @@ -197,13 +185,7 @@ export class RPCProtocol implements IRPCProtocol { }); this._pendingRPCReplies[callId] = result; - - if (isFancy) { - this._multiplexor.send(MessageFactory.fancyRequest(callId, proxyId, methodName, args)); - } else { - this._multiplexor.send(MessageFactory.request(callId, proxyId, methodName, args)); - } - + this._multiplexor.send(MessageFactory.request(callId, proxyId, methodName, args)); return result; } } @@ -256,10 +238,6 @@ class MessageFactory { return `{"type":${MessageType.Request},"id":"${req}","proxyId":"${rpcId}","method":"${method}","args":${JSON.stringify(args)}}`; } - public static fancyRequest(req: string, rpcId: string, method: string, args: any[]): string { - return `{"type":${MessageType.FancyRequest},"id":"${req}","proxyId":"${rpcId}","method":"${method}","args":${marshalling.stringify(args)}}`; - } - public static replyOK(req: string, res: any): string { if (typeof res === 'undefined') { return `{"type":${MessageType.Reply},"id":"${req}"}`; @@ -267,13 +245,6 @@ class MessageFactory { return `{"type":${MessageType.Reply},"id":"${req}","res":${JSON.stringify(res)}}`; } - public static fancyReplyOK(req: string, res: any): string { - if (typeof res === 'undefined') { - return `{"type":${MessageType.Reply},"id":"${req}"}`; - } - return `{"type":${MessageType.FancyReply},"id":"${req}","res":${marshalling.stringify(res)}}`; - } - public static replyErr(req: string, err: any): string { if (err instanceof Error) { return `{"type":${MessageType.ReplyErr},"id":"${req}","err":${JSON.stringify(errors.transformErrorForSerialization(err))}}`; @@ -284,11 +255,9 @@ class MessageFactory { const enum MessageType { Request = 1, - FancyRequest = 2, - Cancel = 3, - Reply = 4, - FancyReply = 5, - ReplyErr = 6 + Cancel = 2, + Reply = 3, + ReplyErr = 4 } class RequestMessage { @@ -298,13 +267,6 @@ class RequestMessage { method: string; args: any[]; } -class FancyRequestMessage { - type: MessageType.FancyRequest; - id: string; - proxyId: string; - method: string; - args: any[]; -} class CancelMessage { type: MessageType.Cancel; id: string; @@ -314,15 +276,10 @@ class ReplyMessage { id: string; res: any; } -class FancyReplyMessage { - type: MessageType.FancyReply; - id: string; - res: any; -} class ReplyErrMessage { type: MessageType.ReplyErr; id: string; err: errors.SerializedError; } -type RPCMessage = RequestMessage | FancyRequestMessage | CancelMessage | ReplyMessage | FancyReplyMessage | ReplyErrMessage; +type RPCMessage = RequestMessage | CancelMessage | ReplyMessage | ReplyErrMessage; diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 5eeae64bf3a..e97cc0ffd1d 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -11,7 +11,7 @@ import paths = require('vs/base/common/paths'); import encoding = require('vs/base/node/encoding'); import errors = require('vs/base/common/errors'); import uri from 'vs/base/common/uri'; -import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent, ICreateFileOptions } from 'vs/platform/files/common/files'; +import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent, ICreateFileOptions, ITextSnapshot } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -181,7 +181,7 @@ export class FileService implements IFileService { return this.raw.resolveStreamContent(resource, options); } - public updateContent(resource: uri, value: string, options?: IUpdateContentOptions): TPromise { + public updateContent(resource: uri, value: string | ITextSnapshot, options?: IUpdateContentOptions): TPromise { return this.raw.updateContent(resource, value, options); } diff --git a/src/vs/workbench/services/files/electron-browser/remoteFileService.ts b/src/vs/workbench/services/files/electron-browser/remoteFileService.ts index 2bf1ba014e1..1fb80d99042 100644 --- a/src/vs/workbench/services/files/electron-browser/remoteFileService.ts +++ b/src/vs/workbench/services/files/electron-browser/remoteFileService.ts @@ -6,7 +6,7 @@ import URI from 'vs/base/common/uri'; import { FileService } from 'vs/workbench/services/files/electron-browser/fileService'; -import { IContent, IStreamContent, IFileStat, IResolveContentOptions, IUpdateContentOptions, IResolveFileOptions, IResolveFileResult, FileOperationEvent, FileOperation, IFileSystemProvider, IStat, FileType, IImportResult, FileChangesEvent, ICreateFileOptions, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; +import { IContent, IStreamContent, IFileStat, IResolveContentOptions, IUpdateContentOptions, IResolveFileOptions, IResolveFileResult, FileOperationEvent, FileOperation, IFileSystemProvider, IStat, FileType, IImportResult, FileChangesEvent, ICreateFileOptions, FileOperationError, FileOperationResult, ITextSnapshot, snapshotToString } from 'vs/platform/files/common/files'; import { TPromise } from 'vs/base/common/winjs.base'; import { basename, join } from 'path'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -351,7 +351,7 @@ export class RemoteFileService extends FileService { } } - updateContent(resource: URI, value: string, options?: IUpdateContentOptions): TPromise { + updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): TPromise { if (resource.scheme === Schemas.file) { return super.updateContent(resource, value, options); } else { @@ -361,9 +361,10 @@ export class RemoteFileService extends FileService { } } - private _doUpdateContent(provider: IFileSystemProvider, resource: URI, content: string, options: IUpdateContentOptions): TPromise { + private _doUpdateContent(provider: IFileSystemProvider, resource: URI, content: string | ITextSnapshot, options: IUpdateContentOptions): TPromise { const encoding = this.getEncoding(resource, options.encoding); - return provider.write(resource, encode(content, encoding)).then(() => { + // TODO@Joh support streaming API for remote file system writes + return provider.write(resource, encode(typeof content === 'string' ? content : snapshotToString(content), encoding)).then(() => { return this.resolveFile(resource); }); } diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index b1475b44eb9..f443fec34a4 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -10,8 +10,7 @@ import fs = require('fs'); import os = require('os'); import crypto = require('crypto'); import assert = require('assert'); - -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 { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, FileChangesEvent, ICreateFileOptions, IContentData, ITextSnapshot } from 'vs/platform/files/common/files'; import { MAX_FILE_SIZE } from 'vs/platform/files/node/files'; import { isEqualOrParent } from 'vs/base/common/paths'; import { ResourceMap } from 'vs/base/common/map'; @@ -41,6 +40,7 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { getBaseLabel } from 'vs/base/common/labels'; import { assign } from 'vs/base/common/objects'; +import { Readable } from 'stream'; export interface IEncodingOverride { resource: uri; @@ -505,7 +505,7 @@ export class FileService implements IFileService { }); } - public updateContent(resource: uri, value: string, options: IUpdateContentOptions = Object.create(null)): TPromise { + public updateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { if (this.options.elevationSupport && options.writeElevated) { return this.doUpdateContentElevated(resource, value, options); } @@ -513,7 +513,7 @@ export class FileService implements IFileService { return this.doUpdateContent(resource, value, options); } - private doUpdateContent(resource: uri, value: string, options: IUpdateContentOptions = Object.create(null)): TPromise { + private doUpdateContent(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { const absolutePath = this.toAbsolutePath(resource); // 1.) check file @@ -579,18 +579,25 @@ export class FileService implements IFileService { }); } - private doSetContentsAndResolve(resource: uri, absolutePath: string, value: string, addBOM: boolean, encodingToWrite: string, options?: { mode?: number; flag?: string; }): TPromise { + private doSetContentsAndResolve(resource: uri, absolutePath: string, value: string | ITextSnapshot, addBOM: boolean, encodingToWrite: string, options?: { mode?: number; flag?: string; }): TPromise { let writeFilePromise: TPromise; // Write fast if we do UTF 8 without BOM if (!addBOM && encodingToWrite === encoding.UTF8) { - writeFilePromise = pfs.writeFile(absolutePath, value, options); + if (typeof value === 'string') { + writeFilePromise = pfs.writeFile(absolutePath, value, options); + } else { + writeFilePromise = pfs.writeFile(absolutePath, this.snapshotToReadableStream(value), options); + } } // Otherwise use encoding lib else { - const encoded = encoding.encode(value, encodingToWrite, { addBOM }); - writeFilePromise = pfs.writeFile(absolutePath, encoded, options); + if (typeof value === 'string') { + writeFilePromise = pfs.writeFile(absolutePath, encoding.encode(value, encodingToWrite, { addBOM }), options); + } else { + writeFilePromise = pfs.writeFile(absolutePath, this.snapshotToReadableStream(value).pipe(encoding.encodeStream(encodingToWrite, { addBOM })), options); + } } // set contents @@ -601,7 +608,32 @@ export class FileService implements IFileService { }); } - private doUpdateContentElevated(resource: uri, value: string, options: IUpdateContentOptions = Object.create(null)): TPromise { + private snapshotToReadableStream(snapshot: ITextSnapshot): NodeJS.ReadableStream { + return new Readable({ + read: function () { + try { + let chunk: string; + let canPush = true; + + // Push all chunks as long as we can push and as long as + // the underlying snapshot returns strings to us + while (canPush && typeof (chunk = snapshot.read()) === 'string') { + canPush = this.push(chunk); + } + + // Signal EOS by pushing NULL + if (typeof chunk !== 'string') { + this.push(null); + } + } catch (error) { + this.emit('error', error); + } + }, + encoding: encoding.UTF8 // very important, so that strings are passed around and not buffers! + }); + } + + private doUpdateContentElevated(resource: uri, value: string | ITextSnapshot, options: IUpdateContentOptions = Object.create(null)): TPromise { const absolutePath = this.toAbsolutePath(resource); // 1.) check file diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/node/fileService.test.ts index 3a97a2a5cec..378b1b91a08 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/node/fileService.test.ts @@ -22,6 +22,7 @@ import { onError } from 'vs/base/test/common/utils'; import { TestContextService, TestTextResourceConfigurationService, getRandomTestPath, TestLifecycleService } from 'vs/workbench/test/workbenchTestServices'; import { Workspace, toWorkspaceFolders } from 'vs/platform/workspace/common/workspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { TextModel } from 'vs/editor/common/model/textModel'; suite('FileService', () => { let service: FileService; @@ -581,6 +582,54 @@ suite('FileService', () => { }, error => onError(error, done)); }); + test('updateContent (ITextSnapShot)', function (done: () => void) { + const resource = uri.file(path.join(testDir, 'small.txt')); + + service.resolveContent(resource).done(c => { + assert.equal(c.value, 'Small File'); + + const model = TextModel.createFromString('Updates to the small file'); + + return service.updateContent(c.resource, model.createSnapshot()).then(c => { + assert.equal(fs.readFileSync(resource.fsPath), 'Updates to the small file'); + + model.dispose(); + + done(); + }); + }, error => onError(error, done)); + }); + + test('updateContent (large file)', function (done: () => void) { + const resource = uri.file(path.join(testDir, 'lorem.txt')); + + service.resolveContent(resource).done(c => { + const newValue = c.value + c.value; + c.value = newValue; + + return service.updateContent(c.resource, c.value).then(c => { + assert.equal(fs.readFileSync(resource.fsPath), newValue); + + done(); + }); + }, error => onError(error, done)); + }); + + test('updateContent (large file, ITextSnapShot)', function (done: () => void) { + const resource = uri.file(path.join(testDir, 'lorem.txt')); + + service.resolveContent(resource).done(c => { + const newValue = c.value + c.value; + const model = TextModel.createFromString(newValue); + + return service.updateContent(c.resource, model.createSnapshot()).then(c => { + assert.equal(fs.readFileSync(resource.fsPath), newValue); + + done(); + }); + }, error => onError(error, done)); + }); + test('updateContent - use encoding (UTF 16 BE)', function (done: () => void) { const resource = uri.file(path.join(testDir, 'small.txt')); const encoding = 'utf16be'; @@ -602,6 +651,31 @@ suite('FileService', () => { }, error => onError(error, done)); }); + test('updateContent - use encoding (UTF 16 BE, ITextSnapShot)', function (done: () => void) { + const resource = uri.file(path.join(testDir, 'small.txt')); + const encoding = 'utf16be'; + + service.resolveContent(resource).done(c => { + c.encoding = encoding; + + const model = TextModel.createFromString(c.value); + + return service.updateContent(c.resource, model.createSnapshot(), { encoding: encoding }).then(c => { + return encodingLib.detectEncodingByBOM(c.resource.fsPath).then((enc) => { + assert.equal(enc, encodingLib.UTF16be); + + return service.resolveContent(resource).then(c => { + assert.equal(c.encoding, encoding); + + model.dispose(); + + done(); + }); + }); + }); + }, error => onError(error, done)); + }); + test('updateContent - encoding preserved (UTF 16 LE)', function (done: () => void) { const encoding = 'utf16le'; const resource = uri.file(path.join(testDir, 'some_utf16le.css')); @@ -625,6 +699,31 @@ suite('FileService', () => { }, error => onError(error, done)); }); + test('updateContent - encoding preserved (UTF 16 LE, ITextSnapShot)', function (done: () => void) { + const encoding = 'utf16le'; + const resource = uri.file(path.join(testDir, 'some_utf16le.css')); + + service.resolveContent(resource).done(c => { + assert.equal(c.encoding, encoding); + + const model = TextModel.createFromString('Some updates'); + + return service.updateContent(c.resource, model.createSnapshot(), { encoding: encoding }).then(c => { + return encodingLib.detectEncodingByBOM(c.resource.fsPath).then((enc) => { + assert.equal(enc, encodingLib.UTF16le); + + return service.resolveContent(resource).then(c => { + assert.equal(c.encoding, encoding); + + model.dispose(); + + done(); + }); + }); + }); + }, error => onError(error, done)); + }); + test('resolveContent - large file', function (done: () => void) { const resource = uri.file(path.join(testDir, 'lorem.txt')); @@ -846,26 +945,32 @@ suite('FileService', () => { fs.readFile(resource.fsPath, (error, data) => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); + const model = TextModel.createFromString('Hello Bom'); + // Update content: UTF_8 => UTF_8_BOM - _service.updateContent(resource, 'Hello Bom', { encoding: encodingLib.UTF8_with_bom }).done(() => { + _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8_with_bom }).done(() => { fs.readFile(resource.fsPath, (error, data) => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), encodingLib.UTF8); // Update content: PRESERVE BOM when using UTF-8 - _service.updateContent(resource, 'Please stay Bom', { encoding: encodingLib.UTF8 }).done(() => { + model.setValue('Please stay Bom'); + _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).done(() => { fs.readFile(resource.fsPath, (error, data) => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), encodingLib.UTF8); // Update content: REMOVE BOM - _service.updateContent(resource, 'Go away Bom', { encoding: encodingLib.UTF8, overwriteEncoding: true }).done(() => { + model.setValue('Go away Bom'); + _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8, overwriteEncoding: true }).done(() => { fs.readFile(resource.fsPath, (error, data) => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); // Update content: BOM comes not back - _service.updateContent(resource, 'Do not come back Bom', { encoding: encodingLib.UTF8 }).done(() => { + model.setValue('Do not come back Bom'); + _service.updateContent(resource, model.createSnapshot(), { encoding: encodingLib.UTF8 }).done(() => { fs.readFile(resource.fsPath, (error, data) => { assert.equal(encodingLib.detectEncodingByBOMFromBuffer(data, 512), null); + model.dispose(); _service.dispose(); done(); }); diff --git a/src/vs/workbench/services/message/browser/messageList.ts b/src/vs/workbench/services/message/browser/messageList.ts index a882703c7ae..25819ba5062 100644 --- a/src/vs/workbench/services/message/browser/messageList.ts +++ b/src/vs/workbench/services/message/browser/messageList.ts @@ -190,6 +190,18 @@ export class MessageList { private doShowMessage(id: Error, message: string, severity: Severity, onHide: () => void): () => void; private doShowMessage(id: IMessageWithAction, message: string, severity: Severity, onHide: () => void): () => void; private doShowMessage(id: any, message: string, severity: Severity, onHide: () => void): () => void { + const actions = (id).actions; + const source = (id).source || 'vscode'; + + // Telemetry (TODO@Ben remove me later) + /* __GDPR__ + "showMessage" : { + "message" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "buttons" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('showMessage', { message, source, buttons: actions ? actions.map(a => a.label) : void 0 }); // Trigger Auto-Purge of messages to keep list small this.purgeMessages(); @@ -200,8 +212,8 @@ export class MessageList { text: message, severity: severity, time: Date.now(), - actions: (id).actions, - source: (id).source, + actions, + source, onHide }); diff --git a/src/vs/workbench/services/message/electron-browser/messageService.ts b/src/vs/workbench/services/message/electron-browser/messageService.ts index 0c04c556de5..6e7a376cd96 100644 --- a/src/vs/workbench/services/message/electron-browser/messageService.ts +++ b/src/vs/workbench/services/message/electron-browser/messageService.ts @@ -13,7 +13,7 @@ import { IConfirmation, Severity, IChoiceService, IConfirmationResult } from 'vs import { isLinux } from 'vs/base/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Action } from 'vs/base/common/actions'; -import { IWindowService, IMessageBoxResult } from 'vs/platform/windows/common/windows'; +import { IWindowService } from 'vs/platform/windows/common/windows'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; export class MessageService extends WorkbenchMessageService implements IChoiceService { @@ -27,31 +27,22 @@ export class MessageService extends WorkbenchMessageService implements IChoiceSe } public confirmWithCheckbox(confirmation: IConfirmation): TPromise { - const opts = this.getConfirmOptions(confirmation); - - return this.showMessageBoxWithCheckbox(opts).then(result => { - return { - confirmed: result.button === 0 ? true : false, - checkboxChecked: result.checkboxChecked - } as IConfirmationResult; - }); - } - - private showMessageBoxWithCheckbox(opts: Electron.MessageBoxOptions): TPromise { - opts = this.massageMessageBoxOptions(opts); + const opts = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation)); return this.windowService.showMessageBox(opts).then(result => { + const button = isLinux ? opts.buttons.length - result.button - 1 : result.button; + return { - button: isLinux ? opts.buttons.length - result.button - 1 : result.button, + confirmed: button === 0 ? true : false, checkboxChecked: result.checkboxChecked - } as IMessageBoxResult; + } as IConfirmationResult; }); } public confirm(confirmation: IConfirmation): TPromise { const opts = this.getConfirmOptions(confirmation); - return this.showMessageBox(opts).then(result => result === 0 ? true : false); + return this.doShowMessageBox(opts).then(result => result === 0 ? true : false); } private getConfirmOptions(confirmation: IConfirmation): Electron.MessageBoxOptions { @@ -94,16 +85,25 @@ export class MessageService extends WorkbenchMessageService implements IChoiceSe public choose(severity: Severity, message: string, options: string[], cancelId: number, modal: boolean = false): TPromise { if (modal) { - const type: 'none' | 'info' | 'error' | 'question' | 'warning' = severity === Severity.Info ? 'question' : severity === Severity.Error ? 'error' : severity === Severity.Warning ? 'warning' : 'none'; - - return this.showMessageBox({ message, buttons: options, type, cancelId }); + return this.doChooseModal(severity, message, options, cancelId); } + return this.doChooseWithMessage(severity, message, options); + } + + private doChooseModal(severity: Severity, message: string, options: string[], cancelId: number): TPromise { + const type: 'none' | 'info' | 'error' | 'question' | 'warning' = severity === Severity.Info ? 'question' : severity === Severity.Error ? 'error' : severity === Severity.Warning ? 'warning' : 'none'; + + return this.doShowMessageBox({ message, buttons: options, type, cancelId }); + } + + private doChooseWithMessage(severity: Severity, message: string, options: string[]): TPromise { let onCancel: () => void = null; const promise = new TPromise((c, e) => { const callback = (index: number) => () => { c(index); + return TPromise.as(true); }; @@ -115,7 +115,7 @@ export class MessageService extends WorkbenchMessageService implements IChoiceSe return promise; } - private showMessageBox(opts: Electron.MessageBoxOptions): TPromise { + private doShowMessageBox(opts: Electron.MessageBoxOptions): TPromise { opts = this.massageMessageBoxOptions(opts); return this.windowService.showMessageBox(opts).then(result => isLinux ? opts.buttons.length - result.button - 1 : result.button); diff --git a/src/vs/workbench/services/progress/browser/progressService2.ts b/src/vs/workbench/services/progress/browser/progressService2.ts index 8c87a033e1c..ad8d9889ea9 100644 --- a/src/vs/workbench/services/progress/browser/progressService2.ts +++ b/src/vs/workbench/services/progress/browser/progressService2.ts @@ -75,6 +75,8 @@ export class ProgressService2 implements IProgressService2 { return this._withWindowProgress(options, task); case ProgressLocation.Scm: return this._withViewletProgress('workbench.view.scm', task); + case ProgressLocation.Extensions: + return this._withViewletProgress('workbench.view.extensions', task); default: console.warn(`Bad progress location: ${location}`); return undefined; diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index 2e6d6ed3caa..6917c8da877 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -118,7 +118,7 @@ export class FileWalker { this.isCanceled = true; } - public walk(folderQueries: IFolderSearch[], extraFiles: string[], onResult: (result: IRawFileMatch) => void, done: (error: Error, isLimitHit: boolean) => void): void { + public walk(folderQueries: IFolderSearch[], extraFiles: string[], onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgress) => void, done: (error: Error, isLimitHit: boolean) => void): void { this.fileWalkStartTime = Date.now(); // Support that the file pattern is a full path to a file that exists @@ -180,7 +180,7 @@ export class FileWalker { // For each root folder flow.parallel(folderQueries, (folderQuery: IFolderSearch, rootFolderDone: (err: Error, result: void) => void) => { - this.call(traverse, this, folderQuery, onResult, (err?: Error) => { + this.call(traverse, this, folderQuery, onResult, onMessage, (err?: Error) => { if (err) { const errorMessage = toErrorMessage(err); console.error(errorMessage); @@ -205,7 +205,7 @@ export class FileWalker { } } - private cmdTraversal(folderQuery: IFolderSearch, onResult: (result: IRawFileMatch) => void, cb: (err?: Error) => void): void { + private cmdTraversal(folderQuery: IFolderSearch, onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgress) => void, cb: (err?: Error) => void): void { const rootFolder = folderQuery.folder; const isMac = platform.isMacintosh; let cmd: childProcess.ChildProcess; @@ -227,6 +227,18 @@ export class FileWalker { const ripgrep = spawnRipgrepCmd(this.config, folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder).expression); cmd = ripgrep.cmd; noSiblingsClauses = !Object.keys(ripgrep.siblingClauses).length; + + process.nextTick(() => { + const escapedArgs = ripgrep.rgArgs.args + .map(arg => arg.match(/^-/) ? arg : `'${arg}'`) + .join(' '); + + let rgCmd = `rg ${escapedArgs}\n - cwd: ${ripgrep.cwd}`; + if (ripgrep.rgArgs.siblingClauses) { + rgCmd += `\n - Sibling clauses: ${JSON.stringify(ripgrep.rgArgs.siblingClauses)}`; + } + onMessage({ message: rgCmd }); + }); } else { cmd = this.spawnFindCmd(folderQuery); } @@ -504,7 +516,7 @@ export class FileWalker { matchDirectory(rootEntries); } - private nodeJSTraversal(folderQuery: IFolderSearch, onResult: (result: IRawFileMatch) => void, done: (err?: Error) => void): void { + private nodeJSTraversal(folderQuery: IFolderSearch, onResult: (result: IRawFileMatch) => void, onMessage: (message: IProgress) => void, done: (err?: Error) => void): void { this.directoriesWalked++; extfs.readdir(folderQuery.folder, (error: Error, files: string[]) => { if (error || this.isCanceled || this.isLimitHit) { @@ -730,7 +742,7 @@ export class Engine implements ISearchEngine { } public search(onResult: (result: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { - this.walker.walk(this.folderQueries, this.extraFiles, onResult, (err: Error, isLimitHit: boolean) => { + this.walker.walk(this.folderQueries, this.extraFiles, onResult, onProgress, (err: Error, isLimitHit: boolean) => { done(err, { limitHit: isLimitHit, stats: this.walker.getStats() diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index b4956230b48..82cc34039d1 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -367,7 +367,9 @@ export class SearchService implements IRawSearchService { } } }, (progress) => { - p(progress); + process.nextTick(() => { + p(progress); + }); }, (error, stats) => { if (batch.length) { p(batch); diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 50fa1077c40..9b73f7739ec 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -15,9 +15,12 @@ import { foldersToIncludeGlobs, foldersToRgExcludeGlobs } from './ripgrepTextSea export function spawnRipgrepCmd(config: IRawSearch, folderQuery: IFolderSearch, includePattern: glob.IExpression, excludePattern: glob.IExpression) { const rgArgs = getRgArgs(config, folderQuery, includePattern, excludePattern); + const cwd = folderQuery.folder; return { - cmd: cp.spawn(rgPath, rgArgs.globArgs, { cwd: folderQuery.folder }), - siblingClauses: rgArgs.siblingClauses + cmd: cp.spawn(rgPath, rgArgs.args, { cwd }), + siblingClauses: rgArgs.siblingClauses, + rgArgs, + cwd }; } @@ -57,7 +60,7 @@ function getRgArgs(config: IRawSearch, folderQuery: IFolderSearch, includePatter args.push('.'); - return { globArgs: args, siblingClauses }; + return { args, siblingClauses }; } function anchor(glob: string) { diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts index 8742487da29..72ecb4b919d 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearch.ts @@ -18,10 +18,10 @@ import * as paths from 'vs/base/common/paths'; import * as extfs from 'vs/base/node/extfs'; import * as encoding from 'vs/base/node/encoding'; import * as glob from 'vs/base/common/glob'; -import { ISearchLog } from 'vs/platform/search/common/search'; import { TPromise } from 'vs/base/common/winjs.base'; import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, IFolderSearch, LineMatch, FileMatch } from './search'; +import { IProgress } from 'vs/platform/search/common/search'; export class RipgrepEngine { private isDone = false; @@ -44,7 +44,7 @@ export class RipgrepEngine { } // TODO@Rob - make promise-based once the old search is gone, and I don't need them to have matching interfaces anymore - search(onResult: (match: ISerializedFileMatch) => void, onMessage: (message: ISearchLog) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { + search(onResult: (match: ISerializedFileMatch) => void, onMessage: (message: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { if (!this.config.folderQueries.length && !this.config.extraFiles.length) { process.removeListener('exit', this.killRgProcFn); done(null, { @@ -61,17 +61,18 @@ export class RipgrepEngine { const cwd = platform.isWindows ? 'c:/' : '/'; process.nextTick(() => { // Allow caller to register progress callback - const escapedArgs = rgArgs.globArgs + const escapedArgs = rgArgs.args .map(arg => arg.match(/^-/) ? arg : `'${arg}'`) .join(' '); - const rgCmd = `rg ${escapedArgs}\n - cwd: ${cwd}\n`; - onMessage({ message: rgCmd }); + let rgCmd = `rg ${escapedArgs}\n - cwd: ${cwd}`; if (rgArgs.siblingClauses) { - onMessage({ message: ` - Sibling clauses: ${JSON.stringify(rgArgs.siblingClauses)}\n` }); + rgCmd += `\n - Sibling clauses: ${JSON.stringify(rgArgs.siblingClauses)}`; } + + onMessage({ message: rgCmd }); }); - this.rgProc = cp.spawn(rgPath, rgArgs.globArgs, { cwd }); + this.rgProc = cp.spawn(rgPath, rgArgs.args, { cwd }); process.once('exit', this.killRgProcFn); this.ripgrepParser = new RipgrepParser(this.config.maxResults, cwd, this.config.extraFiles); @@ -421,7 +422,7 @@ export function fixDriveC(path: string): string { path; } -function getRgArgs(config: IRawSearch): IRgGlobResult { +function getRgArgs(config: IRawSearch) { const args = ['--hidden', '--heading', '--line-number', '--color', 'ansi', '--colors', 'path:none', '--colors', 'line:none', '--colors', 'match:fg:red', '--colors', 'match:style:nobold']; if (config.contentPattern.isSmartCase) { args.push('--smart-case'); @@ -499,7 +500,7 @@ function getRgArgs(config: IRawSearch): IRgGlobResult { args.push(...config.folderQueries.map(q => q.folder)); args.push(...config.extraFiles); - return { globArgs: args, siblingClauses }; + return { args, siblingClauses }; } function getSiblings(file: string): TPromise { diff --git a/src/vs/workbench/services/search/node/search.ts b/src/vs/workbench/services/search/node/search.ts index 1c5c4947e7a..a1061c52d22 100644 --- a/src/vs/workbench/services/search/node/search.ts +++ b/src/vs/workbench/services/search/node/search.ts @@ -7,7 +7,7 @@ import { PPromise, TPromise } from 'vs/base/common/winjs.base'; import { IExpression } from 'vs/base/common/glob'; -import { IProgress, ILineMatch, IPatternInfo, ISearchStats, ISearchLog } from 'vs/platform/search/common/search'; +import { IProgress, ILineMatch, IPatternInfo, ISearchStats } from 'vs/platform/search/common/search'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; export interface IFolderSearch { @@ -71,7 +71,7 @@ export interface ISerializedFileMatch { } // Type of the possible values for progress calls from the engine -export type ISerializedSearchProgressItem = ISerializedFileMatch | ISerializedFileMatch[] | IProgress | ISearchLog; +export type ISerializedSearchProgressItem = ISerializedFileMatch | ISerializedFileMatch[] | IProgress; export type IFileSearchProgressItem = IRawFileMatch | IRawFileMatch[] | IProgress; diff --git a/src/vs/workbench/services/search/node/searchService.ts b/src/vs/workbench/services/search/node/searchService.ts index 8284c0f6c74..bbfe0682918 100644 --- a/src/vs/workbench/services/search/node/searchService.ts +++ b/src/vs/workbench/services/search/node/searchService.ts @@ -22,6 +22,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Schemas } from 'vs/base/common/network'; +import { ILogService } from 'vs/platform/log/common/log'; export class SearchService implements ISearchService { public _serviceBrand: any; @@ -35,7 +36,8 @@ export class SearchService implements ISearchService { @IUntitledEditorService private untitledEditorService: IUntitledEditorService, @IEnvironmentService environmentService: IEnvironmentService, @ITelemetryService private telemetryService: ITelemetryService, - @IConfigurationService private configurationService: IConfigurationService + @IConfigurationService private configurationService: IConfigurationService, + @ILogService private logService: ILogService ) { this.diskSearch = new DiskSearch(!environmentService.isBuilt || environmentService.verbose, /*timeout=*/undefined, environmentService.debugSearch); this.registerSearchResultProvider(this.diskSearch); @@ -104,6 +106,10 @@ export class SearchService implements ISearchService { // Progress onProgress(progress); } + + if (progress.message) { + this.logService.info('SearchService#search', progress.message); + } } )); diff --git a/src/vs/workbench/services/search/node/textSearch.ts b/src/vs/workbench/services/search/node/textSearch.ts index b5a62eb9023..c2002bb88ed 100644 --- a/src/vs/workbench/services/search/node/textSearch.ts +++ b/src/vs/workbench/services/search/node/textSearch.ts @@ -147,20 +147,22 @@ export class Engine implements ISearchEngine { nextBatch = []; nextBatchBytes = 0; } - }, (error, isLimitHit) => { - this.walkerIsDone = true; - this.walkerError = error; + }, + onProgress, + (error, isLimitHit) => { + this.walkerIsDone = true; + this.walkerError = error; - // Send any remaining paths to a worker, or unwind if we're stopping - if (nextBatch.length) { - if (this.limitReached || this.isCanceled) { - unwind(nextBatchBytes); + // Send any remaining paths to a worker, or unwind if we're stopping + if (nextBatch.length) { + if (this.limitReached || this.isCanceled) { + unwind(nextBatchBytes); + } else { + run(nextBatch, nextBatchBytes); + } } else { - run(nextBatch, nextBatchBytes); + unwind(0); } - } else { - unwind(0); - } - }); + }); } } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index fc18f6c5656..981d07eaca2 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -22,8 +22,8 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; -import { IBackupFileService, BACKUP_FILE_RESOLVE_OPTIONS } from 'vs/workbench/services/backup/common/backup'; -import { IFileService, IFileStat, FileOperationError, FileOperationResult, IContent, CONTENT_CHANGE_EVENT_BUFFER_DELAY, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files'; +import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; +import { IFileService, IFileStat, FileOperationError, FileOperationResult, CONTENT_CHANGE_EVENT_BUFFER_DELAY, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -32,6 +32,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RunOnceScheduler } from 'vs/base/common/async'; import { ITextBufferFactory } from 'vs/editor/common/model'; import { IHashService } from 'vs/workbench/services/hash/common/hashService'; +import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; /** * The text file editor model listens to changes to its underlying code editor model and saves these changes through the file service back to the disk. @@ -188,7 +189,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return; } - const firstLineText = this.getFirstLineText(this.textEditorModel.getValue()); + const firstLineText = this.getFirstLineText(this.textEditorModel.createSnapshot()); const mode = this.getOrCreateMode(this.modeService, modeId, firstLineText); this.modelService.setMode(this.textEditorModel, mode); @@ -290,12 +291,12 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // If we have a backup, continue loading with it if (!!backup) { - const content: IContent = { + const content: IRawTextContent = { resource: this.resource, name: paths.basename(this.resource.fsPath), mtime: Date.now(), etag: void 0, - value: '', /* will be filled later from backup */ + value: createTextBufferFactory(''), /* will be filled later from backup */ encoding: this.fileService.getEncoding(this.resource, this.preferredEncoding) }; @@ -355,7 +356,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return TPromise.wrapError(error); } - private loadWithContent(content: IRawTextContent | IContent, backup?: URI): TPromise { + private loadWithContent(content: IRawTextContent, backup?: URI): TPromise { return this.doLoadWithContent(content, backup).then(model => { // Telemetry: We log the fileGet telemetry event after the model has been loaded to ensure a good mimetype @@ -379,7 +380,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil }); } - private doLoadWithContent(content: IRawTextContent | IContent, backup?: URI): TPromise { + private doLoadWithContent(content: IRawTextContent, backup?: URI): TPromise { diag('load() - resolved content', this.resource, new Date()); // Update our resolved disk stat model @@ -420,7 +421,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return this.doCreateTextModel(content.resource, content.value, backup); } - private doUpdateTextModel(value: string | ITextBufferFactory): TPromise { + private doUpdateTextModel(value: ITextBufferFactory): TPromise { diag('load() - updated text editor model', this.resource, new Date()); // Ensure we are not tracking a stale state @@ -440,11 +441,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return TPromise.as(this); } - private doCreateTextModel(resource: URI, value: string | ITextBufferFactory, backup: URI): TPromise { + private doCreateTextModel(resource: URI, value: ITextBufferFactory, backup: URI): TPromise { diag('load() - created text editor model', this.resource, new Date()); this.createTextEditorModelPromise = this.doLoadBackup(backup).then(backupContent => { - const hasBackupContent = (typeof backupContent === 'string'); + const hasBackupContent = !!backupContent; return this.createTextEditorModel(hasBackupContent ? backupContent : value, resource).then(() => { this.createTextEditorModelPromise = null; @@ -488,14 +489,12 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil this.toDispose.push(this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged())); } - private doLoadBackup(backup: URI): TPromise { + private doLoadBackup(backup: URI): TPromise { if (!backup) { return TPromise.as(null); } - return this.textFileService.resolveTextContent(backup, BACKUP_FILE_RESOLVE_OPTIONS).then(backup => { - return this.backupFileService.parseBackupContent(backup.value); - }, error => null /* ignore errors */); + return this.backupFileService.resolveBackupContent(backup).then(backupContent => backupContent, error => null /* ignore errors */); } protected getOrCreateMode(modeService: IModeService, preferredModeIds: string, firstLineText?: string): TPromise { @@ -702,7 +701,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // Save to Disk // mark the save operation as currently pending with the versionId (it might have changed from a save participant triggering) diag(`doSave(${versionId}) - before updateContent()`, this.resource, new Date()); - return this.saveSequentializer.setPending(newVersionId, this.fileService.updateContent(this.lastResolvedDiskStat.resource, this.getValue(), { + return this.saveSequentializer.setPending(newVersionId, this.fileService.updateContent(this.lastResolvedDiskStat.resource, this.createSnapshot(), { overwriteReadonly: options.overwriteReadonly, overwriteEncoding: options.overwriteEncoding, mtime: this.lastResolvedDiskStat.mtime, diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 6e5bf84bf4a..42f1d466370 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -32,6 +32,8 @@ import { Schemas } from 'vs/base/common/network'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IRevertOptions } from 'vs/platform/editor/common/editor'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel'; +import { IModelService } from 'vs/editor/common/services/modelService'; export interface IBackupResult { didBackup: boolean; @@ -73,7 +75,8 @@ export abstract class TextFileService implements ITextFileService { private backupFileService: IBackupFileService, private windowsService: IWindowsService, private historyService: IHistoryService, - contextKeyService: IContextKeyService + contextKeyService: IContextKeyService, + private modelService: IModelService ) { this.toUnbind = []; @@ -241,7 +244,7 @@ export abstract class TextFileService implements ITextFileService { private doBackupAll(dirtyFileModels: ITextFileEditorModel[], untitledResources: URI[]): TPromise { // Handle file resources first - return TPromise.join(dirtyFileModels.map(model => this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId()))).then(results => { + return TPromise.join(dirtyFileModels.map(model => this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId()))).then(results => { // Handle untitled resources const untitledModelPromises = untitledResources @@ -250,7 +253,7 @@ export abstract class TextFileService implements ITextFileService { return TPromise.join(untitledModelPromises).then(untitledModels => { const untitledBackupPromises = untitledModels.map(model => { - return this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId()); + return this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId()); }); return TPromise.join(untitledBackupPromises).then(() => void 0); @@ -615,7 +618,7 @@ export abstract class TextFileService implements ITextFileService { // take over encoding and model value from source model targetModel.updatePreferredEncoding(sourceModel.getEncoding()); - targetModel.textEditorModel.setValue(sourceModel.getValue()); + this.modelService.updateModel(targetModel.textEditorModel, createTextBufferFactoryFromSnapshot(sourceModel.createSnapshot())); // save model return targetModel.save(options); diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index 4be8ffb329e..eacc46d1970 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -9,7 +9,7 @@ import URI from 'vs/base/common/uri'; import Event from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IEncodingSupport, ConfirmResult } from 'vs/workbench/common/editor'; -import { IBaseStat, IResolveContentOptions } from 'vs/platform/files/common/files'; +import { IBaseStat, IResolveContentOptions, ITextSnapshot } from 'vs/platform/files/common/files'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { ITextBufferFactory } from 'vs/editor/common/model'; @@ -200,7 +200,7 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport revert(soft?: boolean): TPromise; - getValue(): string; + createSnapshot(): ITextSnapshot; isDirty(): boolean; diff --git a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts index ecf4229c83b..1dcfc4c6334 100644 --- a/src/vs/workbench/services/textfile/electron-browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/textFileService.ts @@ -30,6 +30,7 @@ import { IWindowsService, IWindowService } from 'vs/platform/windows/common/wind import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IModelService } from 'vs/editor/common/services/modelService'; export class TextFileService extends AbstractTextFileService { @@ -41,6 +42,7 @@ export class TextFileService extends AbstractTextFileService { @IInstantiationService instantiationService: IInstantiationService, @IConfigurationService configurationService: IConfigurationService, @IModeService private modeService: IModeService, + @IModelService modelService: IModelService, @IWindowService private windowService: IWindowService, @IEnvironmentService environmentService: IEnvironmentService, @IMessageService messageService: IMessageService, @@ -49,7 +51,7 @@ export class TextFileService extends AbstractTextFileService { @IHistoryService historyService: IHistoryService, @IContextKeyService contextKeyService: IContextKeyService ) { - super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, messageService, environmentService, backupFileService, windowsService, historyService, contextKeyService); + super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, messageService, environmentService, backupFileService, windowsService, historyService, contextKeyService, modelService); } public resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise { diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts index 5e36065442d..d747bb23b3f 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts @@ -14,7 +14,7 @@ import { ITextFileService, ModelState, StateChange } from 'vs/workbench/services import { workbenchInstantiationService, TestTextFileService, createFileInput, TestFileService } from 'vs/workbench/test/workbenchTestServices'; import { onError, toResource } from 'vs/base/test/common/utils'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; -import { FileOperationResult, FileOperationError, IFileService } from 'vs/platform/files/common/files'; +import { FileOperationResult, FileOperationError, IFileService, snapshotToString } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; class ServiceAccessor { @@ -284,7 +284,7 @@ suite('Files - TextFileEditorModel', () => { model.onDidStateChange(e => { if (e === StateChange.SAVED) { - assert.equal(model.getValue(), 'bar'); + assert.equal(snapshotToString(model.createSnapshot()), 'bar'); assert.ok(!model.isDirty()); eventCounter++; } diff --git a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts index f5bde377342..3c904f154a4 100644 --- a/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts +++ b/src/vs/workbench/services/textmodelResolver/test/textModelResolverService.test.ts @@ -22,6 +22,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { once } from 'vs/base/common/event'; +import { snapshotToString } from 'vs/platform/files/common/files'; class ServiceAccessor { constructor( @@ -73,7 +74,7 @@ suite('Workbench - TextModelResolverService', () => { input.resolve().then(model => { assert.ok(model); - assert.equal((model as ResourceEditorModel).getValue(), 'Hello Test'); + assert.equal(snapshotToString((model as ResourceEditorModel).createSnapshot()), 'Hello Test'); let disposed = false; once(model.onDispose)(() => { diff --git a/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts b/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts index 37e0498d121..fd7ad73cded 100644 --- a/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts +++ b/src/vs/workbench/services/themes/electron-browser/colorThemeData.ts @@ -30,7 +30,7 @@ const tokenGroupToScopesMap: { [setting: string]: string[] } = { keywords: ['keyword', 'keyword.control', 'storage', 'storage.type'], numbers: ['constant.numeric'], types: ['entity.name.type', 'entity.name.class', 'support.type', 'support.class'], - functions: ['entity.name.function'], + functions: ['entity.name.function', 'support.function'], variables: ['variable'] }; diff --git a/src/vs/workbench/services/timer/common/timerService.ts b/src/vs/workbench/services/timer/common/timerService.ts index f6ca71866cb..bee527e3878 100644 --- a/src/vs/workbench/services/timer/common/timerService.ts +++ b/src/vs/workbench/services/timer/common/timerService.ts @@ -66,6 +66,7 @@ export interface IStartupMetrics { ellapsedEditorRestore: number; ellapsedWorkbench: number; ellapsedTimersToTimersComputed: number; + ellapsedNlsGeneration: number; }; platform: string; release: string; diff --git a/src/vs/workbench/services/timer/node/timerService.ts b/src/vs/workbench/services/timer/node/timerService.ts index 7a49b00ba65..1de3ba8f6cc 100644 --- a/src/vs/workbench/services/timer/node/timerService.ts +++ b/src/vs/workbench/services/timer/node/timerService.ts @@ -70,6 +70,9 @@ export class TimerService implements ITimerService { // ignore, be on the safe side with these hardware method calls } + let nlsStart = perf.getEntry('mark', 'nlsGeneration:start'); + let nlsEnd = perf.getEntry('mark', 'nlsGeneration:end'); + let nlsTime = nlsStart && nlsEnd ? nlsEnd.startTime - nlsStart.startTime : 0; this._startupMetrics = { version: 1, ellapsed: perf.getEntry('mark', 'didStartWorkbench').startTime - start, @@ -81,7 +84,8 @@ export class TimerService implements ITimerService { ellapsedViewletRestore: perf.getDuration('willRestoreViewlet', 'didRestoreViewlet'), ellapsedWorkbench: perf.getDuration('willStartWorkbench', 'didStartWorkbench'), ellapsedWindowLoadToRequire: perf.getEntry('mark', 'willLoadWorkbenchMain').startTime - this.windowLoad, - ellapsedTimersToTimersComputed: Date.now() - now + ellapsedTimersToTimersComputed: Date.now() - now, + ellapsedNlsGeneration: nlsTime }, platform, release, diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index 3e22bf28ba6..920be3ef667 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -27,6 +27,12 @@ export interface IWorkspaceEditingService { */ removeFolders(folders: URI[], donotNotifyError?: boolean): TPromise; + /** + * Allows to add and remove folders to the existing workspace at once. + * When `donotNotifyError` is `true`, error will be bubbled up otherwise, the service handles the error with proper message and action + */ + updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): TPromise; + /** * creates a new workspace with the provided folders and opens it. if path is provided * the workspace will be saved into that location. diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index 7bb21530f42..c35254fc87f 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -47,16 +47,56 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { ) { } + public updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): TPromise { + const folders = this.contextService.getWorkspace().folders; + + let foldersToDelete: URI[] = []; + if (typeof deleteCount === 'number') { + foldersToDelete = folders.slice(index, index + deleteCount).map(f => f.uri); + } + + const wantsToDelete = foldersToDelete.length > 0; + const wantsToAdd = Array.isArray(foldersToAdd) && foldersToAdd.length > 0; + + if (!wantsToAdd && !wantsToDelete) { + return TPromise.as(void 0); // return early if there is nothing to do + } + + // Add Folders + if (wantsToAdd && !wantsToDelete) { + return this.doAddFolders(foldersToAdd, index, donotNotifyError); + } + + // Delete Folders + if (wantsToDelete && !wantsToAdd) { + return this.removeFolders(foldersToDelete); + } + + // Add & Delete Folders + if (this.includesSingleFolderWorkspace(foldersToDelete)) { + // if we are in single-folder state and the folder is replaced with + // other folders, we handle this specially and just enter workspace + // mode with the folders that are being added. + return this.createAndEnterWorkspace(foldersToAdd); + } + + // Make sure to first remove folders and then add them to account for folders being updated + return this.removeFolders(foldersToDelete).then(() => this.doAddFolders(foldersToAdd, index, donotNotifyError)); + } + public addFolders(foldersToAdd: IWorkspaceFolderCreationData[], donotNotifyError: boolean = false): TPromise { + return this.doAddFolders(foldersToAdd, void 0, donotNotifyError); + } + + private doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number, donotNotifyError: boolean = false): TPromise { const state = this.contextService.getWorkbenchState(); // If we are in no-workspace or single-folder workspace, adding folders has to // enter a workspace. if (state !== WorkbenchState.WORKSPACE) { - const newWorkspaceFolders: IWorkspaceFolderCreationData[] = distinct([ - ...this.contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri } as IWorkspaceFolderCreationData)), - ...foldersToAdd - ] as IWorkspaceFolderCreationData[], folder => isLinux ? folder.uri.toString() : folder.uri.toString().toLowerCase()); + let newWorkspaceFolders = this.contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri } as IWorkspaceFolderCreationData)); + newWorkspaceFolders.splice(typeof index === 'number' ? index : newWorkspaceFolders.length, 0, ...foldersToAdd); + newWorkspaceFolders = distinct(newWorkspaceFolders, folder => isLinux ? folder.uri.toString() : folder.uri.toString().toLowerCase()); if (state === WorkbenchState.EMPTY && newWorkspaceFolders.length === 0 || state === WorkbenchState.FOLDER && newWorkspaceFolders.length === 1) { return TPromise.as(void 0); // return if the operation is a no-op for the current state @@ -66,19 +106,16 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { } // Delegate addition of folders to workspace service otherwise - return this.contextService.addFolders(foldersToAdd) + return this.contextService.addFolders(foldersToAdd, index) .then(() => null, error => donotNotifyError ? TPromise.wrapError(error) : this.handleWorkspaceConfigurationEditingError(error)); } public removeFolders(foldersToRemove: URI[], donotNotifyError: boolean = false): TPromise { // If we are in single-folder state and the opened folder is to be removed, - // we close the workspace and enter the empty workspace state for the window. - if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { - const workspaceFolder = this.contextService.getWorkspace().folders[0]; - if (foldersToRemove.some(folder => isEqual(folder, workspaceFolder.uri, !isLinux))) { - return this.windowService.closeWorkspace(); - } + // we create an empty workspace and enter it. + if (this.includesSingleFolderWorkspace(foldersToRemove)) { + return this.createAndEnterWorkspace([]); } // Delegate removal of folders to workspace service otherwise @@ -86,6 +123,15 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { .then(() => null, error => donotNotifyError ? TPromise.wrapError(error) : this.handleWorkspaceConfigurationEditingError(error)); } + private includesSingleFolderWorkspace(folders: URI[]): boolean { + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + const workspaceFolder = this.contextService.getWorkspace().folders[0]; + return (folders.some(folder => isEqual(folder, workspaceFolder.uri, !isLinux))); + } + + return false; + } + public createAndEnterWorkspace(folders?: IWorkspaceFolderCreationData[], path?: string): TPromise { return this.doEnterWorkspace(() => this.windowService.createAndEnterWorkspace(folders, path)); } diff --git a/src/vs/workbench/test/common/editor/editorModel.test.ts b/src/vs/workbench/test/common/editor/editorModel.test.ts index b0c237b73bb..843e19701a6 100644 --- a/src/vs/workbench/test/common/editor/editorModel.test.ts +++ b/src/vs/workbench/test/common/editor/editorModel.test.ts @@ -15,9 +15,16 @@ import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; +import { ITextBufferFactory } from 'vs/editor/common/model'; +import URI from 'vs/base/common/uri'; +import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; class MyEditorModel extends EditorModel { } -class MyTextEditorModel extends BaseTextEditorModel { } +class MyTextEditorModel extends BaseTextEditorModel { + public createTextEditorModel(value: ITextBufferFactory, resource?: URI, modeId?: string) { + return super.createTextEditorModel(value, resource, modeId); + } +} suite('Workbench - EditorModel', () => { @@ -51,9 +58,9 @@ suite('Workbench - EditorModel', () => { let modelService = stubModelService(instantiationService); let m = new MyTextEditorModel(modelService, modeService); - m.load().then((model: any) => { + m.load().then((model: MyTextEditorModel) => { assert(model === m); - return model.createTextEditorModel('foo', null, 'text/plain').then(() => { + return model.createTextEditorModel(createTextBufferFactory('foo'), null, 'text/plain').then(() => { assert.strictEqual(m.isResolved(), true); }); }).done(() => { diff --git a/src/vs/workbench/test/common/editor/resourceEditorInput.test.ts b/src/vs/workbench/test/common/editor/resourceEditorInput.test.ts index 85c63eb3e1b..bed57cb0b05 100644 --- a/src/vs/workbench/test/common/editor/resourceEditorInput.test.ts +++ b/src/vs/workbench/test/common/editor/resourceEditorInput.test.ts @@ -13,6 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; +import { snapshotToString } from 'vs/platform/files/common/files'; class ServiceAccessor { constructor( @@ -39,7 +40,7 @@ suite('Workbench - ResourceEditorInput', () => { return input.resolve().then((model: ResourceEditorModel) => { assert.ok(model); - assert.equal(model.getValue(), 'function test() {}'); + assert.equal(snapshotToString(model.createSnapshot()), 'function test() {}'); }); }); }); \ No newline at end of file diff --git a/src/vs/workbench/test/common/editor/untitledEditor.test.ts b/src/vs/workbench/test/common/editor/untitledEditor.test.ts index b7b8a04dd4a..8edf3bb24aa 100644 --- a/src/vs/workbench/test/common/editor/untitledEditor.test.ts +++ b/src/vs/workbench/test/common/editor/untitledEditor.test.ts @@ -17,6 +17,7 @@ import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorMo import { IModeService } from 'vs/editor/common/services/modeService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; +import { snapshotToString } from 'vs/platform/files/common/files'; export class TestUntitledEditorService extends UntitledEditorService { @@ -142,7 +143,7 @@ suite('Workbench - Untitled Editor', () => { assert.ok(!model1.isDirty()); return service.loadOrCreate({ initialValue: 'Hello World' }).then(model2 => { - assert.equal(model2.getValue(), 'Hello World'); + assert.equal(snapshotToString(model2.createSnapshot()), 'Hello World'); const input = service.createOrGet(); diff --git a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts index a4c0366b6e4..8ec74bfb073 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostDocumentSaveParticipant.test.ts @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; import { TextDocumentSaveReason, TextEdit, Position, EndOfLine } from 'vs/workbench/api/node/extHostTypes'; -import { MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol'; +import { MainThreadEditorsShape, WorkspaceEditDto } from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant'; import { SingleProxyRPCProtocol } from './testRPCProtocol'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -18,6 +18,7 @@ import * as vscode from 'vscode'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { NullLogService } from 'vs/platform/log/common/log'; +import { isResourceTextEdit, ResourceTextEdit } from 'vs/editor/common/modes'; suite('ExtHostDocumentSaveParticipant', () => { @@ -262,10 +263,10 @@ suite('ExtHostDocumentSaveParticipant', () => { test('event delivery, pushEdits sync', () => { - let edits: IWorkspaceResourceEdit[]; + let dto: WorkspaceEditDto; const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, new class extends mock() { - $tryApplyWorkspaceEdit(_edits: IWorkspaceResourceEdit[]) { - edits = _edits; + $tryApplyWorkspaceEdit(_edits: WorkspaceEditDto) { + dto = _edits; return TPromise.as(true); } }); @@ -278,16 +279,17 @@ suite('ExtHostDocumentSaveParticipant', () => { return participant.$participateInSave(resource, SaveReason.EXPLICIT).then(() => { sub.dispose(); - assert.equal(edits.length, 1); - assert.equal(edits[0].edits.length, 2); + assert.equal(dto.edits.length, 1); + assert.ok(isResourceTextEdit(dto.edits[0])); + assert.equal((dto.edits[0]).edits.length, 2); }); }); test('event delivery, concurrent change', () => { - let edits: IWorkspaceResourceEdit[]; + let edits: WorkspaceEditDto; const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, new class extends mock() { - $tryApplyWorkspaceEdit(_edits: IWorkspaceResourceEdit[]) { + $tryApplyWorkspaceEdit(_edits: WorkspaceEditDto) { edits = _edits; return TPromise.as(true); } @@ -321,16 +323,20 @@ suite('ExtHostDocumentSaveParticipant', () => { test('event delivery, two listeners -> two document states', () => { const participant = new ExtHostDocumentSaveParticipant(nullLogService, documents, new class extends mock() { - $tryApplyWorkspaceEdit(_edits: IWorkspaceResourceEdit[]) { + $tryApplyWorkspaceEdit(dto: WorkspaceEditDto) { - for (const { resource, edits } of _edits) { + for (const edit of dto.edits) { + if (!isResourceTextEdit(edit)) { + continue; + } + const { resource, edits } = edit; const uri = URI.revive(resource); - for (const { newText, range } of edits) { + for (const { text, range } of edits) { documents.$acceptModelChanged(uri.toString(), { changes: [{ range, + text, rangeLength: undefined, - text: newText }], eol: undefined, versionId: documents.getDocumentData(uri).version + 1 diff --git a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts index 256ebb6879f..ad73ec6a899 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -24,7 +24,7 @@ import { IHeapService } from 'vs/workbench/api/electron-browser/mainThreadHeapSe import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen'; -import { DocumentSymbolProviderRegistry, DocumentHighlightKind, Hover } from 'vs/editor/common/modes'; +import { DocumentSymbolProviderRegistry, DocumentHighlightKind, Hover, ResourceTextEdit } from 'vs/editor/common/modes'; import { getCodeLensData } from 'vs/editor/contrib/codelens/codelens'; import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } from 'vs/editor/contrib/goToDeclaration/goToDeclaration'; import { getHover } from 'vs/editor/contrib/hover/getHover'; @@ -641,7 +641,7 @@ suite('ExtHostLanguageFeatures', function () { // --- quick fix - test('Quick Fix, data conversion', function () { + test('Quick Fix, command data conversion', function () { disposables.push(extHost.registerCodeActionProvider(defaultSelector, { provideCodeActions(): vscode.Command[] { @@ -665,6 +665,34 @@ suite('ExtHostLanguageFeatures', function () { }); }); + test('Quick Fix, code action data conversion', function () { + + disposables.push(extHost.registerCodeActionProvider(defaultSelector, { + provideCodeActions(): vscode.CodeAction[] { + return [ + { + title: 'Testing1', + command: { title: 'Testing1Command', command: 'test1' }, + kind: types.CodeActionKind.Empty.append('test.scope') + } + ]; + } + })); + + return rpcProtocol.sync().then(() => { + return getCodeActions(model, model.getFullModelRange()).then(value => { + assert.equal(value.length, 1); + + const [first] = value; + assert.equal(first.title, 'Testing1'); + assert.equal(first.command.title, 'Testing1Command'); + assert.equal(first.command.id, 'test1'); + assert.equal(first.kind, 'test.scope'); + }); + }); + }); + + test('Cannot read property \'id\' of undefined, #29469', function () { disposables.push(extHost.registerCodeActionProvider(defaultSelector, { @@ -812,7 +840,8 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return rename(model, new EditorPosition(1, 1), 'newName').then(value => { - assert.equal(value.edits.length, 2); // least relevant renamer + assert.equal(value.edits.length, 1); // least relevant renamer + assert.equal((value.edits)[0].edits.length, 2); // least relevant renamer }); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostTextEditors.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTextEditors.test.ts index b5ec3f55274..41663d277ef 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTextEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTextEditors.test.ts @@ -7,25 +7,26 @@ import * as assert from 'assert'; import { TPromise } from 'vs/base/common/winjs.base'; import * as extHostTypes from 'vs/workbench/api/node/extHostTypes'; -import { MainContext, MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol'; +import { MainContext, MainThreadEditorsShape, WorkspaceEditDto } from 'vs/workbench/api/node/extHost.protocol'; import URI from 'vs/base/common/uri'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; import { SingleProxyRPCProtocol, TestRPCProtocol } from 'vs/workbench/test/electron-browser/api/testRPCProtocol'; import { ExtHostEditors } from 'vs/workbench/api/node/extHostTextEditors'; +import { ResourceTextEdit } from 'vs/editor/common/modes'; suite('ExtHostTextEditors.applyWorkspaceEdit', () => { const resource = URI.parse('foo:bar'); let editors: ExtHostEditors; - let workspaceResourceEdits: IWorkspaceResourceEdit[]; + let workspaceResourceEdits: WorkspaceEditDto; setup(() => { workspaceResourceEdits = null; let rpcProtocol = new TestRPCProtocol(); rpcProtocol.set(MainContext.MainThreadEditors, new class extends mock() { - $tryApplyWorkspaceEdit(_workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise { + $tryApplyWorkspaceEdit(_workspaceResourceEdits: WorkspaceEditDto): TPromise { workspaceResourceEdits = _workspaceResourceEdits; return TPromise.as(true); } @@ -48,8 +49,8 @@ suite('ExtHostTextEditors.applyWorkspaceEdit', () => { let edit = new extHostTypes.WorkspaceEdit(); edit.replace(resource, new extHostTypes.Range(0, 0, 0, 0), 'hello'); return editors.applyWorkspaceEdit(edit).then((result) => { - assert.equal(workspaceResourceEdits.length, 1); - assert.equal(workspaceResourceEdits[0].modelVersionId, 1337); + assert.equal(workspaceResourceEdits.edits.length, 1); + assert.equal((workspaceResourceEdits.edits[0]).modelVersionId, 1337); }); }); @@ -57,8 +58,8 @@ suite('ExtHostTextEditors.applyWorkspaceEdit', () => { let edit = new extHostTypes.WorkspaceEdit(); edit.replace(URI.parse('foo:bar2'), new extHostTypes.Range(0, 0, 0, 0), 'hello'); return editors.applyWorkspaceEdit(edit).then((result) => { - assert.equal(workspaceResourceEdits.length, 1); - assert.ok(typeof workspaceResourceEdits[0].modelVersionId === 'undefined'); + assert.equal(workspaceResourceEdits.edits.length, 1); + assert.ok(typeof (workspaceResourceEdits.edits[0]).modelVersionId === 'undefined'); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts index 3cd1208f264..478b506e60f 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTypes.test.ts @@ -362,6 +362,53 @@ suite('ExtHostTypes', function () { }); + // test('WorkspaceEdit should fail when editing deleted resource', () => { + // const resource = URI.parse('file:///a.ts'); + + // const edit = new types.WorkspaceEdit(); + // edit.deleteResource(resource); + // try { + // edit.insert(resource, new types.Position(0, 0), ''); + // assert.fail(false, 'Should disallow edit of deleted resource'); + // } catch { + // // expected + // } + // }); + + test('WorkspaceEdit - keep order of text and file changes', function () { + + const edit = new types.WorkspaceEdit(); + edit.replace(URI.parse('foo:a'), new types.Range(1, 1, 1, 1), 'foo'); + edit.renameResource(URI.parse('foo:a'), URI.parse('foo:b')); + edit.replace(URI.parse('foo:a'), new types.Range(2, 1, 2, 1), 'bar'); + edit.replace(URI.parse('foo:b'), new types.Range(3, 1, 3, 1), 'bazz'); + + const all = edit.allEntries(); + assert.equal(all.length, 3); + + function isFileChange(thing: [URI, types.TextEdit[]] | [URI, URI]): thing is [URI, URI] { + const [f, s] = thing; + return URI.isUri(f) && URI.isUri(s); + } + + function isTextChange(thing: [URI, types.TextEdit[]] | [URI, URI]): thing is [URI, types.TextEdit[]] { + const [f, s] = thing; + return URI.isUri(f) && Array.isArray(s); + } + + const [first, second, third] = all; + assert.equal(first[0].toString(), 'foo:a'); + assert.ok(!isFileChange(first)); + assert.ok(isTextChange(first) && first[1].length === 2); + + assert.equal(second[0].toString(), 'foo:a'); + assert.ok(isFileChange(second)); + + assert.equal(third[0].toString(), 'foo:b'); + assert.ok(!isFileChange(third)); + assert.ok(isTextChange(third) && third[1].length === 1); + }); + test('DocumentLink', function () { assert.throws(() => new types.DocumentLink(null, null)); assert.throws(() => new types.DocumentLink(new types.Range(1, 1, 1, 1), null)); diff --git a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts index 75f5cb5effe..8a56c49a9e7 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts @@ -12,9 +12,21 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { TestRPCProtocol } from './testRPCProtocol'; import { normalize } from 'vs/base/common/paths'; import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; suite('ExtHostWorkspace', function () { + const extensionDescriptor: IExtensionDescription = { + id: 'nullExtensionDescription', + name: 'ext', + publisher: 'vscode', + enableProposedApi: false, + engines: undefined, + extensionFolderPath: undefined, + isBuiltin: false, + version: undefined + }; + function assertAsRelativePath(workspace: ExtHostWorkspace, input: string, expected: string, includeWorkspace?: boolean) { const actual = workspace.getRelativePath(input, includeWorkspace); if (actual === expected) { @@ -159,57 +171,370 @@ suite('ExtHostWorkspace', function () { assert.equal(folder.name, 'Two'); }); - test('Multiroot change event should have a delta, #29641', function () { + test('Multiroot change event should have a delta, #29641', function (done) { let ws = new ExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }); + let finished = false; + const finish = (error?) => { + if (!finished) { + finished = true; + done(error); + } + }; + let sub = ws.onDidChangeWorkspace(e => { - assert.deepEqual(e.added, []); - assert.deepEqual(e.removed, []); + try { + assert.deepEqual(e.added, []); + assert.deepEqual(e.removed, []); + } catch (error) { + finish(error); + } }); ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { - assert.deepEqual(e.removed, []); - assert.equal(e.added.length, 1); - assert.equal(e.added[0].uri.toString(), 'foo:bar'); + try { + assert.deepEqual(e.removed, []); + assert.equal(e.added.length, 1); + assert.equal(e.added[0].uri.toString(), 'foo:bar'); + } catch (error) { + finish(error); + } }); ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { - assert.deepEqual(e.removed, []); - assert.equal(e.added.length, 1); - assert.equal(e.added[0].uri.toString(), 'foo:bar2'); + try { + assert.deepEqual(e.removed, []); + assert.equal(e.added.length, 1); + assert.equal(e.added[0].uri.toString(), 'foo:bar2'); + } catch (error) { + finish(error); + } }); ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar2'), 1)] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { - assert.equal(e.removed.length, 2); - assert.equal(e.removed[0].uri.toString(), 'foo:bar'); - assert.equal(e.removed[1].uri.toString(), 'foo:bar2'); + try { + assert.equal(e.removed.length, 2); + assert.equal(e.removed[0].uri.toString(), 'foo:bar'); + assert.equal(e.removed[1].uri.toString(), 'foo:bar2'); - assert.equal(e.added.length, 1); - assert.equal(e.added[0].uri.toString(), 'foo:bar3'); + assert.equal(e.added.length, 1); + assert.equal(e.added[0].uri.toString(), 'foo:bar3'); + } catch (error) { + finish(error); + } }); ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0)] }); sub.dispose(); - + finish(); }); - test('Multiroot change event is immutable', function () { + test('Multiroot change keeps existing workspaces live', function () { + let ws = new ExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }); + + let firstFolder = ws.getWorkspaceFolders()[0]; + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar2'), 0), aWorkspaceFolderData(URI.parse('foo:bar'), 1, 'renamed')] }); + + assert.equal(ws.getWorkspaceFolders()[1], firstFolder); + assert.equal(firstFolder.index, 1); + assert.equal(firstFolder.name, 'renamed'); + + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar2'), 1), aWorkspaceFolderData(URI.parse('foo:bar'), 2)] }); + assert.equal(ws.getWorkspaceFolders()[2], firstFolder); + assert.equal(firstFolder.index, 2); + + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0)] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar'), 1)] }); + + assert.notEqual(firstFolder, ws.workspace.folders[0]); + }); + + test('updateWorkspaceFolders - invalid arguments', function () { + let ws = new ExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }); + + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, null, null)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 0)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 1)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 1, 0)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, 0)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, -1)); + + ws = new ExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }); + + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 1, 1)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2)); + assert.equal(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 1, asUpdateWorkspaceFolderData(URI.parse('foo:bar')))); + }); + + test('updateWorkspaceFolders - valid arguments', function (done) { + let finished = false; + const finish = (error?) => { + if (!finished) { + finished = true; + done(error); + } + }; + + const protocol = { + getProxy: () => { return undefined; }, + set: undefined, + assertRegistered: undefined + }; + + const ws = new ExtHostWorkspace(protocol, { id: 'foo', name: 'Test', folders: [] }); + + // + // Add one folder + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar')))); + assert.equal(1, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar').toString()); + + const firstAddedFolder = ws.getWorkspaceFolders()[0]; + + let gotEvent = false; + let sub = ws.onDidChangeWorkspace(e => { + try { + assert.deepEqual(e.removed, []); + assert.equal(e.added.length, 1); + assert.equal(e.added[0].uri.toString(), 'foo:bar'); + assert.equal(e.added[0], firstAddedFolder); // verify object is still live + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], firstAddedFolder); // verify object is still live + + // + // Add two more folders + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 1, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar1')), asUpdateWorkspaceFolderData(URI.parse('foo:bar2')))); + assert.equal(3, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar1').toString()); + assert.equal(ws.workspace.folders[2].uri.toString(), URI.parse('foo:bar2').toString()); + + const secondAddedFolder = ws.getWorkspaceFolders()[1]; + const thirdAddedFolder = ws.getWorkspaceFolders()[2]; + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.deepEqual(e.removed, []); + assert.equal(e.added.length, 2); + assert.equal(e.added[0].uri.toString(), 'foo:bar1'); + assert.equal(e.added[1].uri.toString(), 'foo:bar2'); + assert.equal(e.added[0], secondAddedFolder); + assert.equal(e.added[1], thirdAddedFolder); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar1'), 1), aWorkspaceFolderData(URI.parse('foo:bar2'), 2)] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], firstAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], secondAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[2], thirdAddedFolder); // verify object is still live + + // + // Remove one folder + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 2, 1)); + assert.equal(2, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar1').toString()); + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.deepEqual(e.added, []); + assert.equal(e.removed.length, 1); + assert.equal(e.removed[0], thirdAddedFolder); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar1'), 1)] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], firstAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], secondAddedFolder); // verify object is still live + + // + // Rename folder + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar'), 'renamed 1'), asUpdateWorkspaceFolderData(URI.parse('foo:bar1'), 'renamed 2'))); + assert.equal(2, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar1').toString()); + assert.equal(ws.workspace.folders[0].name, 'renamed 1'); + assert.equal(ws.workspace.folders[1].name, 'renamed 2'); + assert.equal(ws.getWorkspaceFolders()[0].name, 'renamed 1'); + assert.equal(ws.getWorkspaceFolders()[1].name, 'renamed 2'); + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.deepEqual(e.added, []); + assert.equal(e.removed.length, []); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0, 'renamed 1'), aWorkspaceFolderData(URI.parse('foo:bar1'), 1, 'renamed 2')] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], firstAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], secondAddedFolder); // verify object is still live + assert.equal(ws.workspace.folders[0].name, 'renamed 1'); + assert.equal(ws.workspace.folders[1].name, 'renamed 2'); + assert.equal(ws.getWorkspaceFolders()[0].name, 'renamed 1'); + assert.equal(ws.getWorkspaceFolders()[1].name, 'renamed 2'); + + // + // Add and remove folders + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar3')), asUpdateWorkspaceFolderData(URI.parse('foo:bar4')))); + assert.equal(2, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar3').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar4').toString()); + + const fourthAddedFolder = ws.getWorkspaceFolders()[0]; + const fifthAddedFolder = ws.getWorkspaceFolders()[1]; + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.equal(e.added.length, 2); + assert.equal(e.added[0], fourthAddedFolder); + assert.equal(e.added[1], fifthAddedFolder); + assert.equal(e.removed.length, 2); + assert.equal(e.removed[0], firstAddedFolder); + assert.equal(e.removed[1], secondAddedFolder); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar4'), 1)] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], fourthAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], fifthAddedFolder); // verify object is still live + + // + // Swap folders + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar4')), asUpdateWorkspaceFolderData(URI.parse('foo:bar3')))); + assert.equal(2, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar4').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar3').toString()); + + assert.equal(ws.getWorkspaceFolders()[0], fifthAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], fourthAddedFolder); // verify object is still live + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.equal(e.added.length, 0); + assert.equal(e.removed.length, 0); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar4'), 0), aWorkspaceFolderData(URI.parse('foo:bar3'), 1)] }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + assert.equal(ws.getWorkspaceFolders()[0], fifthAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], fourthAddedFolder); // verify object is still live + assert.equal(fifthAddedFolder.index, 0); + assert.equal(fourthAddedFolder.index, 1); + + // + // Add one folder after the other without waiting for confirmation (not supported currently) + // + + assert.equal(true, ws.updateWorkspaceFolders(extensionDescriptor, 2, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar5')))); + + assert.equal(3, ws.workspace.folders.length); + assert.equal(ws.workspace.folders[0].uri.toString(), URI.parse('foo:bar4').toString()); + assert.equal(ws.workspace.folders[1].uri.toString(), URI.parse('foo:bar3').toString()); + assert.equal(ws.workspace.folders[2].uri.toString(), URI.parse('foo:bar5').toString()); + + const sixthAddedFolder = ws.getWorkspaceFolders()[2]; + + gotEvent = false; + sub = ws.onDidChangeWorkspace(e => { + try { + assert.equal(e.added.length, 1); + assert.equal(e.added[0], sixthAddedFolder); + gotEvent = true; + } catch (error) { + finish(error); + } + }); + ws.$acceptWorkspaceData({ + id: 'foo', name: 'Test', folders: [ + aWorkspaceFolderData(URI.parse('foo:bar4'), 0), + aWorkspaceFolderData(URI.parse('foo:bar3'), 1), + aWorkspaceFolderData(URI.parse('foo:bar5'), 2) + ] + }); // simulate acknowledgement from main side + assert.equal(gotEvent, true); + sub.dispose(); + + assert.equal(ws.getWorkspaceFolders()[0], fifthAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[1], fourthAddedFolder); // verify object is still live + assert.equal(ws.getWorkspaceFolders()[2], sixthAddedFolder); // verify object is still live + + finish(); + }); + + test('Multiroot change event is immutable', function (done) { + let finished = false; + const finish = (error?) => { + if (!finished) { + finished = true; + done(error); + } + }; + let ws = new ExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }); let sub = ws.onDidChangeWorkspace(e => { - assert.throws(() => { - (e).added = []; - }); - assert.throws(() => { - (e.added)[0] = null; - }); + try { + assert.throws(() => { + (e).added = []; + }); + assert.throws(() => { + (e.added)[0] = null; + }); + } catch (error) { + finish(error); + } }); ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] }); sub.dispose(); + finish(); }); test('`vscode.workspace.getWorkspaceFolder(file)` don\'t return workspace folder when file open from command line. #36221', function () { @@ -230,4 +555,8 @@ suite('ExtHostWorkspace', function () { name: name || basename(uri.path) }; } + + function asUpdateWorkspaceFolderData(uri: URI, name?: string): { uri: URI, name?: string } { + return { uri, name }; + } }); diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts index 73887be8ea3..03ad3ac7926 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadEditors.test.ts @@ -13,7 +13,7 @@ import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { TestCodeEditorService } from 'vs/editor/test/browser/testCodeEditorService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { ExtHostDocumentsAndEditorsShape, IWorkspaceResourceEdit, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/node/extHost.protocol'; +import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape } from 'vs/workbench/api/node/extHost.protocol'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import Event from 'vs/base/common/event'; @@ -23,6 +23,10 @@ import { Range } from 'vs/editor/common/core/range'; import { Position } from 'vs/editor/common/core/position'; import { IModelService } from 'vs/editor/common/services/modelService'; import { EditOperation } from 'vs/editor/common/core/editOperation'; +import { TestFileService } from 'vs/workbench/test/workbenchTestServices'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { IFileStat } from 'vs/platform/files/common/files'; +import { ResourceTextEdit } from 'vs/editor/common/modes'; suite('MainThreadEditors', () => { @@ -31,10 +35,34 @@ suite('MainThreadEditors', () => { let modelService: IModelService; let editors: MainThreadEditors; + const movedResources = new Map(); + const createdResources = new Set(); + const deletedResources = new Set(); + setup(() => { const configService = new TestConfigurationService(); modelService = new ModelServiceImpl(null, configService); const codeEditorService = new TestCodeEditorService(); + + movedResources.clear(); + createdResources.clear(); + deletedResources.clear(); + + const fileService = new class extends TestFileService { + async moveFile(from, target): TPromise { + movedResources.set(from, target); + return createMockFileStat(target); + } + async createFile(uri): TPromise { + createdResources.add(uri); + return createMockFileStat(uri); + } + async del(uri): TPromise { + deletedResources.add(uri); + } + }; + + const textFileService = new class extends mock() { isDirty() { return false; } models = { @@ -69,7 +97,7 @@ suite('MainThreadEditors', () => { workbenchEditorService, codeEditorService, null, - null, + fileService, null, null, editorGroupService, @@ -82,7 +110,7 @@ suite('MainThreadEditors', () => { workbenchEditorService, editorGroupService, null, - null, + fileService, modelService ); }); @@ -91,11 +119,11 @@ suite('MainThreadEditors', () => { let model = modelService.createModel('something', null, resource); - let workspaceResourceEdit: IWorkspaceResourceEdit = { + let workspaceResourceEdit: ResourceTextEdit = { resource: resource, modelVersionId: model.getVersionId(), edits: [{ - newText: 'asdfg', + text: 'asdfg', range: new Range(1, 1, 1, 1) }] }; @@ -103,8 +131,35 @@ suite('MainThreadEditors', () => { // Act as if the user edited the model model.applyEdits([EditOperation.insert(new Position(0, 0), 'something')]); - return editors.$tryApplyWorkspaceEdit([workspaceResourceEdit]).then((result) => { + return editors.$tryApplyWorkspaceEdit({ edits: [workspaceResourceEdit] }).then((result) => { assert.equal(result, false); }); }); + + test(`applyWorkspaceEdit with only resource edit`, () => { + return editors.$tryApplyWorkspaceEdit({ + edits: [ + { oldUri: resource, newUri: resource }, + { oldUri: undefined, newUri: resource }, + { oldUri: resource, newUri: undefined } + ] + }).then((result) => { + assert.equal(result, true); + assert.equal(movedResources.get(resource), resource); + assert.equal(createdResources.has(resource), true); + assert.equal(deletedResources.has(resource), true); + }); + }); }); + + +function createMockFileStat(target: URI): IFileStat { + return { + etag: '', + isDirectory: false, + name: target.path, + mtime: 0, + resource: target + }; +} + diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts index d6f3681d331..d83503b679e 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadSaveParticipant.test.ts @@ -17,6 +17,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { ITextFileService, SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; +import { snapshotToString } from 'vs/platform/files/common/files'; class ServiceAccessor { constructor( @ITextFileService public textFileService: TestTextFileService, @IModelService public modelService: IModelService) { @@ -51,25 +52,25 @@ suite('MainThreadSaveParticipant', function () { let lineContent = ''; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), lineContent); + assert.equal(snapshotToString(model.createSnapshot()), lineContent); // No new line if last line already empty lineContent = `Hello New Line${model.textEditorModel.getEOL()}`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), lineContent); + assert.equal(snapshotToString(model.createSnapshot()), lineContent); // New empty line added (single line) lineContent = 'Hello New Line'; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), `${lineContent}${model.textEditorModel.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()), `${lineContent}${model.textEditorModel.getEOL()}`); // New empty line added (multi line) lineContent = `Hello New Line${model.textEditorModel.getEOL()}Hello New Line${model.textEditorModel.getEOL()}Hello New Line`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), `${lineContent}${model.textEditorModel.getEOL()}`); + assert.equal(snapshotToString(model.createSnapshot()), `${lineContent}${model.textEditorModel.getEOL()}`); done(); }); @@ -91,25 +92,25 @@ suite('MainThreadSaveParticipant', function () { let lineContent = `${textContent}`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), lineContent); + assert.equal(snapshotToString(model.createSnapshot()), lineContent); // No new line removal if last line is single new line lineContent = `${textContent}${eol}`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), lineContent); + assert.equal(snapshotToString(model.createSnapshot()), lineContent); // Remove new line (single line with two new lines) lineContent = `${textContent}${eol}${eol}`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), `${textContent}${eol}`); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}`); // Remove new lines (multiple lines with multiple new lines) lineContent = `${textContent}${eol}${textContent}${eol}${eol}${eol}`; model.textEditorModel.setValue(lineContent); participant.participate(model, { reason: SaveReason.EXPLICIT }); - assert.equal(model.getValue(), `${textContent}${eol}${textContent}${eol}`); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}${eol}${textContent}${eol}`); done(); }); @@ -134,11 +135,11 @@ suite('MainThreadSaveParticipant', function () { model.textEditorModel.pushEditOperations([new Selection(1, 14, 1, 14)], textEdits, () => { return [new Selection(1, 15, 1, 15)]; }); // undo model.textEditorModel.undo(); - assert.equal(model.getValue(), `${textContent}`); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}`); // trim final new lines should not mess the undo stack participant.participate(model, { reason: SaveReason.EXPLICIT }); model.textEditorModel.redo(); - assert.equal(model.getValue(), `${textContent}.`); + assert.equal(snapshotToString(model.createSnapshot()), `${textContent}.`); done(); }); }); diff --git a/src/vs/workbench/test/electron-browser/api/testRPCProtocol.ts b/src/vs/workbench/test/electron-browser/api/testRPCProtocol.ts index f2effd9e861..12a3f397b04 100644 --- a/src/vs/workbench/test/electron-browser/api/testRPCProtocol.ts +++ b/src/vs/workbench/test/electron-browser/api/testRPCProtocol.ts @@ -8,7 +8,6 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { CharCode } from 'vs/base/common/charCode'; -import * as marshalling from 'vs/base/common/marshalling'; export function SingleProxyRPCProtocol(thing: any): IRPCProtocol { return { @@ -70,17 +69,17 @@ export class TestRPCProtocol implements IRPCProtocol { public getProxy(identifier: ProxyIdentifier): T { if (!this._proxies[identifier.id]) { - this._proxies[identifier.id] = this._createProxy(identifier.id, identifier.isFancy); + this._proxies[identifier.id] = this._createProxy(identifier.id); } return this._proxies[identifier.id]; } - private _createProxy(proxyId: string, isFancy: boolean): T { + private _createProxy(proxyId: string): T { let handler = { get: (target, name: string) => { if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) { target[name] = (...myArgs: any[]) => { - return this._remoteCall(proxyId, name, myArgs, isFancy); + return this._remoteCall(proxyId, name, myArgs); }; } return target[name]; @@ -94,7 +93,7 @@ export class TestRPCProtocol implements IRPCProtocol { return value; } - protected _remoteCall(proxyId: string, path: string, args: any[], isFancy: boolean): TPromise { + protected _remoteCall(proxyId: string, path: string, args: any[]): TPromise { this._callCount++; return new TPromise((c) => { @@ -102,7 +101,7 @@ export class TestRPCProtocol implements IRPCProtocol { }).then(() => { const instance = this._locals[proxyId]; // pretend the args went over the wire... (invoke .toJSON on objects...) - const wireArgs = simulateWireTransfer(args, isFancy); + const wireArgs = simulateWireTransfer(args); let p: Thenable; try { let result = (instance[path]).apply(instance, wireArgs); @@ -114,7 +113,7 @@ export class TestRPCProtocol implements IRPCProtocol { return p.then(result => { this._callCount--; // pretend the result went over the wire... (invoke .toJSON on objects...) - const wireResult = simulateWireTransfer(result, isFancy); + const wireResult = simulateWireTransfer(result); return wireResult; }, err => { this._callCount--; @@ -128,13 +127,9 @@ export class TestRPCProtocol implements IRPCProtocol { } } -function simulateWireTransfer(obj: T, isFancy: boolean): T { +function simulateWireTransfer(obj: T): T { if (!obj) { return obj; } - return ( - isFancy - ? marshalling.parse(marshalling.stringify(obj)) - : JSON.parse(JSON.stringify(obj)) - ); + return JSON.parse(JSON.stringify(obj)); } diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index e45bc1a4b10..0b7031c62fa 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -33,7 +33,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { IEditorGroupService, GroupArrangement, GroupOrientation, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService'; -import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent, ICreateFileOptions } from 'vs/platform/files/common/files'; +import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent, ICreateFileOptions, ITextSnapshot } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; @@ -180,9 +180,10 @@ export class TestTextFileService extends TextFileService { @IBackupFileService backupFileService: IBackupFileService, @IWindowsService windowsService: IWindowsService, @IHistoryService historyService: IHistoryService, - @IContextKeyService contextKeyService: IContextKeyService + @IContextKeyService contextKeyService: IContextKeyService, + @IModelService modelService: IModelService ) { - super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, messageService, TestEnvironmentService, backupFileService, windowsService, historyService, contextKeyService); + super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, messageService, TestEnvironmentService, backupFileService, windowsService, historyService, contextKeyService, modelService); } public setPromptPath(path: string): void { @@ -755,7 +756,7 @@ export class TestFileService implements IFileService { }); } - updateContent(resource: URI, value: string, options?: IUpdateContentOptions): TPromise { + updateContent(resource: URI, value: string | ITextSnapshot, options?: IUpdateContentOptions): TPromise { return TPromise.timeout(1).then(() => { return { resource, @@ -856,7 +857,7 @@ export class TestBackupFileService implements IBackupFileService { return null; } - public backupResource(resource: URI, content: string): TPromise { + public backupResource(resource: URI, content: ITextSnapshot): TPromise { return TPromise.as(void 0); } @@ -871,6 +872,10 @@ export class TestBackupFileService implements IBackupFileService { return textBuffer.getValueInRange(range, EndOfLinePreference.TextDefined); } + public resolveBackupContent(backup: URI): TPromise { + return TPromise.as(null); + } + public discardResourceBackup(resource: URI): TPromise { return TPromise.as(void 0); } diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index cc5fa97e31a..2966cea4559 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -21,6 +21,9 @@ import 'vs/platform/actions/electron-browser/menusExtensionPoint'; // Views import 'vs/workbench/api/browser/viewsExtensionPoint'; +// Localizations +import 'vs/workbench/api/browser/localizationsExtensionPoint'; + // Workbench import 'vs/workbench/browser/actions/toggleActivityBarVisibility'; import 'vs/workbench/browser/actions/toggleStatusbarVisibility'; diff --git a/test/grid.html b/test/grid.html new file mode 100644 index 00000000000..a455621fea8 --- /dev/null +++ b/test/grid.html @@ -0,0 +1,59 @@ + + + + + + + Grid Example + + + + + + + + + + + \ No newline at end of file diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 3218911858d..7e924b95b62 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -5,54 +5,19 @@ import * as assert from 'assert'; import * as http from 'http'; -import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication, Quality } from '../../spectron/application'; +import { SpectronApplication } from '../../spectron/application'; export function setup() { describe('Debug', () => { - let skip = false; - before(async function () { const app = this.app as SpectronApplication; - - if (app.quality === Quality.Dev) { - const extensionsPath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions'); - - const debugPath = path.join(extensionsPath, 'vscode-node-debug'); - const debugExists = fs.existsSync(debugPath); - - const debug2Path = path.join(extensionsPath, 'vscode-node-debug2'); - const debug2Exists = fs.existsSync(debug2Path); - - if (!debugExists) { - console.warn(`Skipping debug tests because vscode-node-debug extension was not found in ${extensionsPath}`); - skip = true; - return; - } - - if (!debug2Exists) { - console.warn(`Skipping debug tests because vscode-node-debug2 extension was not found in ${extensionsPath}`); - skip = true; - return; - } - - await new Promise((c, e) => fs.symlink(debugPath, path.join(app.extensionsPath, 'vscode-node-debug'), err => err ? e(err) : c())); - await new Promise((c, e) => fs.symlink(debug2Path, path.join(app.extensionsPath, 'vscode-node-debug2'), err => err ? e(err) : c())); - await app.reload(); - } - - this.app.suiteName = 'Debug'; + app.suiteName = 'Debug'; }); it('configure launch json', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.debug.openDebugViewlet(); @@ -78,11 +43,6 @@ export function setup() { }); it('breakpoints', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.quickopen.openFile('index.js'); @@ -92,11 +52,6 @@ export function setup() { let port: number; it('start debugging', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; port = await app.workbench.debug.startDebugging(); @@ -112,11 +67,6 @@ export function setup() { }); it('focus stack frames and variables', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables'); @@ -132,11 +82,6 @@ export function setup() { }); it('stepOver, stepIn, stepOut', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.debug.stepIn(); @@ -154,11 +99,6 @@ export function setup() { }); it('continue', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.debug.continue(); @@ -174,22 +114,12 @@ export function setup() { }); it('debug console', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.debug.waitForReplCommand('2 + 2', r => r === '4'); }); it('stop debugging', async function () { - if (skip) { - this.skip(); - return; - } - const app = this.app as SpectronApplication; await app.workbench.debug.stopDebugging(); diff --git a/test/smoke/src/areas/git/git.test.ts b/test/smoke/src/areas/git/git.test.ts index 19f1c3e51d2..7ce6407053f 100644 --- a/test/smoke/src/areas/git/git.test.ts +++ b/test/smoke/src/areas/git/git.test.ts @@ -12,8 +12,9 @@ const SYNC_STATUSBAR = 'div[id="workbench.parts.statusbar"] .statusbar-entry a[t export function setup() { describe('Git', () => { - before(function () { - this.app.suiteName = 'Git'; + before(async function () { + const app = this.app as SpectronApplication; + app.suiteName = 'Git'; }); it('reflects working tree changes', async function () { diff --git a/test/smoke/src/areas/git/scm.ts b/test/smoke/src/areas/git/scm.ts index ed33e320710..824cfc3d144 100644 --- a/test/smoke/src/areas/git/scm.ts +++ b/test/smoke/src/areas/git/scm.ts @@ -13,7 +13,7 @@ const SCM_RESOURCE = `${VIEWLET} .monaco-list-row > .resource`; const SCM_RESOURCE_GROUP = `${VIEWLET} .monaco-list-row > .resource-group`; const REFRESH_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Refresh"]`; const COMMIT_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Commit"]`; -const SCM_RESOURCE_CLICK = name => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"]`; +const SCM_RESOURCE_CLICK = name => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .label-name`; const SCM_RESOURCE_GROUP_COMMAND_CLICK = name => `${SCM_RESOURCE_GROUP} .actions .action-label[title="${name}"]`; export interface Change { @@ -49,7 +49,7 @@ export class SCM extends Viewlet { const result = await this.spectron.webclient.selectorExecute(SCM_RESOURCE, div => (Array.isArray(div) ? div : [div]).map(element => { const name = element.querySelector('.label-name') as HTMLElement; - const icon = element.querySelector('.decoration-icon') as HTMLElement; + const type = element.getAttribute('data-tooltip') || ''; const actionElementList = element.querySelectorAll('.actions .action-label'); const actionElements: any[] = []; @@ -60,7 +60,7 @@ export class SCM extends Viewlet { return { name: name.textContent, - type: (icon.title || ''), + type, element, actionElements }; diff --git a/test/smoke/src/areas/workbench/workbench.ts b/test/smoke/src/areas/workbench/workbench.ts index 08a3204d1eb..c2711f449d3 100644 --- a/test/smoke/src/areas/workbench/workbench.ts +++ b/test/smoke/src/areas/workbench/workbench.ts @@ -51,14 +51,8 @@ export class Workbench { } public async saveOpenedFile(): Promise { - try { - await this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty'); - } catch (e) { - // ignore if there is no dirty file - return Promise.resolve(); - } - await this.spectron.runCommand('workbench.action.files.save'); - return this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty', element => !element); + await this.spectron.client.waitForElement('.tabs-container div.tab.active.dirty'); + await this.spectron.workbench.quickopen.runCommand('File: Save'); } public async selectTab(tabName: string, untitled: boolean = false): Promise { diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 1d922106600..019ee28cff6 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -220,7 +220,7 @@ console.warn = function suppressWebdriverWarnings(message) { }; function createApp(quality: Quality): SpectronApplication | null { - const path = quality === Quality.Insiders ? electronPath : stablePath; + const path = quality === Quality.Stable ? stablePath : electronPath; if (!path) { return null; diff --git a/tslint.json b/tslint.json index 23e3b8f5899..24a7ac86d1b 100644 --- a/tslint.json +++ b/tslint.json @@ -398,6 +398,18 @@ "*" // node modules ] }, + { + "target": "**/vs/code/electron-browser/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "vs/nls", + "**/vs/base/**", + "**/vs/platform/**", + "**/vs/code/**", + "*" // node modules + ] + }, { "target": "**/vs/code/**", "restrictions": [ diff --git a/yarn.lock b/yarn.lock index 625afd3a6d8..ff3b7020a8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -513,10 +513,14 @@ camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" -camelcase@^2.0.0, camelcase@^2.0.1: +camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -630,12 +634,12 @@ cliui@^2.1.0: right-align "^0.1.1" wordwrap "0.0.2" -cliui@^3.0.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" +cliui@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + string-width "^2.1.1" + strip-ansi "^4.0.0" wrap-ansi "^2.0.0" clone-buffer@^1.0.0: @@ -840,6 +844,14 @@ cross-spawn@^4.0.0: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@0.2.x: version "0.2.2" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-0.2.2.tgz#ed91ff1f17ad13d3748288594f8a48a0d26f325c" @@ -1452,7 +1464,7 @@ event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" -event-stream@^3.1.7, event-stream@^3.3.1, event-stream@^3.3.2, event-stream@~3.3.4: +event-stream@^3.1.7, event-stream@^3.3.1, event-stream@^3.3.4, event-stream@~3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" dependencies: @@ -1468,6 +1480,18 @@ eventemitter2@~0.4.13: version "0.4.14" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -1673,6 +1697,12 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + findup-sync@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12" @@ -1867,6 +1897,10 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + get-stdin@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-3.0.2.tgz#c1ced24b9039b38ded85bdf161e57713b6dd4abe" @@ -1875,6 +1909,10 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getmac@1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/getmac/-/getmac-1.0.7.tgz#94460f9778698d2e159a03da6c165689f22cdd67" @@ -1990,17 +2028,7 @@ glob@^4.3.1, glob@~4.5.x: minimatch "^2.0.1" once "^1.3.0" -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2415,7 +2443,7 @@ gulp-util@^2.2.14, gulp-util@~2.2.14: through2 "^0.5.0" vinyl "^0.2.1" -gulp-util@^3.0.0, gulp-util@^3.0.1, gulp-util@^3.0.6, gulp-util@^3.0.7, gulp-util@~3.0.0, gulp-util@~3.0.8: +gulp-util@^3.0.0, gulp-util@^3.0.1, gulp-util@^3.0.6, gulp-util@^3.0.7, gulp-util@^3.0.8, gulp-util@~3.0.0, gulp-util@~3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -2662,7 +2690,7 @@ husky@^0.13.1: is-ci "^1.0.9" normalize-path "^1.0.0" -iconv-lite@0.4.19, iconv-lite@^0.4.15: +iconv-lite@0.4.19, iconv-lite@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -3226,6 +3254,13 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" @@ -3546,6 +3581,12 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + meow@^3.1.0, meow@^3.3.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -3611,6 +3652,10 @@ mime@1.4.1, mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + minimatch@0.2.12: version "0.2.12" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.12.tgz#ea82a012ac662c7ddfaa144f1c147e6946f5dafb" @@ -3836,6 +3881,12 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + nsfw@1.0.16: version "1.0.16" resolved "https://registry.yarnpkg.com/nsfw/-/nsfw-1.0.16.tgz#78ba3e7f513b53d160c221b9018e0baf108614cc" @@ -4014,11 +4065,13 @@ os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" dependencies: + execa "^0.7.0" lcid "^1.0.0" + mem "^1.1.0" os-tmpdir@^1.0.0, os-tmpdir@~1.0.1: version "1.0.2" @@ -4031,6 +4084,26 @@ osenv@^0.1.3: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + parse-filepath@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" @@ -4100,6 +4173,10 @@ path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -4794,6 +4871,14 @@ request@~2.74.0: tough-cookie "~2.3.0" tunnel-agent "~0.4.1" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -4928,6 +5013,10 @@ serve-static@1.13.1: parseurl "~1.3.2" send "0.16.1" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -4940,6 +5029,16 @@ setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + shelljs@^0.7.5: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" @@ -5018,7 +5117,7 @@ source-map@0.4.x, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@0.X, source-map@>=0.5.6, source-map@~0.6.1: +source-map@0.X, source-map@>=0.5.6, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -5042,9 +5141,9 @@ sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" -spdlog@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/spdlog/-/spdlog-0.5.0.tgz#5ec92c34e59f29328f4e19dfab17a1ba51cc0573" +spdlog@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/spdlog/-/spdlog-0.6.0.tgz#20632ed4f1558ffa46e8a5827a5e97c61e0fa9ed" dependencies: bindings "^1.3.0" mkdirp "^0.5.1" @@ -5136,7 +5235,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0: +string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -5199,6 +5298,10 @@ strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -5462,10 +5565,14 @@ typescript-formatter@4.0.1: editorconfig "^0.13.2" glob-expand "^0.2.1" -typescript@2.6.1, typescript@^2.0.3: +typescript@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631" +typescript@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" + uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" @@ -5682,7 +5789,7 @@ vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: dependencies: source-map "^0.5.1" -vinyl@1.X, vinyl@^1.0.0, vinyl@^1.1.1: +vinyl@1.X, vinyl@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" dependencies: @@ -5711,7 +5818,7 @@ vinyl@^0.5.0, vinyl@^0.5.1: clone-stats "^0.0.1" replace-ext "0.0.1" -vinyl@^2.0.0: +vinyl@^2.0.0, vinyl@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" dependencies: @@ -5781,21 +5888,21 @@ vscode-fsevents@0.3.8: dependencies: nan "^2.3.0" -vscode-nls-dev@^2.0.1: - version "2.1.5" - resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-2.1.5.tgz#19faa3b18a7f302201039a4c967bbd22fa12844d" +vscode-nls-dev@^3.0.5: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vscode-nls-dev/-/vscode-nls-dev-3.0.3.tgz#9728541449576559ae7bf2cff4869edaeca7e2e1" dependencies: - clone "^1.0.2" - event-stream "^3.3.2" - glob "^6.0.4" - gulp-util "^3.0.7" - iconv-lite "^0.4.15" + clone "^2.1.1" + event-stream "^3.3.4" + glob "^7.1.2" + gulp-util "^3.0.8" + iconv-lite "^0.4.19" is "^3.2.1" - source-map "^0.5.3" - typescript "^2.0.3" - vinyl "^1.1.1" - xml2js "^0.4.17" - yargs "^3.32.0" + source-map "^0.6.1" + typescript "^2.6.2" + vinyl "^2.1.0" + xml2js "^0.4.19" + yargs "^10.1.1" vscode-ripgrep@^0.7.1-patch.0: version "0.7.1-patch.0" @@ -5808,9 +5915,9 @@ vscode-textmate@^3.2.0: fast-plist "^0.1.2" oniguruma "^6.0.1" -vscode-xterm@3.1.0-beta2: - version "3.1.0-beta2" - resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.1.0-beta2.tgz#74adae19283738fab15f0ef145797f2eff5cc608" +vscode-xterm@3.1.0-beta11: + version "3.1.0-beta11" + resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.1.0-beta11.tgz#a6cfa957a6cac3bcc574da0433a2aa58654f2d8f" vso-node-api@^6.1.2-preview: version "6.1.2-preview" @@ -5825,6 +5932,10 @@ whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + which@^1.1.1, which@^1.2.12, which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" @@ -5839,10 +5950,6 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - windows-foreground-love@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/windows-foreground-love/-/windows-foreground-love-0.1.0.tgz#948e4beac0733cd58624710cc09432b7e8bf3521" @@ -5907,7 +6014,7 @@ xml2js@0.2.7: dependencies: sax "0.5.2" -xml2js@^0.4.17: +xml2js@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" dependencies: @@ -5950,7 +6057,7 @@ xtend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" -y18n@^3.2.0: +y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" @@ -5958,17 +6065,28 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" -yargs@^3.32.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" + camelcase "^4.1.0" + +yargs@^10.1.1: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + dependencies: + cliui "^4.0.0" decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" yargs@~3.10.0: version "3.10.0"