diff --git a/.github/classifier.yml b/.github/classifier.yml index a7bcb40c96f..eba4910f445 100644 --- a/.github/classifier.yml +++ b/.github/classifier.yml @@ -20,7 +20,10 @@ }, diff-editor: [], dropdown: [], - editor: [], + editor: { + assignees: [], + assignLabel: false + }, editor-1000-limit: [], editor-autoclosing: [], editor-autoindent: [], diff --git a/.yarnrc b/.yarnrc index 40cb5766ccb..55749a8a0a7 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "2.0.9" +target "2.0.11" runtime "electron" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d8ba5500ae..46afac5dfe4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,12 +48,13 @@ Do not add your issue as a comment to an existing issue unless it's for the iden The more information you can provide, the more likely someone will be successful at reproducing the issue and finding a fix. +The built-in tool for reporting an issue, which you can access by using `Report Issue` in VS Code's Help menu, can help streamline this process by automatically providing the version of VS Code, all your installed extensions, and your system info. Additionally, the tool will search among existing issues to see if a similar issue already exists. + Please include the following with each issue: * Version of VS Code * List of extensions that you have installed. - * **Tip:** You can easily add the list of extensions by creating the issue using `Report Issues` from VS Code's Help menu * Reproducible steps (1... 2... 3...) that cause the issue diff --git a/OSSREADME.json b/OSSREADME.json index 98c9d0476b5..c59395867eb 100644 --- a/OSSREADME.json +++ b/OSSREADME.json @@ -51,7 +51,7 @@ }, { "name": "electron", - "version": "2.0.9", + "version": "2.0.11", "license": "MIT", "repositoryURL": "https://github.com/electron/electron", "isProd": true diff --git a/build/monaco/api.js b/build/monaco/api.js index d4502c97997..f411ab4a566 100644 --- a/build/monaco/api.js +++ b/build/monaco/api.js @@ -315,7 +315,6 @@ function generateDeclarationFile(out, inputFiles, recipe) { var resultTxt = result.join(endl); resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri'); resultTxt = resultTxt.replace(/\bEvent(); public constructor( private readonly extensionPreviewResourceProvider: MarkdownContributions, @@ -36,7 +36,6 @@ export class MarkdownEngine { private async getEngine(resource: vscode.Uri): Promise { if (!this.md) { const hljs = await import('highlight.js'); - const mdnh = await import('markdown-it-named-headers'); this.md = (await import('markdown-it'))({ html: true, highlight: (str: string, lang?: string) => { @@ -54,8 +53,6 @@ export class MarkdownEngine { } return `
${this.md!.utils.escapeHtml(str)}
`; } - }).use(mdnh, { - slugify: (header: string) => this.slugifier.fromHeading(header).value }); for (const plugin of this.extensionPreviewResourceProvider.markdownItPlugins) { @@ -71,6 +68,7 @@ export class MarkdownEngine { this.addLinkNormalizer(this.md); this.addLinkValidator(this.md); + this.addNamedHeaders(this.md); } const config = vscode.workspace.getConfiguration('markdown', resource); @@ -101,6 +99,8 @@ export class MarkdownEngine { } this.currentDocument = document; this.firstLine = offset; + this._slugCount = new Map(); + const engine = await this.getEngine(document); return engine.render(text); } @@ -108,6 +108,8 @@ export class MarkdownEngine { public async parse(document: vscode.Uri, source: string): Promise { const { text, offset } = this.stripFrontmatter(source); this.currentDocument = document; + this._slugCount = new Map(); + const engine = await this.getEngine(document); return engine.parse(text, {}).map(token => { @@ -219,4 +221,29 @@ export class MarkdownEngine { return validateLink(link) || link.indexOf('file:') === 0; }; } + + private addNamedHeaders(md: any): void { + const original = md.renderer.rules.heading_open; + md.renderer.rules.heading_open = (tokens: any, idx: number, options: any, env: any, self: any) => { + const title = tokens[idx + 1].children.reduce((acc: string, t: any) => acc + t.content, ''); + let slug = this.slugifier.fromHeading(title); + + if (this._slugCount.has(slug.value)) { + const count = this._slugCount.get(slug.value)!; + this._slugCount.set(slug.value, count + 1); + slug = this.slugifier.fromHeading(slug.value + '-' + (count + 1)); + } else { + this._slugCount.set(slug.value, 0); + } + + tokens[idx].attrs = tokens[idx].attrs || []; + tokens[idx].attrs.push(['id', slug.value]); + + if (original) { + return original(tokens, idx, options, env, self); + } else { + return self.renderToken(tokens, idx, options, env, self); + } + }; + } } \ No newline at end of file diff --git a/extensions/markdown-language-features/src/tableOfContentsProvider.ts b/extensions/markdown-language-features/src/tableOfContentsProvider.ts index 944fc750734..bbb30b7cea6 100644 --- a/extensions/markdown-language-features/src/tableOfContentsProvider.ts +++ b/extensions/markdown-language-features/src/tableOfContentsProvider.ts @@ -51,11 +51,23 @@ export class TableOfContentsProvider { const toc: TocEntry[] = []; const tokens = await this.engine.parse(document.uri, document.getText()); + const slugCount = new Map(); + for (const heading of tokens.filter(token => token.type === 'heading_open')) { const lineNumber = heading.map[0]; const line = document.lineAt(lineNumber); + + let slug = githubSlugifier.fromHeading(line.text); + if (slugCount.has(slug.value)) { + const count = slugCount.get(slug.value)!; + slugCount.set(slug.value, count + 1); + slug = githubSlugifier.fromHeading(slug.value + '-' + (count + 1)); + } else { + slugCount.set(slug.value, 0); + } + toc.push({ - slug: githubSlugifier.fromHeading(line.text), + slug, text: TableOfContentsProvider.getHeaderText(line.text), level: TableOfContentsProvider.getHeaderLevel(heading.markup), line: lineNumber, diff --git a/extensions/markdown-language-features/src/test/tableOfContentsProvider.test.ts b/extensions/markdown-language-features/src/test/tableOfContentsProvider.test.ts index ee103b294ca..91e12f278a5 100644 --- a/extensions/markdown-language-features/src/test/tableOfContentsProvider.test.ts +++ b/extensions/markdown-language-features/src/test/tableOfContentsProvider.test.ts @@ -106,4 +106,25 @@ suite('markdown.TableOfContentsProvider', () => { assert.strictEqual((await provider.lookup('Заголовок-header-3'))!.line, 4); assert.strictEqual((await provider.lookup('Заголовок'))!.line, 5); }); + + test('Lookup should support suffixes for repeated headers', async () => { + const doc = new InMemoryDocument(testFileName, `# a\n# a\n## a`); + const provider = new TableOfContentsProvider(createNewMarkdownEngine(), doc); + + { + const entry = await provider.lookup('a'); + assert.ok(entry); + assert.strictEqual(entry!.line, 0); + } + { + const entry = await provider.lookup('a-1'); + assert.ok(entry); + assert.strictEqual(entry!.line, 1); + } + { + const entry = await provider.lookup('a-2'); + assert.ok(entry); + assert.strictEqual(entry!.line, 2); + } + }); }); diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 2ee630f88b9..e95b79f5238 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -3895,13 +3895,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -markdown-it-named-headers@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/markdown-it-named-headers/-/markdown-it-named-headers-0.0.4.tgz#82efc28324240a6b1e77b9aae501771d5f351c1f" - integrity sha1-gu/CgyQkCmsed7mq5QF3HV81HB8= - dependencies: - string "^3.0.1" - markdown-it@^8.4.1: version "8.4.1" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44" @@ -5711,11 +5704,6 @@ string-width@^2.0.0, string-width@^2.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/string/-/string-3.3.1.tgz#8d2757ec1c0e6c526796fbb6b14036a4098398b7" - integrity sha1-jSdX7BwObFJnlvu2sUA2pAmDmLc= - string_decoder@^1.0.0, string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" diff --git a/extensions/package.json b/extensions/package.json index d75f31424f4..5d1eaf63e22 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "3.1.1" + "typescript": "3.1.2" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/php/snippets/php.snippets.json b/extensions/php/snippets/php.snippets.json index c8dc8405300..1f2a07bef20 100644 --- a/extensions/php/snippets/php.snippets.json +++ b/extensions/php/snippets/php.snippets.json @@ -254,8 +254,8 @@ "body": [ "try {", "\t${1://code...}", - "} catch (\\Exception \\$$e) {", - "\t${2://throw $$e;}", + "} catch (${2:\\Throwable} ${3:$$th}) {", + "\t${4://throw $$th;}", "}" ], "description": "Try catch block" diff --git a/extensions/typescript-language-features/src/features/rename.ts b/extensions/typescript-language-features/src/features/rename.ts index 3547b15d508..8d0ceeeff77 100644 --- a/extensions/typescript-language-features/src/features/rename.ts +++ b/extensions/typescript-language-features/src/features/rename.ts @@ -11,6 +11,13 @@ import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService'; import API from '../utils/api'; import * as typeConverters from '../utils/typeConverters'; +// TODO: Remove when we pick up TS 3.2 +declare module '../protocol' { + interface RenameTextSpan extends Proto.TextSpan { + readonly prefixText?: string; + readonly suffixText?: string; + } +} const localize = nls.loadMessageBundle(); @@ -102,8 +109,9 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { for (const spanGroup of locations) { const resource = this.client.toResource(spanGroup.file); if (resource) { - for (const textSpan of spanGroup.locs) { - edit.replace(resource, typeConverters.Range.fromTextSpan(textSpan), newName); + for (const textSpan of spanGroup.locs as Proto.RenameTextSpan[]) { + edit.replace(resource, typeConverters.Range.fromTextSpan(textSpan), + (textSpan.prefixText || '') + newName + (textSpan.suffixText || '')); } } } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index e4311f57343..d211db9565b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -43,7 +43,7 @@ suite('Webview tests', () => { }); test('webviews should not have scripts enabled by default', async () => { - const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { })); + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {})); const response = Promise.race([ getMesssage(webview), new Promise<{}>(resolve => setTimeout(() => resolve({ value: '🎉' }), 1000)) @@ -71,14 +71,14 @@ suite('Webview tests', () => { assert.strictEqual((await response).value, 'first'); } { - const firstResponse = getMesssage(webview); + const response = getMesssage(webview); webview.webview.html = createHtmlDocumentWithBody(/*html*/` `); - assert.strictEqual((await firstResponse).value, 'second'); + assert.strictEqual((await response).value, 'second'); } }); @@ -243,6 +243,70 @@ suite('Webview tests', () => { const secondResponse = await sendRecieveMessage(webview, { type: 'get' }); assert.strictEqual(secondResponse.value, 100); }); + + test('webviews should only be able to load resources from workspace by default', async () => { + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true })); + + webview.webview.html = createHtmlDocumentWithBody(/*html*/` + `); + + const workspaceRootUri = vscode.Uri.file(vscode.workspace.rootPath!).with({ scheme: 'vscode-resource' }); + + { + const imagePath = workspaceRootUri.toString() + '/image.png'; + const response = sendRecieveMessage(webview, { src: imagePath }); + assert.strictEqual((await response).value, true); + } + { + const imagePath = workspaceRootUri.toString() + '/no-such-image.png'; + const response = sendRecieveMessage(webview, { src: imagePath }); + assert.strictEqual((await response).value, false); + } + { + const imagePath = vscode.Uri.file(join(vscode.workspace.rootPath!, '..', '..', '..', 'resources', 'linux', 'code.png')).with({ scheme: 'vscode-resource' }); + const response = sendRecieveMessage(webview, { src: imagePath.toString() }); + assert.strictEqual((await response).value, false); + } + }); + + test('webviews should allow overriding allowed resource paths using localResourceRoots', async () => { + const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { + enableScripts: true, + localResourceRoots: [vscode.Uri.file(join(vscode.workspace.rootPath!, 'sub'))] + })); + + webview.webview.html = createHtmlDocumentWithBody(/*html*/` + `); + + const workspaceRootUri = vscode.Uri.file(vscode.workspace.rootPath!).with({ scheme: 'vscode-resource' }); + + { + const response = sendRecieveMessage(webview, { src: workspaceRootUri.toString() + '/sub/image.png' }); + assert.strictEqual((await response).value, true); + } + { + const response = sendRecieveMessage(webview, { src: workspaceRootUri.toString() + '/image.png' }); + assert.strictEqual((await response).value, false); + } + }); }); function createHtmlDocumentWithBody(body: string): string { diff --git a/extensions/vscode-api-tests/testWorkspace/sub/image.png b/extensions/vscode-api-tests/testWorkspace/sub/image.png new file mode 100644 index 00000000000..ff8b42295dd Binary files /dev/null and b/extensions/vscode-api-tests/testWorkspace/sub/image.png differ diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 4beb25d35fc..fa9bc190628 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -typescript@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96" - integrity sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ== +typescript@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.2.tgz#c03a5d16f30bb60ad8bb6fe8e7cb212eedeec950" + integrity sha512-gOoGJWbNnFAfP9FlrSV63LYD5DJqYJHG5ky1kOXSl3pCImn4rqWy/flyq1BRd4iChQsoCqjbQaqtmXO4yCVPCA== diff --git a/package.json b/package.json index 41a499b7851..8a3213512a5 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "vscode-nsfw": "1.0.17", "vscode-ripgrep": "^1.2.2", "vscode-textmate": "^4.0.1", - "vscode-xterm": "3.9.0-beta1", + "vscode-xterm": "3.9.0-beta5", "winreg": "^1.2.4", "yauzl": "^2.9.1", "yazl": "^2.4.3" diff --git a/src/typings/vscode-xterm.d.ts b/src/typings/vscode-xterm.d.ts index a104e7aee35..2631d806ad2 100644 --- a/src/typings/vscode-xterm.d.ts +++ b/src/typings/vscode-xterm.d.ts @@ -89,6 +89,16 @@ declare module 'vscode-xterm' { */ experimentalCharAtlas?: 'none' | 'static' | 'dynamic'; + /** + * (EXPERIMENTAL) Defines which implementation to use for buffer lines. + * + * - 'JsArray': The default/stable implementation. + * - 'TypedArray': The new experimental implementation based on TypedArrays that is expected to + * significantly boost performance and memory consumption. Use at your own risk. + * + * This option will be removed in the future. + */ + experimentalBufferLineImpl?: 'JsArray' | 'TypedArray'; /** * The font size used to render text. */ diff --git a/src/vs/base/browser/ui/actionbar/actionbar.css b/src/vs/base/browser/ui/actionbar/actionbar.css index 4ff042d038f..25795ddb631 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.css +++ b/src/vs/base/browser/ui/actionbar/actionbar.css @@ -28,10 +28,6 @@ .monaco-action-bar .action-item { cursor: pointer; display: inline-block; - -ms-transition: -ms-transform 50ms ease; - -webkit-transition: -webkit-transform 50ms ease; - -moz-transition: -moz-transform 50ms ease; - -o-transition: -o-transform 50ms ease; transition: transform 50ms ease; position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */ } @@ -41,11 +37,7 @@ } .monaco-action-bar.animated .action-item.active { - -ms-transform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */ - -webkit-transform: scale(1.272019649, 1.272019649); - -moz-transform: scale(1.272019649, 1.272019649); - -o-transform: scale(1.272019649, 1.272019649); - transform: scale(1.272019649, 1.272019649); + transform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */ } .monaco-action-bar .action-item .icon { @@ -87,10 +79,6 @@ } .monaco-action-bar.animated.vertical .action-item.active { - -ms-transform: translate(5px, 0); - -webkit-transform: translate(5px, 0); - -moz-transform: translate(5px, 0); - -o-transform: translate(5px, 0); transform: translate(5px, 0); } diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 9a4fb385355..4d25c01ecfd 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -419,6 +419,10 @@ export class ActionBar extends Disposable implements IActionRunner { this._context = options.context; this._actionRunner = this.options.actionRunner; + if (!this.options.triggerKeys) { + this.options.triggerKeys = defaultOptions.triggerKeys; + } + if (!this._actionRunner) { this._actionRunner = new ActionRunner(); this._register(this._actionRunner); diff --git a/src/vs/base/browser/ui/menu/menu.css b/src/vs/base/browser/ui/menu/menu.css index 938304b5ef2..63c1860664d 100644 --- a/src/vs/base/browser/ui/menu/menu.css +++ b/src/vs/base/browser/ui/menu/menu.css @@ -14,20 +14,12 @@ .monaco-menu .monaco-action-bar.vertical .action-item { padding: 0; - -ms-transform: none; - -webkit-transform: none; - -moz-transform: none; - -o-transform: none; transform: none; display: -ms-flexbox; display: flex; } .monaco-menu .monaco-action-bar.vertical .action-item.active { - -ms-transform: none; - -webkit-transform: none; - -moz-transform: none; - -o-transform: none; transform: none; } diff --git a/src/vs/base/browser/ui/progressbar/progressbar.css b/src/vs/base/browser/ui/progressbar/progressbar.css index 0546a200cdf..f926530cec4 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.css +++ b/src/vs/base/browser/ui/progressbar/progressbar.css @@ -24,10 +24,6 @@ .monaco-progress-container.discrete .progress-bit { left: 0; transition: width 100ms linear; - -webkit-transition: width 100ms linear; - -o-transition: width 100ms linear; - -moz-transition: width 100ms linear; - -ms-transition: width 100ms linear; } .monaco-progress-container.discrete.done .progress-bit { diff --git a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css index aa824d83a2f..b05c77eed8a 100644 --- a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css +++ b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css @@ -44,10 +44,6 @@ /* Background rule added for IE9 - to allow clicks on dom node */ background:rgba(0,0,0,0); - -webkit-transition: opacity 100ms linear; - -o-transition: opacity 100ms linear; - -moz-transition: opacity 100ms linear; - -ms-transition: opacity 100ms linear; transition: opacity 100ms linear; } .monaco-scrollable-element > .invisible { @@ -55,10 +51,6 @@ pointer-events: none; } .monaco-scrollable-element > .invisible.fade { - -webkit-transition: opacity 800ms linear; - -o-transition: opacity 800ms linear; - -moz-transition: opacity 800ms linear; - -ms-transition: opacity 800ms linear; transition: opacity 800ms linear; } diff --git a/src/vs/base/browser/ui/splitview/panelview.css b/src/vs/base/browser/ui/splitview/panelview.css index fba60f61621..4801a2bd3a9 100644 --- a/src/vs/base/browser/ui/splitview/panelview.css +++ b/src/vs/base/browser/ui/splitview/panelview.css @@ -90,21 +90,13 @@ .monaco-panel-view.animated .split-view-view { transition-duration: 0.15s; - -webkit-transition-duration: 0.15s; - -moz-transition-duration: 0.15s; transition-timing-function: ease-out; - -webkit-transition-timing-function: ease-out; - -moz-transition-timing-function: ease-out; } .monaco-panel-view.animated.vertical .split-view-view { transition-property: height; - -webkit-transition-property: height; - -moz-transition-property: height; } .monaco-panel-view.animated.horizontal .split-view-view { transition-property: width; - -webkit-transition-property: width; - -moz-transition-property: width; } diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 2f7554426dc..3d0da96fb2d 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -188,9 +188,9 @@ export abstract class Panel implements IView { layout(size: number): void { const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; - this.layoutBody(size - headerSize); if (this.isExpanded()) { + this.layoutBody(size - headerSize); this.expandedSize = size; } } diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index cc3d388ce35..bcf32e22066 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -657,7 +657,7 @@ export class RunOnceWorker extends RunOnceScheduler { export function nfcall(fn: Function, ...args: any[]): Promise; export function nfcall(fn: Function, ...args: any[]): Promise; export function nfcall(fn: Function, ...args: any[]): any { - return new Promise((c, e) => fn(...args, (err: any, result: any) => err ? e(err) : c(result))); + return new TPromise((c, e) => fn(...args, (err: any, result: any) => err ? e(err) : c(result))); } export function ninvoke(thisArg: any, fn: Function, ...args: any[]): TPromise; diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index a2504791f3d..40f273531a6 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -686,4 +686,20 @@ export function containsUppercaseCharacter(target: string, ignoreEscapedChars = export function uppercaseFirstLetter(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); -} \ No newline at end of file +} + +export function getNLines(str: string, n = 1): string { + if (n === 0) { + return ''; + } + + let idx = -1; + do { + idx = str.indexOf('\n', idx + 1); + n--; + } while (n > 0 && idx >= 0); + + return idx >= 0 ? + str.substr(0, idx) : + str; +} diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index 7f9293c5927..c55e76ee6f1 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -5,7 +5,6 @@ import { transformErrorForSerialization } from 'vs/base/common/errors'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ErrorCallback, TPromise, ValueCallback } from 'vs/base/common/winjs.base'; import { isWeb } from 'vs/base/common/platform'; const INITIALIZE = '$initialize'; @@ -56,13 +55,13 @@ interface IReplyMessage extends IMessage { } interface IMessageReply { - c: ValueCallback; - e: ErrorCallback; + resolve: (value?: any) => void; + reject: (error?: any) => void; } interface IMessageHandler { sendMessage(msg: string): void; - handleMessage(method: string, args: any[]): TPromise; + handleMessage(method: string, args: any[]): Promise; } class SimpleWorkerProtocol { @@ -83,15 +82,15 @@ class SimpleWorkerProtocol { this._workerId = workerId; } - public sendMessage(method: string, args: any[]): TPromise { + public sendMessage(method: string, args: any[]): Promise { let req = String(++this._lastSentReq); let reply: IMessageReply = { - c: null, - e: null + resolve: null, + reject: null }; - let result = new TPromise((c, e) => { - reply.c = c; - reply.e = e; + let result = new Promise((resolve, reject) => { + reply.resolve = resolve; + reply.reject = reject; }); this._pendingReplies[req] = reply; @@ -140,11 +139,11 @@ class SimpleWorkerProtocol { err.message = replyMessage.err.message; err.stack = replyMessage.err.stack; } - reply.e(err); + reply.reject(err); return; } - reply.c(replyMessage.res); + reply.resolve(replyMessage.res); return; } @@ -185,14 +184,14 @@ class SimpleWorkerProtocol { export class SimpleWorkerClient extends Disposable { private _worker: IWorker; - private _onModuleLoaded: TPromise; + private _onModuleLoaded: Promise; private _protocol: SimpleWorkerProtocol; - private _lazyProxy: TPromise; + private _lazyProxy: Promise; constructor(workerFactory: IWorkerFactory, moduleId: string) { super(); - let lazyProxyFulfill: (v: T) => void = null; + let lazyProxyResolve: (v: T) => void = null; let lazyProxyReject: (err: any) => void = null; this._worker = this._register(workerFactory.create( @@ -211,9 +210,9 @@ export class SimpleWorkerClient extends Disposable { sendMessage: (msg: string): void => { this._worker.postMessage(msg); }, - handleMessage: (method: string, args: any[]): TPromise => { + handleMessage: (method: string, args: any[]): Promise => { // Intentionally not supporting worker -> main requests - return TPromise.as(null); + return Promise.resolve(null); } }); this._protocol.setWorkerId(this._worker.getId()); @@ -228,9 +227,9 @@ export class SimpleWorkerClient extends Disposable { loaderConfiguration = (self).requirejs.s.contexts._.config; } - this._lazyProxy = new TPromise((c, e) => { - lazyProxyFulfill = c; - lazyProxyReject = e; + this._lazyProxy = new Promise((resolve, reject) => { + lazyProxyResolve = resolve; + lazyProxyReject = reject; }); // Send initialize message @@ -244,18 +243,18 @@ export class SimpleWorkerClient extends Disposable { for (let i = 0; i < availableMethods.length; i++) { (proxy as any)[availableMethods[i]] = createProxyMethod(availableMethods[i], proxyMethodRequest); } - lazyProxyFulfill(proxy); + lazyProxyResolve(proxy); }, (e) => { lazyProxyReject(e); this._onError('Worker failed to load ' + moduleId, e); }); // Create proxy to loaded code - let proxyMethodRequest = (method: string, args: any[]): TPromise => { + let proxyMethodRequest = (method: string, args: any[]): Promise => { return this._request(method, args); }; - let createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => TPromise): Function => { + let createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise): Function => { return function () { let args = Array.prototype.slice.call(arguments, 0); return proxyMethodRequest(method, args); @@ -263,15 +262,15 @@ export class SimpleWorkerClient extends Disposable { }; } - public getProxyObject(): TPromise { + public getProxyObject(): Promise { return this._lazyProxy; } - private _request(method: string, args: any[]): TPromise { - return new TPromise((c, e) => { + private _request(method: string, args: any[]): Promise { + return new Promise((resolve, reject) => { this._onModuleLoaded.then(() => { - this._protocol.sendMessage(method, args).then(c, e); - }, e); + this._protocol.sendMessage(method, args).then(resolve, reject); + }, reject); }); } @@ -300,7 +299,7 @@ export class SimpleWorkerServer { sendMessage: (msg: string): void => { postSerializedMessage(msg); }, - handleMessage: (method: string, args: any[]): TPromise => this._handleMessage(method, args) + handleMessage: (method: string, args: any[]): Promise => this._handleMessage(method, args) }); } @@ -308,23 +307,23 @@ export class SimpleWorkerServer { this._protocol.handleMessage(msg); } - private _handleMessage(method: string, args: any[]): TPromise { + private _handleMessage(method: string, args: any[]): Promise { if (method === INITIALIZE) { return this.initialize(args[0], args[1], args[2]); } if (!this._requestHandler || typeof this._requestHandler[method] !== 'function') { - return TPromise.wrapError(new Error('Missing requestHandler or method: ' + method)); + return Promise.reject(new Error('Missing requestHandler or method: ' + method)); } try { - return TPromise.as(this._requestHandler[method].apply(this._requestHandler, args)); + return Promise.resolve(this._requestHandler[method].apply(this._requestHandler, args)); } catch (e) { - return TPromise.wrapError(e); + return Promise.reject(e); } } - private initialize(workerId: number, moduleId: string, loaderConfig: any): TPromise { + private initialize(workerId: number, moduleId: string, loaderConfig: any): Promise { this._protocol.setWorkerId(workerId); if (this._requestHandler) { @@ -335,7 +334,7 @@ export class SimpleWorkerServer { methods.push(prop); } } - return TPromise.as(methods); + return Promise.resolve(methods); } if (loaderConfig) { @@ -354,11 +353,11 @@ export class SimpleWorkerServer { (self).require.config(loaderConfig); } - let cc: ValueCallback; - let ee: ErrorCallback; - let r = new TPromise((c, e) => { - cc = c; - ee = e; + let resolve: (value?: string[]) => void; + let reject: (error?: any) => void; + let r = new Promise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; }); // Use the global require to be sure to get the global config @@ -373,8 +372,8 @@ export class SimpleWorkerServer { } } - cc(methods); - }, ee); + resolve(methods); + }, reject); return r; } diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index 88179c27bc1..2e8ee07797b 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -391,4 +391,16 @@ suite('Strings', () => { assert.equal(strings.uppercaseFirstLetter(inStr), result, `Wrong result for ${inStr}`); }); }); + + test('getNLines', () => { + assert.equal(strings.getNLines('', 5), ''); + assert.equal(strings.getNLines('foo', 5), 'foo'); + assert.equal(strings.getNLines('foo\nbar', 5), 'foo\nbar'); + assert.equal(strings.getNLines('foo\nbar', 2), 'foo\nbar'); + + assert.equal(strings.getNLines('foo\nbar', 1), 'foo'); + assert.equal(strings.getNLines('foo\nbar'), 'foo'); + assert.equal(strings.getNLines('foo\nbar\nsomething', 2), 'foo\nbar'); + assert.equal(strings.getNLines('foo', 0), ''); + }); }); diff --git a/src/vs/code/electron-main/keyboard.ts b/src/vs/code/electron-main/keyboard.ts index 670068ba501..2ec1623f173 100644 --- a/src/vs/code/electron-main/keyboard.ts +++ b/src/vs/code/electron-main/keyboard.ts @@ -5,14 +5,7 @@ import * as nativeKeymap from 'native-keymap'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IStateService } from 'vs/platform/state/common/state'; -import { Event, Emitter, once } from 'vs/base/common/event'; -import { ConfigWatcher } from 'vs/base/node/config'; -import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ipcMain as ipc } from 'electron'; -import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; -import { ILogService } from 'vs/platform/log/common/log'; +import { Emitter } from 'vs/base/common/event'; export class KeyboardLayoutMonitor { @@ -36,109 +29,4 @@ export class KeyboardLayoutMonitor { } return this._emitter.event(callback); } -} - -export interface IKeybinding { - id: string; - label: string; - isNative: boolean; -} - -export class KeybindingsResolver { - - private static readonly lastKnownKeybindingsMapStorageKey = 'lastKnownKeybindings'; - - private commandIds: Set; - private keybindings: { [commandId: string]: IKeybinding }; - private keybindingsWatcher: ConfigWatcher; - - private _onKeybindingsChanged = new Emitter(); - onKeybindingsChanged: Event = this._onKeybindingsChanged.event; - - constructor( - @IStateService private stateService: IStateService, - @IEnvironmentService environmentService: IEnvironmentService, - @IWindowsMainService private windowsMainService: IWindowsMainService, - @ILogService private logService: ILogService - ) { - this.commandIds = new Set(); - this.keybindings = this.stateService.getItem<{ [id: string]: string; }>(KeybindingsResolver.lastKnownKeybindingsMapStorageKey) || Object.create(null); - this.keybindingsWatcher = new ConfigWatcher(environmentService.appKeybindingsPath, { changeBufferDelay: 100, onError: error => this.logService.error(error) }); - - this.registerListeners(); - } - - private registerListeners(): void { - - // Listen to resolved keybindings from window - ipc.on('vscode:keybindingsResolved', (event, rawKeybindings: string) => { - let keybindings: IKeybinding[] = []; - try { - keybindings = JSON.parse(rawKeybindings); - } catch (error) { - // Should not happen - } - - // Fill hash map of resolved keybindings and check for changes - let keybindingsChanged = false; - let keybindingsCount = 0; - const resolvedKeybindings: { [commandId: string]: IKeybinding } = Object.create(null); - keybindings.forEach(keybinding => { - keybindingsCount++; - - resolvedKeybindings[keybinding.id] = keybinding; - - if (!this.keybindings[keybinding.id] || keybinding.label !== this.keybindings[keybinding.id].label) { - keybindingsChanged = true; - } - }); - - // A keybinding might have been unassigned, so we have to account for that too - if (Object.keys(this.keybindings).length !== keybindingsCount) { - keybindingsChanged = true; - } - - if (keybindingsChanged) { - this.keybindings = resolvedKeybindings; - this.stateService.setItem(KeybindingsResolver.lastKnownKeybindingsMapStorageKey, this.keybindings); // keep to restore instantly after restart - - this._onKeybindingsChanged.fire(); - } - }); - - // Resolve keybindings when any first window is loaded - const onceOnWindowReady = once(this.windowsMainService.onWindowReady); - onceOnWindowReady(win => this.resolveKeybindings(win)); - - // Resolve keybindings again when keybindings.json changes - this.keybindingsWatcher.onDidUpdateConfiguration(() => this.resolveKeybindings()); - - // Resolve keybindings when window reloads because an installed extension could have an impact - this.windowsMainService.onWindowReload(() => this.resolveKeybindings()); - } - - private resolveKeybindings(win = this.windowsMainService.getLastActiveWindow()): void { - if (this.commandIds.size && win) { - const commandIds: string[] = []; - this.commandIds.forEach(id => commandIds.push(id)); - win.sendWhenReady('vscode:resolveKeybindings', JSON.stringify(commandIds)); - } - } - - public getKeybinding(commandId: string): IKeybinding { - if (!commandId) { - return void 0; - } - - if (!this.commandIds.has(commandId)) { - this.commandIds.add(commandId); - } - - return this.keybindings[commandId]; - } - - public dispose(): void { - this._onKeybindingsChanged.dispose(); - this.keybindingsWatcher.dispose(); - } } \ No newline at end of file diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts deleted file mode 100644 index b0f6cdb7872..00000000000 --- a/src/vs/code/electron-main/menus.ts +++ /dev/null @@ -1,1294 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vs/nls'; -import { isMacintosh, isLinux, isWindows, language } from 'vs/base/common/platform'; -import * as arrays from 'vs/base/common/arrays'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { app, shell, Menu, MenuItem, BrowserWindow } from 'electron'; -import { OpenContext, IRunActionInWindowRequest, IWindowsService } from 'vs/platform/windows/common/windows'; -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, 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'; -import { mnemonicMenuLabel as baseMnemonicLabel, unmnemonicLabel } from 'vs/base/common/labels'; -import { KeybindingsResolver } from 'vs/code/electron-main/keyboard'; -import { IWindowsMainService, IWindowsCountChangedEvent } from 'vs/platform/windows/electron-main/windows'; -import { IHistoryMainService } from 'vs/platform/history/common/history'; -import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; -import { URI } from 'vs/base/common/uri'; -import { ILabelService } from 'vs/platform/label/common/label'; - -interface IMenuItemClickHandler { - inDevTools: (contents: Electron.WebContents) => void; - inNoWindow: () => void; -} - -const telemetryFrom = 'menu'; - -export class CodeMenu { - - private static readonly MAX_MENU_RECENT_ENTRIES = 10; - - private keys = [ - 'files.autoSave', - 'editor.multiCursorModifier', - 'workbench.sideBar.location', - 'workbench.statusBar.visible', - 'workbench.activityBar.visible', - 'window.enableMenuBarMnemonics', - 'window.nativeTabs' - ]; - - private isQuitting: boolean; - private appMenuInstalled: boolean; - - private menuUpdater: RunOnceScheduler; - - private keybindingsResolver: KeybindingsResolver; - - private closeFolder: Electron.MenuItem; - private closeWorkspace: Electron.MenuItem; - - constructor( - @IUpdateService private updateService: IUpdateService, - @IInstantiationService instantiationService: IInstantiationService, - @IConfigurationService private configurationService: IConfigurationService, - @IWindowsMainService private windowsMainService: IWindowsMainService, - @IWindowsService private windowsService: IWindowsService, - @IEnvironmentService private environmentService: IEnvironmentService, - @ITelemetryService private telemetryService: ITelemetryService, - @IHistoryMainService private historyMainService: IHistoryMainService, - @ILabelService private labelService: ILabelService - ) { - this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0); - this.keybindingsResolver = instantiationService.createInstance(KeybindingsResolver); - - this.install(); - - this.registerListeners(); - } - - private registerListeners(): void { - - // Keep flag when app quits - app.on('will-quit', () => { - this.isQuitting = true; - }); - - // Listen to some events from window service to update menu - this.historyMainService.onRecentlyOpenedChange(() => this.updateMenu()); - this.windowsMainService.onWindowsCountChanged(e => this.onWindowsCountChanged(e)); - this.windowsMainService.onActiveWindowChanged(() => this.updateWorkspaceMenuItems()); - this.windowsMainService.onWindowReady(() => this.updateWorkspaceMenuItems()); - this.windowsMainService.onWindowClose(() => this.updateWorkspaceMenuItems()); - - // Update when auto save config changes - this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)); - - // Listen to update service - this.updateService.onStateChange(() => this.updateMenu()); - - // Listen to keybindings change - this.keybindingsResolver.onKeybindingsChanged(() => this.updateMenu()); - } - - private onConfigurationUpdated(event: IConfigurationChangeEvent): void { - if (this.keys.some(key => event.affectsConfiguration(key))) { - this.updateMenu(); - } - } - - private get currentAutoSaveSetting(): string { - return this.configurationService.getValue('files.autoSave'); - } - - private get currentMultiCursorModifierSetting(): string { - return this.configurationService.getValue('editor.multiCursorModifier'); - } - - private get currentSidebarLocation(): string { - return this.configurationService.getValue('workbench.sideBar.location') || 'left'; - } - - private get currentStatusbarVisible(): boolean { - let statusbarVisible = this.configurationService.getValue('workbench.statusBar.visible'); - if (typeof statusbarVisible !== 'boolean') { - statusbarVisible = true; - } - return statusbarVisible; - } - - private get currentActivityBarVisible(): boolean { - let activityBarVisible = this.configurationService.getValue('workbench.activityBar.visible'); - if (typeof activityBarVisible !== 'boolean') { - activityBarVisible = true; - } - return activityBarVisible; - } - - private get currentEnableMenuBarMnemonics(): boolean { - let enableMenuBarMnemonics = this.configurationService.getValue('window.enableMenuBarMnemonics'); - if (typeof enableMenuBarMnemonics !== 'boolean') { - enableMenuBarMnemonics = true; - } - return enableMenuBarMnemonics; - } - - private get currentEnableNativeTabs(): boolean { - let enableNativeTabs = this.configurationService.getValue('window.nativeTabs'); - if (typeof enableNativeTabs !== 'boolean') { - enableNativeTabs = false; - } - return enableNativeTabs; - } - - private updateMenu(): void { - this.menuUpdater.schedule(); // buffer multiple attempts to update the menu - } - - private doUpdateMenu(): void { - - // Due to limitations in Electron, it is not possible to update menu items dynamically. The suggested - // workaround from Electron is to set the application menu again. - // See also https://github.com/electron/electron/issues/846 - // - // Run delayed to prevent updating menu while it is open - if (!this.isQuitting) { - setTimeout(() => { - if (!this.isQuitting) { - this.install(); - } - }, 10 /* delay this because there is an issue with updating a menu when it is open */); - } - } - - private onWindowsCountChanged(e: IWindowsCountChangedEvent): void { - if (!isMacintosh) { - return; - } - - // Update menu if window count goes from N > 0 or 0 > N to update menu item enablement - if ((e.oldCount === 0 && e.newCount > 0) || (e.oldCount > 0 && e.newCount === 0)) { - this.updateMenu(); - } - } - - private updateWorkspaceMenuItems(): void { - const window = this.windowsMainService.getLastActiveWindow(); - const isInWorkspaceContext = window && !!window.openedWorkspace; - const isInFolderContext = window && !!window.openedFolderUri; - - this.closeWorkspace.visible = isInWorkspaceContext; - this.closeFolder.visible = !isInWorkspaceContext; - this.closeFolder.enabled = isInFolderContext || isLinux /* https://github.com/Microsoft/vscode/issues/36431 */; - } - - private install(): void { - - // Menus - const menubar = new Menu(); - - // Mac: Application - let macApplicationMenuItem: Electron.MenuItem; - if (isMacintosh) { - const applicationMenu = new Menu(); - macApplicationMenuItem = new MenuItem({ label: product.nameShort, submenu: applicationMenu }); - this.setMacApplicationMenu(applicationMenu); - } - - // File - const fileMenu = new Menu(); - const fileMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mFile', comment: ['&& denotes a mnemonic'] }, "&&File")), submenu: fileMenu }); - this.setFileMenu(fileMenu); - - // Edit - const editMenu = new Menu(); - const editMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mEdit', comment: ['&& denotes a mnemonic'] }, "&&Edit")), submenu: editMenu }); - this.setEditMenu(editMenu); - - // Selection - const selectionMenu = new Menu(); - const selectionMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection")), submenu: selectionMenu }); - this.setSelectionMenu(selectionMenu); - - // View - const viewMenu = new Menu(); - const viewMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mView', comment: ['&& denotes a mnemonic'] }, "&&View")), submenu: viewMenu }); - this.setViewMenu(viewMenu); - - // Goto - const gotoMenu = new Menu(); - const gotoMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go")), submenu: gotoMenu }); - this.setGotoMenu(gotoMenu); - - // Debug - const debugMenu = new Menu(); - const debugMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug")), submenu: debugMenu }); - this.setDebugMenu(debugMenu); - - // Terminal - const terminalMenu = new Menu(); - const terminalMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal")), submenu: terminalMenu }); - this.setTerminalMenu(terminalMenu); - - // Mac: Window - let macWindowMenuItem: Electron.MenuItem; - if (isMacintosh) { - const windowMenu = new Menu(); - macWindowMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize('mWindow', "Window")), submenu: windowMenu, role: 'window' }); - this.setMacWindowMenu(windowMenu); - } - - // Help - const helpMenu = new Menu(); - const helpMenuItem = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'mHelp', comment: ['&& denotes a mnemonic'] }, "&&Help")), submenu: helpMenu, role: 'help' }); - this.setHelpMenu(helpMenu); - - - // Menu Structure - if (macApplicationMenuItem) { - menubar.append(macApplicationMenuItem); - } - - menubar.append(fileMenuItem); - menubar.append(editMenuItem); - menubar.append(selectionMenuItem); - menubar.append(viewMenuItem); - menubar.append(gotoMenuItem); - menubar.append(debugMenuItem); - menubar.append(terminalMenuItem); - - if (macWindowMenuItem) { - menubar.append(macWindowMenuItem); - } - - menubar.append(helpMenuItem); - - Menu.setApplicationMenu(menubar); - - // Dock Menu - if (isMacintosh && !this.appMenuInstalled) { - this.appMenuInstalled = true; - - const dockMenu = new Menu(); - dockMenu.append(new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsMainService.openNewWindow(OpenContext.DOCK) })); - - app.dock.setMenu(dockMenu); - } - } - - private setMacApplicationMenu(macApplicationMenu: Electron.Menu): void { - const about = new MenuItem({ label: nls.localize('mAbout', "About {0}", product.nameLong), role: 'about' }); - const checkForUpdates = this.getUpdateMenuItems(); - const preferences = this.getPreferencesMenu(); - const servicesMenu = new Menu(); - const services = new MenuItem({ label: nls.localize('mServices', "Services"), role: 'services', submenu: servicesMenu }); - const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", product.nameLong), role: 'hide', accelerator: 'Command+H' }); - const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideothers', accelerator: 'Command+Alt+H' }); - 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 || !!BrowserWindow.getFocusedWindow()) { - this.windowsMainService.quit(); // fix for https://github.com/Microsoft/vscode/issues/39191 - } - } - })); - - const actions = [about]; - actions.push(...checkForUpdates); - actions.push(...[ - __separator__(), - preferences, - __separator__(), - services, - __separator__(), - hide, - hideOthers, - showAll, - __separator__(), - quit - ]); - - actions.forEach(i => macApplicationMenu.append(i)); - } - - private setFileMenu(fileMenu: Electron.Menu): void { - const hasNoWindows = (this.windowsMainService.getWindowCount() === 0); - - let newFile: Electron.MenuItem; - if (hasNoWindows) { - newFile = new MenuItem(this.likeAction('workbench.action.files.newUntitledFile', { label: this.mnemonicLabel(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File")), click: () => this.windowsMainService.openNewWindow(OpenContext.MENU) })); - } else { - newFile = this.createMenuItem(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File"), 'workbench.action.files.newUntitledFile'); - } - - let open: Electron.MenuItem; - if (hasNoWindows) { - open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: this.mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: (menuItem, win, event) => this.windowsMainService.pickFileFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); - } else { - open = this.createMenuItem(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open..."), ['workbench.action.files.openFileFolder', 'workbench.action.files.openFileFolderInNewWindow']); - } - - let openWorkspace: Electron.MenuItem; - if (hasNoWindows) { - openWorkspace = new MenuItem(this.likeAction('workbench.action.openWorkspace', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "Open Wor&&kspace...")), click: (menuItem, win, event) => this.windowsMainService.pickWorkspaceAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); - } else { - openWorkspace = this.createMenuItem(nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "Open Wor&&kspace..."), ['workbench.action.openWorkspace', 'workbench.action.openWorkspaceInNewWindow']); - } - - let openFolder: Electron.MenuItem; - if (hasNoWindows) { - openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: (menuItem, win, event) => this.windowsMainService.pickFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); - } else { - openFolder = this.createMenuItem(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder..."), ['workbench.action.files.openFolder', 'workbench.action.files.openFolderInNewWindow']); - } - - let openFile: Electron.MenuItem; - if (hasNoWindows) { - openFile = new MenuItem(this.likeAction('workbench.action.files.openFile', { label: this.mnemonicLabel(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")), click: (menuItem, win, event) => this.windowsMainService.pickFileAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } }) })); - } else { - openFile = this.createMenuItem(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File..."), ['workbench.action.files.openFile', 'workbench.action.files.openFileInNewWindow']); - } - - const openRecentMenu = new Menu(); - this.setOpenRecentMenu(openRecentMenu); - const openRecent = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miOpenRecent', comment: ['&& denotes a mnemonic'] }, "Open &&Recent")), submenu: openRecentMenu, enabled: openRecentMenu.items.length > 0 }); - - const saveWorkspaceAs = this.createMenuItem(nls.localize('miSaveWorkspaceAs', "Save Workspace As..."), 'workbench.action.saveWorkspaceAs'); - const addFolder = this.createMenuItem(nls.localize({ key: 'miAddFolderToWorkspace', comment: ['&& denotes a mnemonic'] }, "A&&dd Folder to Workspace..."), 'workbench.action.addRootFolder'); - - const saveFile = this.createMenuItem(nls.localize({ key: 'miSave', comment: ['&& denotes a mnemonic'] }, "&&Save"), 'workbench.action.files.save'); - const saveFileAs = this.createMenuItem(nls.localize({ key: 'miSaveAs', comment: ['&& denotes a mnemonic'] }, "Save &&As..."), 'workbench.action.files.saveAs'); - const saveAllFiles = this.createMenuItem(nls.localize({ key: 'miSaveAll', comment: ['&& denotes a mnemonic'] }, "Save A&&ll"), 'workbench.action.files.saveAll'); - - const autoSaveEnabled = [AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE].some(s => this.currentAutoSaveSetting === s); - - const autoSave = this.createMenuItem(this.mnemonicLabel(nls.localize('miAutoSave', "A&&uto Save")), 'workbench.action.toggleAutoSave', this.windowsMainService.getWindowCount() > 0, autoSaveEnabled); - - const preferences = this.getPreferencesMenu(); - - const newWindow = new MenuItem(this.likeAction('workbench.action.newWindow', { label: this.mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsMainService.openNewWindow(OpenContext.MENU) })); - const revertFile = this.createMenuItem(nls.localize({ key: 'miRevert', comment: ['&& denotes a mnemonic'] }, "Re&&vert File"), 'workbench.action.files.revert'); - const closeWindow = new MenuItem(this.likeAction('workbench.action.closeWindow', { label: this.mnemonicLabel(nls.localize({ key: 'miCloseWindow', comment: ['&& denotes a mnemonic'] }, "Clos&&e Window")), click: () => this.windowsMainService.getLastActiveWindow().win.close(), enabled: this.windowsMainService.getWindowCount() > 0 })); - - this.closeWorkspace = this.createMenuItem(nls.localize({ key: 'miCloseWorkspace', comment: ['&& denotes a mnemonic'] }, "Close &&Workspace"), 'workbench.action.closeFolder'); - this.closeFolder = this.createMenuItem(nls.localize({ key: 'miCloseFolder', comment: ['&& denotes a mnemonic'] }, "Close &&Folder"), 'workbench.action.closeFolder'); - - const closeEditor = this.createMenuItem(nls.localize({ key: 'miCloseEditor', comment: ['&& denotes a mnemonic'] }, "&&Close Editor"), 'workbench.action.closeActiveEditor'); - - const exit = new MenuItem(this.likeAction('workbench.action.quit', { label: this.mnemonicLabel(nls.localize({ key: 'miExit', comment: ['&& denotes a mnemonic'] }, "E&&xit")), click: () => this.windowsMainService.quit() })); - - this.updateWorkspaceMenuItems(); - - arrays.coalesce([ - newFile, - newWindow, - __separator__(), - isMacintosh ? open : null, - !isMacintosh ? openFile : null, - !isMacintosh ? openFolder : null, - openWorkspace, - openRecent, - __separator__(), - addFolder, - saveWorkspaceAs, - __separator__(), - saveFile, - saveFileAs, - saveAllFiles, - __separator__(), - autoSave, - __separator__(), - !isMacintosh ? preferences : null, - !isMacintosh ? __separator__() : null, - revertFile, - closeEditor, - this.closeWorkspace, - this.closeFolder, - closeWindow, - !isMacintosh ? __separator__() : null, - !isMacintosh ? exit : null - ]).forEach(item => fileMenu.append(item)); - } - - private getPreferencesMenu(): Electron.MenuItem { - const settings = this.createMenuItem(nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&Settings"), 'workbench.action.openSettings'); - const extensions = this.createMenuItem(nls.localize({ key: 'miOpenExtensions', comment: ['&& denotes a mnemonic'] }, '&&Extensions'), 'workbench.view.extensions'); - const kebindingSettings = this.createMenuItem(nls.localize({ key: 'miOpenKeymap', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts"), 'workbench.action.openGlobalKeybindings'); - const keymapExtensions = this.createMenuItem(nls.localize({ key: 'miOpenKeymapExtensions', comment: ['&& denotes a mnemonic'] }, "&&Keymaps"), 'workbench.extensions.action.showRecommendedKeymapExtensions'); - const snippetsSettings = this.createMenuItem(nls.localize({ key: 'miOpenSnippets', comment: ['&& denotes a mnemonic'] }, "User &&Snippets"), 'workbench.action.openSnippets'); - const colorThemeSelection = this.createMenuItem(nls.localize({ key: 'miSelectColorTheme', comment: ['&& denotes a mnemonic'] }, "&&Color Theme"), 'workbench.action.selectTheme'); - const iconThemeSelection = this.createMenuItem(nls.localize({ key: 'miSelectIconTheme', comment: ['&& denotes a mnemonic'] }, "File &&Icon Theme"), 'workbench.action.selectIconTheme'); - - const preferencesMenu = new Menu(); - preferencesMenu.append(settings); - preferencesMenu.append(extensions); - preferencesMenu.append(__separator__()); - preferencesMenu.append(kebindingSettings); - preferencesMenu.append(keymapExtensions); - preferencesMenu.append(__separator__()); - preferencesMenu.append(snippetsSettings); - preferencesMenu.append(__separator__()); - preferencesMenu.append(colorThemeSelection); - preferencesMenu.append(iconThemeSelection); - - return new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miPreferences', comment: ['&& denotes a mnemonic'] }, "&&Preferences")), submenu: preferencesMenu }); - } - - private setOpenRecentMenu(openRecentMenu: Electron.Menu): void { - openRecentMenu.append(this.createMenuItem(nls.localize({ key: 'miReopenClosedEditor', comment: ['&& denotes a mnemonic'] }, "&&Reopen Closed Editor"), 'workbench.action.reopenClosedEditor')); - - const { workspaces, files } = this.historyMainService.getRecentlyOpened(); - - // Workspaces - if (workspaces.length > 0) { - openRecentMenu.append(__separator__()); - - for (let i = 0; i < CodeMenu.MAX_MENU_RECENT_ENTRIES && i < workspaces.length; i++) { - openRecentMenu.append(this.createOpenRecentMenuItem(workspaces[i], 'openRecentWorkspace', false)); - } - } - - // Files - if (files.length > 0) { - openRecentMenu.append(__separator__()); - - for (let i = 0; i < CodeMenu.MAX_MENU_RECENT_ENTRIES && i < files.length; i++) { - openRecentMenu.append(this.createOpenRecentMenuItem(files[i], 'openRecentFile', true)); - } - } - - if (workspaces.length || files.length) { - const hasNoWindows = (this.windowsMainService.getWindowCount() === 0); - - openRecentMenu.append(__separator__()); - openRecentMenu.append(this.createMenuItem(nls.localize({ key: 'miMore', comment: ['&& denotes a mnemonic'] }, "&&More..."), 'workbench.action.openRecent')); - openRecentMenu.append(__separator__()); - - let clearRecentFiles: MenuItem; - if (hasNoWindows) { - clearRecentFiles = new MenuItem(this.likeAction('workbench.action.clearRecentFiles', { label: this.mnemonicLabel(nls.localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened")), click: () => this.historyMainService.clearRecentlyOpened() })); - } else { - clearRecentFiles = this.createMenuItem(nls.localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened"), 'workbench.action.clearRecentFiles'); - } - - openRecentMenu.append(clearRecentFiles); - } - } - - private createOpenRecentMenuItem(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string, commandId: string, isFile: boolean): Electron.MenuItem { - let label: string; - let uri: URI; - if (isSingleFolderWorkspaceIdentifier(workspace)) { - label = unmnemonicLabel(this.labelService.getWorkspaceLabel(workspace, { verbose: true })); - uri = workspace; - } else if (isWorkspaceIdentifier(workspace)) { - label = this.labelService.getWorkspaceLabel(workspace, { verbose: true }); - uri = URI.file(workspace.configPath); - } else { - uri = URI.file(workspace); - label = unmnemonicLabel(this.labelService.getUriLabel(uri)); - } - - return new MenuItem(this.likeAction(commandId, { - label, - click: (menuItem, win, event) => { - const openInNewWindow = this.isOptionClick(event); - const success = this.windowsMainService.open({ - context: OpenContext.MENU, - cli: this.environmentService.args, - urisToOpen: [uri], - forceNewWindow: openInNewWindow, - forceOpenWorkspaceAsFile: isFile - }).length > 0; - - if (!success) { - this.historyMainService.removeFromRecentlyOpened([workspace]); - } - } - }, false)); - } - - private isOptionClick(event: Electron.Event): boolean { - return event && ((!isMacintosh && (event.ctrlKey || event.shiftKey)) || (isMacintosh && (event.metaKey || event.altKey))); - } - - private createRoleMenuItem(label: string, commandId: string, role: any): Electron.MenuItem { - const options: Electron.MenuItemConstructorOptions = { - label: this.mnemonicLabel(label), - role, - enabled: true - }; - - return new MenuItem(this.withKeybinding(commandId, options)); - } - - private setEditMenu(winLinuxEditMenu: Electron.Menu): void { - let undo: Electron.MenuItem; - let redo: Electron.MenuItem; - let cut: Electron.MenuItem; - let copy: Electron.MenuItem; - let paste: Electron.MenuItem; - - if (isMacintosh) { - undo = this.createContextAwareMenuItem(nls.localize({ key: 'miUndo', comment: ['&& denotes a mnemonic'] }, "&&Undo"), 'undo', { - inDevTools: devTools => devTools.undo(), - inNoWindow: () => Menu.sendActionToFirstResponder('undo:') - }); - redo = this.createContextAwareMenuItem(nls.localize({ key: 'miRedo', comment: ['&& denotes a mnemonic'] }, "&&Redo"), 'redo', { - inDevTools: devTools => devTools.redo(), - inNoWindow: () => Menu.sendActionToFirstResponder('redo:') - }); - cut = this.createRoleMenuItem(nls.localize({ key: 'miCut', comment: ['&& denotes a mnemonic'] }, "Cu&&t"), 'editor.action.clipboardCutAction', 'cut'); - copy = this.createRoleMenuItem(nls.localize({ key: 'miCopy', comment: ['&& denotes a mnemonic'] }, "&&Copy"), 'editor.action.clipboardCopyAction', 'copy'); - paste = this.createRoleMenuItem(nls.localize({ key: 'miPaste', comment: ['&& denotes a mnemonic'] }, "&&Paste"), 'editor.action.clipboardPasteAction', 'paste'); - } else { - undo = this.createMenuItem(nls.localize({ key: 'miUndo', comment: ['&& denotes a mnemonic'] }, "&&Undo"), 'undo'); - redo = this.createMenuItem(nls.localize({ key: 'miRedo', comment: ['&& denotes a mnemonic'] }, "&&Redo"), 'redo'); - cut = this.createMenuItem(nls.localize({ key: 'miCut', comment: ['&& denotes a mnemonic'] }, "Cu&&t"), 'editor.action.clipboardCutAction'); - copy = this.createMenuItem(nls.localize({ key: 'miCopy', comment: ['&& denotes a mnemonic'] }, "&&Copy"), 'editor.action.clipboardCopyAction'); - paste = this.createMenuItem(nls.localize({ key: 'miPaste', comment: ['&& denotes a mnemonic'] }, "&&Paste"), 'editor.action.clipboardPasteAction'); - } - - const find = this.createMenuItem(nls.localize({ key: 'miFind', comment: ['&& denotes a mnemonic'] }, "&&Find"), 'actions.find'); - const replace = this.createMenuItem(nls.localize({ key: 'miReplace', comment: ['&& denotes a mnemonic'] }, "&&Replace"), 'editor.action.startFindReplaceAction'); - const findInFiles = this.createMenuItem(nls.localize({ key: 'miFindInFiles', comment: ['&& denotes a mnemonic'] }, "Find &&in Files"), 'workbench.action.findInFiles'); - const replaceInFiles = this.createMenuItem(nls.localize({ key: 'miReplaceInFiles', comment: ['&& denotes a mnemonic'] }, "Replace &&in Files"), 'workbench.action.replaceInFiles'); - - const emmetExpandAbbreviation = this.createMenuItem(nls.localize({ key: 'miEmmetExpandAbbreviation', comment: ['&& denotes a mnemonic'] }, "Emmet: E&&xpand Abbreviation"), 'editor.emmet.action.expandAbbreviation'); - const showEmmetCommands = this.createMenuItem(nls.localize({ key: 'miShowEmmetCommands', comment: ['&& denotes a mnemonic'] }, "E&&mmet..."), 'workbench.action.showEmmetCommands'); - const toggleLineComment = this.createMenuItem(nls.localize({ key: 'miToggleLineComment', comment: ['&& denotes a mnemonic'] }, "&&Toggle Line Comment"), 'editor.action.commentLine'); - const toggleBlockComment = this.createMenuItem(nls.localize({ key: 'miToggleBlockComment', comment: ['&& denotes a mnemonic'] }, "Toggle &&Block Comment"), 'editor.action.blockComment'); - - [ - undo, - redo, - __separator__(), - cut, - copy, - paste, - __separator__(), - find, - replace, - __separator__(), - findInFiles, - replaceInFiles, - __separator__(), - toggleLineComment, - toggleBlockComment, - emmetExpandAbbreviation, - showEmmetCommands - ].forEach(item => winLinuxEditMenu.append(item)); - } - - private setSelectionMenu(winLinuxEditMenu: Electron.Menu): void { - let multiCursorModifierLabel: string; - if (this.currentMultiCursorModifierSetting === 'ctrlCmd') { - multiCursorModifierLabel = nls.localize('miMultiCursorAlt', "Switch to Alt+Click for Multi-Cursor"); // The default has been overwritten - } else { - multiCursorModifierLabel = ( - isMacintosh - ? nls.localize('miMultiCursorCmd', "Switch to Cmd+Click for Multi-Cursor") - : nls.localize('miMultiCursorCtrl', "Switch to Ctrl+Click for Multi-Cursor") - ); - } - - const multicursorModifier = this.createMenuItem(multiCursorModifierLabel, 'workbench.action.toggleMultiCursorModifier'); - const insertCursorAbove = this.createMenuItem(nls.localize({ key: 'miInsertCursorAbove', comment: ['&& denotes a mnemonic'] }, "&&Add Cursor Above"), 'editor.action.insertCursorAbove'); - const insertCursorBelow = this.createMenuItem(nls.localize({ key: 'miInsertCursorBelow', comment: ['&& denotes a mnemonic'] }, "A&&dd Cursor Below"), 'editor.action.insertCursorBelow'); - const insertCursorAtEndOfEachLineSelected = this.createMenuItem(nls.localize({ key: 'miInsertCursorAtEndOfEachLineSelected', comment: ['&& denotes a mnemonic'] }, "Add C&&ursors to Line Ends"), 'editor.action.insertCursorAtEndOfEachLineSelected'); - const addSelectionToNextFindMatch = this.createMenuItem(nls.localize({ key: 'miAddSelectionToNextFindMatch', comment: ['&& denotes a mnemonic'] }, "Add &&Next Occurrence"), 'editor.action.addSelectionToNextFindMatch'); - const addSelectionToPreviousFindMatch = this.createMenuItem(nls.localize({ key: 'miAddSelectionToPreviousFindMatch', comment: ['&& denotes a mnemonic'] }, "Add P&&revious Occurrence"), 'editor.action.addSelectionToPreviousFindMatch'); - const selectHighlights = this.createMenuItem(nls.localize({ key: 'miSelectHighlights', comment: ['&& denotes a mnemonic'] }, "Select All &&Occurrences"), 'editor.action.selectHighlights'); - - const copyLinesUp = this.createMenuItem(nls.localize({ key: 'miCopyLinesUp', comment: ['&& denotes a mnemonic'] }, "&&Copy Line Up"), 'editor.action.copyLinesUpAction'); - const copyLinesDown = this.createMenuItem(nls.localize({ key: 'miCopyLinesDown', comment: ['&& denotes a mnemonic'] }, "Co&&py Line Down"), 'editor.action.copyLinesDownAction'); - const moveLinesUp = this.createMenuItem(nls.localize({ key: 'miMoveLinesUp', comment: ['&& denotes a mnemonic'] }, "Mo&&ve Line Up"), 'editor.action.moveLinesUpAction'); - const moveLinesDown = this.createMenuItem(nls.localize({ key: 'miMoveLinesDown', comment: ['&& denotes a mnemonic'] }, "Move &&Line Down"), 'editor.action.moveLinesDownAction'); - - let selectAll: Electron.MenuItem; - if (isMacintosh) { - selectAll = this.createContextAwareMenuItem(nls.localize({ key: 'miSelectAll', comment: ['&& denotes a mnemonic'] }, "&&Select All"), 'editor.action.selectAll', { - inDevTools: devTools => devTools.selectAll(), - inNoWindow: () => Menu.sendActionToFirstResponder('selectAll:') - }); - } else { - selectAll = this.createMenuItem(nls.localize({ key: 'miSelectAll', comment: ['&& denotes a mnemonic'] }, "&&Select All"), 'editor.action.selectAll'); - } - const smartSelectGrow = this.createMenuItem(nls.localize({ key: 'miSmartSelectGrow', comment: ['&& denotes a mnemonic'] }, "&&Expand Selection"), 'editor.action.smartSelect.grow'); - const smartSelectshrink = this.createMenuItem(nls.localize({ key: 'miSmartSelectShrink', comment: ['&& denotes a mnemonic'] }, "&&Shrink Selection"), 'editor.action.smartSelect.shrink'); - - [ - selectAll, - smartSelectGrow, - smartSelectshrink, - __separator__(), - copyLinesUp, - copyLinesDown, - moveLinesUp, - moveLinesDown, - __separator__(), - multicursorModifier, - insertCursorAbove, - insertCursorBelow, - insertCursorAtEndOfEachLineSelected, - addSelectionToNextFindMatch, - addSelectionToPreviousFindMatch, - selectHighlights, - ].forEach(item => winLinuxEditMenu.append(item)); - } - - private setViewMenu(viewMenu: Electron.Menu): void { - 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'); - - // Views - const explorer = this.createMenuItem(nls.localize({ key: 'miViewExplorer', comment: ['&& denotes a mnemonic'] }, "&&Explorer"), 'workbench.view.explorer'); - const search = this.createMenuItem(nls.localize({ key: 'miViewSearch', comment: ['&& denotes a mnemonic'] }, "&&Search"), 'workbench.view.search'); - const scm = this.createMenuItem(nls.localize({ key: 'miViewSCM', comment: ['&& denotes a mnemonic'] }, "S&&CM"), 'workbench.view.scm'); - const debug = this.createMenuItem(nls.localize({ key: 'miViewDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"), 'workbench.view.debug'); - const extensions = this.createMenuItem(nls.localize({ key: 'miViewExtensions', comment: ['&& denotes a mnemonic'] }, "E&&xtensions"), 'workbench.view.extensions'); - - // Panels - const output = this.createMenuItem(nls.localize({ key: 'miToggleOutput', comment: ['&& denotes a mnemonic'] }, "&&Output"), 'workbench.action.output.toggleOutput'); - const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console"), 'workbench.debug.action.toggleRepl'); - const terminal = this.createMenuItem(nls.localize({ key: 'miToggleTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"), 'workbench.action.terminal.toggleTerminal'); - const problems = this.createMenuItem(nls.localize({ key: 'miMarker', comment: ['&& denotes a mnemonic'] }, "&&Problems"), 'workbench.actions.view.problems'); - - // Appearance - - const appearanceMenu = new Menu(); - - 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'); - const toggleCenteredLayout = this.createMenuItem(nls.localize('miToggleCenteredLayout', "Toggle Centered Layout"), 'workbench.action.toggleCenteredLayout'); - const toggleMenuBar = this.createMenuItem(nls.localize({ key: 'miToggleMenuBar', comment: ['&& denotes a mnemonic'] }, "Toggle Menu &&Bar"), 'workbench.action.toggleMenuBar'); - - const toggleSidebar = this.createMenuItem(nls.localize({ key: 'miToggleSidebar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Side Bar"), 'workbench.action.toggleSidebarVisibility'); - - let moveSideBarLabel: string; - if (this.currentSidebarLocation !== 'right') { - moveSideBarLabel = nls.localize({ key: 'miMoveSidebarRight', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Right"); - } else { - moveSideBarLabel = nls.localize({ key: 'miMoveSidebarLeft', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Left"); - } - - const moveSidebar = this.createMenuItem(moveSideBarLabel, 'workbench.action.toggleSidebarPosition'); - const movePanel = this.createMenuItem(nls.localize('togglePanelPosition', "Toggle Panel Position"), 'workbench.action.togglePanelPosition'); - const togglePanel = this.createMenuItem(nls.localize({ key: 'miTogglePanel', comment: ['&& denotes a mnemonic'] }, "Toggle &&Panel"), 'workbench.action.togglePanel'); - - let statusBarLabel: string; - if (this.currentStatusbarVisible) { - statusBarLabel = nls.localize({ key: 'miHideStatusbar', comment: ['&& denotes a mnemonic'] }, "&&Hide Status Bar"); - } else { - statusBarLabel = nls.localize({ key: 'miShowStatusbar', comment: ['&& denotes a mnemonic'] }, "&&Show Status Bar"); - } - const toggleStatusbar = this.createMenuItem(statusBarLabel, 'workbench.action.toggleStatusbarVisibility'); - - let activityBarLabel: string; - if (this.currentActivityBarVisible) { - activityBarLabel = nls.localize({ key: 'miHideActivityBar', comment: ['&& denotes a mnemonic'] }, "Hide &&Activity Bar"); - } else { - activityBarLabel = nls.localize({ key: 'miShowActivityBar', comment: ['&& denotes a mnemonic'] }, "Show &&Activity Bar"); - } - const toggleActivtyBar = this.createMenuItem(activityBarLabel, 'workbench.action.toggleActivityBarVisibility'); - - const zoomIn = this.createMenuItem(nls.localize({ key: 'miZoomIn', comment: ['&& denotes a mnemonic'] }, "&&Zoom In"), 'workbench.action.zoomIn'); - const zoomOut = this.createMenuItem(nls.localize({ key: 'miZoomOut', comment: ['&& denotes a mnemonic'] }, "Zoom O&&ut"), 'workbench.action.zoomOut'); - const resetZoom = this.createMenuItem(nls.localize({ key: 'miZoomReset', comment: ['&& denotes a mnemonic'] }, "&&Reset Zoom"), 'workbench.action.zoomReset'); - - arrays.coalesce([ - fullscreen, - toggleZenMode, - toggleCenteredLayout, - isWindows || isLinux ? toggleMenuBar : void 0, - __separator__(), - moveSidebar, - toggleSidebar, - movePanel, - togglePanel, - toggleStatusbar, - toggleActivtyBar, - __separator__(), - zoomIn, - zoomOut, - resetZoom - ]).forEach(item => appearanceMenu.append(item)); - - const appearance = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miAppearance', comment: ['&& denotes a mnemonic'] }, "&&Appearance")), submenu: appearanceMenu }); - - // Editor Layout - - const editorLayoutMenu = new Menu(); - - const splitEditorUp = this.createMenuItem(nls.localize({ key: 'miSplitEditorUp', comment: ['&& denotes a mnemonic'] }, "Split &&Up"), 'workbench.action.splitEditorUp'); - const splitEditorDown = this.createMenuItem(nls.localize({ key: 'miSplitEditorDown', comment: ['&& denotes a mnemonic'] }, "Split &&Down"), 'workbench.action.splitEditorDown'); - const splitEditorLeft = this.createMenuItem(nls.localize({ key: 'miSplitEditorLeft', comment: ['&& denotes a mnemonic'] }, "Split &&Left"), 'workbench.action.splitEditorLeft'); - const splitEditorRight = this.createMenuItem(nls.localize({ key: 'miSplitEditorRight', comment: ['&& denotes a mnemonic'] }, "Split &&Right"), 'workbench.action.splitEditorRight'); - - const singleColumnEditorLayout = this.createMenuItem(nls.localize({ key: 'miSingleColumnEditorLayout', comment: ['&& denotes a mnemonic'] }, "&&Single"), 'workbench.action.editorLayoutSingle'); - const twoColumnsEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoColumnsEditorLayout', comment: ['&& denotes a mnemonic'] }, "&&Two Columns"), 'workbench.action.editorLayoutTwoColumns'); - const threeColumnsEditorLayout = this.createMenuItem(nls.localize({ key: 'miThreeColumnsEditorLayout', comment: ['&& denotes a mnemonic'] }, "T&&hree Columns"), 'workbench.action.editorLayoutThreeColumns'); - const twoRowsEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoRowsEditorLayout', comment: ['&& denotes a mnemonic'] }, "T&&wo Rows"), 'workbench.action.editorLayoutTwoRows'); - const threeRowsEditorLayout = this.createMenuItem(nls.localize({ key: 'miThreeRowsEditorLayout', comment: ['&& denotes a mnemonic'] }, "Three &&Rows"), 'workbench.action.editorLayoutThreeRows'); - const twoByTwoGridEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoByTwoGridEditorLayout', comment: ['&& denotes a mnemonic'] }, "&&Grid (2x2)"), 'workbench.action.editorLayoutTwoByTwoGrid'); - const twoRowsRightEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoRowsRightEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two R&&ows Right"), 'workbench.action.editorLayoutTwoRowsRight'); - const twoColumnsBottomEditorLayout = this.createMenuItem(nls.localize({ key: 'miTwoColumnsBottomEditorLayout', comment: ['&& denotes a mnemonic'] }, "Two &&Columns Bottom"), 'workbench.action.editorLayoutTwoColumnsBottom'); - - const toggleEditorLayout = this.createMenuItem(nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Flip &&Layout"), 'workbench.action.toggleEditorGroupLayout'); - - [ - splitEditorUp, - splitEditorDown, - splitEditorLeft, - splitEditorRight, - __separator__(), - singleColumnEditorLayout, - twoColumnsEditorLayout, - threeColumnsEditorLayout, - twoRowsEditorLayout, - threeRowsEditorLayout, - twoByTwoGridEditorLayout, - twoRowsRightEditorLayout, - twoColumnsBottomEditorLayout, - __separator__(), - toggleEditorLayout - ].forEach(item => editorLayoutMenu.append(item)); - - const editorLayout = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miEditorLayout', comment: ['&& denotes a mnemonic'] }, "Editor &&Layout")), submenu: editorLayoutMenu }); - - const toggleWordWrap = this.createMenuItem(nls.localize({ key: 'miToggleWordWrap', comment: ['&& denotes a mnemonic'] }, "Toggle &&Word Wrap"), 'editor.action.toggleWordWrap'); - const toggleMinimap = this.createMenuItem(nls.localize({ key: 'miToggleMinimap', comment: ['&& denotes a mnemonic'] }, "Toggle &&Minimap"), 'editor.action.toggleMinimap'); - const toggleRenderWhitespace = this.createMenuItem(nls.localize({ key: 'miToggleRenderWhitespace', comment: ['&& denotes a mnemonic'] }, "Toggle &&Render Whitespace"), 'editor.action.toggleRenderWhitespace'); - const toggleRenderControlCharacters = this.createMenuItem(nls.localize({ key: 'miToggleRenderControlCharacters', comment: ['&& denotes a mnemonic'] }, "Toggle &&Control Characters"), 'editor.action.toggleRenderControlCharacter'); - const toggleBreadcrumbs = this.createMenuItem(nls.localize({ key: 'miToggleBreadcrumbs', comment: ['&& denotes a mnemonic'] }, "Toggle &&Breadcrumbs"), 'breadcrumbs.toggle'); - - arrays.coalesce([ - commands, - openView, - __separator__(), - appearance, - editorLayout, - __separator__(), - explorer, - search, - scm, - debug, - extensions, - __separator__(), - output, - problems, - debugConsole, - terminal, - __separator__(), - toggleWordWrap, - toggleMinimap, - toggleRenderWhitespace, - toggleRenderControlCharacters, - toggleBreadcrumbs - ]).forEach(item => viewMenu.append(item)); - } - - private setGotoMenu(gotoMenu: Electron.Menu): void { - const back = this.createMenuItem(nls.localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back"), 'workbench.action.navigateBack'); - const forward = this.createMenuItem(nls.localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward"), 'workbench.action.navigateForward'); - - const switchEditorMenu = new Menu(); - - const nextEditor = this.createMenuItem(nls.localize({ key: 'miNextEditor', comment: ['&& denotes a mnemonic'] }, "&&Next Editor"), 'workbench.action.nextEditor'); - const previousEditor = this.createMenuItem(nls.localize({ key: 'miPreviousEditor', comment: ['&& denotes a mnemonic'] }, "&&Previous Editor"), 'workbench.action.previousEditor'); - const nextEditorInGroup = this.createMenuItem(nls.localize({ key: 'miNextEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Used Editor in Group"), 'workbench.action.openNextRecentlyUsedEditorInGroup'); - const previousEditorInGroup = this.createMenuItem(nls.localize({ key: 'miPreviousEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Used Editor in Group"), 'workbench.action.openPreviousRecentlyUsedEditorInGroup'); - - [ - nextEditor, - previousEditor, - __separator__(), - nextEditorInGroup, - previousEditorInGroup - ].forEach(item => switchEditorMenu.append(item)); - - const switchEditor = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miSwitchEditor', comment: ['&& denotes a mnemonic'] }, "Switch &&Editor")), submenu: switchEditorMenu, enabled: true }); - - const switchGroupMenu = new Menu(); - - const focusFirstGroup = this.createMenuItem(nls.localize({ key: 'miFocusFirstGroup', comment: ['&& denotes a mnemonic'] }, "Group &&1"), 'workbench.action.focusFirstEditorGroup'); - const focusSecondGroup = this.createMenuItem(nls.localize({ key: 'miFocusSecondGroup', comment: ['&& denotes a mnemonic'] }, "Group &&2"), 'workbench.action.focusSecondEditorGroup'); - const focusThirdGroup = this.createMenuItem(nls.localize({ key: 'miFocusThirdGroup', comment: ['&& denotes a mnemonic'] }, "Group &&3"), 'workbench.action.focusThirdEditorGroup'); - const focusFourthGroup = this.createMenuItem(nls.localize({ key: 'miFocusFourthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&4"), 'workbench.action.focusFourthEditorGroup'); - const focusFifthGroup = this.createMenuItem(nls.localize({ key: 'miFocusFifthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&5"), 'workbench.action.focusFifthEditorGroup'); - const nextGroup = this.createMenuItem(nls.localize({ key: 'miNextGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Group"), 'workbench.action.focusNextGroup'); - const previousGroup = this.createMenuItem(nls.localize({ key: 'miPreviousGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Group"), 'workbench.action.focusPreviousGroup'); - - const focusLeftGroup = this.createMenuItem(nls.localize({ key: 'miFocusLeftGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Left"), 'workbench.action.focusLeftGroup'); - const focusRightGroup = this.createMenuItem(nls.localize({ key: 'miFocusRightGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Right"), 'workbench.action.focusRightGroup'); - const focusAboveGroup = this.createMenuItem(nls.localize({ key: 'miFocusAboveGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Above"), 'workbench.action.focusAboveGroup'); - const focusBelowGroup = this.createMenuItem(nls.localize({ key: 'miFocusBelowGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Below"), 'workbench.action.focusBelowGroup'); - - [ - focusFirstGroup, - focusSecondGroup, - focusThirdGroup, - focusFourthGroup, - focusFifthGroup, - __separator__(), - nextGroup, - previousGroup, - __separator__(), - focusAboveGroup, - focusBelowGroup, - focusLeftGroup, - focusRightGroup - ].forEach(item => switchGroupMenu.append(item)); - - const switchGroup = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miSwitchGroup', comment: ['&& denotes a mnemonic'] }, "Switch &&Group")), submenu: switchGroupMenu, enabled: true }); - - const gotoFile = this.createMenuItem(nls.localize({ key: 'miGotoFile', comment: ['&& denotes a mnemonic'] }, "Go to &&File..."), 'workbench.action.quickOpen'); - const gotoSymbolInFile = this.createMenuItem(nls.localize({ key: 'miGotoSymbolInFile', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in File..."), 'workbench.action.gotoSymbol'); - const gotoSymbolInWorkspace = this.createMenuItem(nls.localize({ key: 'miGotoSymbolInWorkspace', comment: ['&& denotes a mnemonic'] }, "Go to Symbol in &&Workspace..."), 'workbench.action.showAllSymbols'); - const gotoDefinition = this.createMenuItem(nls.localize({ key: 'miGotoDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Definition"), 'editor.action.goToDeclaration'); - const gotoTypeDefinition = this.createMenuItem(nls.localize({ key: 'miGotoTypeDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Type Definition"), 'editor.action.goToTypeDefinition'); - const goToImplementation = this.createMenuItem(nls.localize({ key: 'miGotoImplementation', comment: ['&& denotes a mnemonic'] }, "Go to &&Implementation"), 'editor.action.goToImplementation'); - const gotoLine = this.createMenuItem(nls.localize({ key: 'miGotoLine', comment: ['&& denotes a mnemonic'] }, "Go to &&Line..."), 'workbench.action.gotoLine'); - - [ - back, - forward, - __separator__(), - switchEditor, - switchGroup, - __separator__(), - gotoFile, - gotoSymbolInFile, - gotoSymbolInWorkspace, - gotoDefinition, - gotoTypeDefinition, - goToImplementation, - gotoLine - ].forEach(item => gotoMenu.append(item)); - } - - private setTerminalMenu(terminalMenu: Electron.Menu): void { - const newTerminal = this.createMenuItem(nls.localize({ key: 'miNewTerminal', comment: ['&& denotes a mnemonic'] }, "&&New Terminal"), 'workbench.action.terminal.new'); - const splitTerminal = this.createMenuItem(nls.localize({ key: 'miSplitTerminal', comment: ['&& denotes a mnemonic'] }, "&&Split Terminal"), 'workbench.action.terminal.split'); - - const runActiveFile = this.createMenuItem(nls.localize({ key: 'miRunActiveFile', comment: ['&& denotes a mnemonic'] }, "Run &&Active File"), 'workbench.action.terminal.runActiveFile'); - const runSelectedText = this.createMenuItem(nls.localize({ key: 'miRunSelectedText', comment: ['&& denotes a mnemonic'] }, "Run &&Selected Text"), 'workbench.action.terminal.runSelectedText'); - - const runTask = this.createMenuItem(nls.localize({ key: 'miRunTask', comment: ['&& denotes a mnemonic'] }, "&&Run Task..."), 'workbench.action.tasks.runTask'); - const buildTask = this.createMenuItem(nls.localize({ key: 'miBuildTask', comment: ['&& denotes a mnemonic'] }, "Run &&Build Task..."), 'workbench.action.tasks.build'); - const showTasks = this.createMenuItem(nls.localize({ key: 'miRunningTask', comment: ['&& denotes a mnemonic'] }, "Show Runnin&&g Tasks..."), 'workbench.action.tasks.showTasks'); - const restartTask = this.createMenuItem(nls.localize({ key: 'miRestartTask', comment: ['&& denotes a mnemonic'] }, "R&&estart Running Task..."), 'workbench.action.tasks.restartTask'); - const terminateTask = this.createMenuItem(nls.localize({ key: 'miTerminateTask', comment: ['&& denotes a mnemonic'] }, "&&Terminate Task..."), 'workbench.action.tasks.terminate'); - const configureTask = this.createMenuItem(nls.localize({ key: 'miConfigureTask', comment: ['&& denotes a mnemonic'] }, "&&Configure Tasks..."), 'workbench.action.tasks.configureTaskRunner'); - const configureBuildTask = this.createMenuItem(nls.localize({ key: 'miConfigureBuildTask', comment: ['&& denotes a mnemonic'] }, "Configure De&&fault Build Task..."), 'workbench.action.tasks.configureDefaultBuildTask'); - - const menuItems: MenuItem[] = [ - newTerminal, - splitTerminal, - __separator__(), - runTask, - buildTask, - runActiveFile, - runSelectedText, - __separator__(), - terminateTask, - restartTask, - showTasks, - __separator__(), - configureTask, - configureBuildTask - ]; - - menuItems.forEach(item => terminalMenu.append(item)); - } - - private setDebugMenu(debugMenu: Electron.Menu): void { - const start = this.createMenuItem(nls.localize({ key: 'miStartDebugging', comment: ['&& denotes a mnemonic'] }, "&&Start Debugging"), 'workbench.action.debug.start'); - const startWithoutDebugging = this.createMenuItem(nls.localize({ key: 'miStartWithoutDebugging', comment: ['&& denotes a mnemonic'] }, "Start &&Without Debugging"), 'workbench.action.debug.run'); - const stop = this.createMenuItem(nls.localize({ key: 'miStopDebugging', comment: ['&& denotes a mnemonic'] }, "&&Stop Debugging"), 'workbench.action.debug.stop'); - const restart = this.createMenuItem(nls.localize({ key: 'miRestart Debugging', comment: ['&& denotes a mnemonic'] }, "&&Restart Debugging"), 'workbench.action.debug.restart'); - - const openConfigurations = this.createMenuItem(nls.localize({ key: 'miOpenConfigurations', comment: ['&& denotes a mnemonic'] }, "Open &&Configurations"), 'workbench.action.debug.configure'); - const addConfiguration = this.createMenuItem(nls.localize({ key: 'miAddConfiguration', comment: ['&& denotes a mnemonic'] }, "A&&dd Configuration..."), 'debug.addConfiguration'); - - const stepOver = this.createMenuItem(nls.localize({ key: 'miStepOver', comment: ['&& denotes a mnemonic'] }, "Step &&Over"), 'workbench.action.debug.stepOver'); - const stepInto = this.createMenuItem(nls.localize({ key: 'miStepInto', comment: ['&& denotes a mnemonic'] }, "Step &&Into"), 'workbench.action.debug.stepInto'); - const stepOut = this.createMenuItem(nls.localize({ key: 'miStepOut', comment: ['&& denotes a mnemonic'] }, "Step O&&ut"), 'workbench.action.debug.stepOut'); - const continueAction = this.createMenuItem(nls.localize({ key: 'miContinue', comment: ['&& denotes a mnemonic'] }, "&&Continue"), 'workbench.action.debug.continue'); - - const toggleBreakpoint = this.createMenuItem(nls.localize({ key: 'miToggleBreakpoint', comment: ['&& denotes a mnemonic'] }, "Toggle &&Breakpoint"), 'editor.debug.action.toggleBreakpoint'); - const breakpointsMenu = new Menu(); - breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miConditionalBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Conditional Breakpoint..."), 'editor.debug.action.conditionalBreakpoint')); - breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miInlineBreakpoint', comment: ['&& denotes a mnemonic'] }, "Inline Breakp&&oint"), 'editor.debug.action.toggleInlineBreakpoint')); - breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miFunctionBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&Function Breakpoint..."), 'workbench.debug.viewlet.action.addFunctionBreakpointAction')); - breakpointsMenu.append(this.createMenuItem(nls.localize({ key: 'miLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Logpoint..."), 'editor.debug.action.toggleLogPoint')); - const newBreakpoints = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miNewBreakpoint', comment: ['&& denotes a mnemonic'] }, "&&New Breakpoint")), submenu: breakpointsMenu }); - const enableAllBreakpoints = this.createMenuItem(nls.localize({ key: 'miEnableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "&&Enable All Breakpoints"), 'workbench.debug.viewlet.action.enableAllBreakpoints'); - const disableAllBreakpoints = this.createMenuItem(nls.localize({ key: 'miDisableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Disable A&&ll Breakpoints"), 'workbench.debug.viewlet.action.disableAllBreakpoints'); - const removeAllBreakpoints = this.createMenuItem(nls.localize({ key: 'miRemoveAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Remove &&All Breakpoints"), 'workbench.debug.viewlet.action.removeAllBreakpoints'); - - const installAdditionalDebuggers = this.createMenuItem(nls.localize({ key: 'miInstallAdditionalDebuggers', comment: ['&& denotes a mnemonic'] }, "&&Install Additional Debuggers..."), 'debug.installAdditionalDebuggers'); - [ - start, - startWithoutDebugging, - stop, - restart, - __separator__(), - openConfigurations, - addConfiguration, - __separator__(), - stepOver, - stepInto, - stepOut, - continueAction, - __separator__(), - toggleBreakpoint, - newBreakpoints, - enableAllBreakpoints, - disableAllBreakpoints, - removeAllBreakpoints, - __separator__(), - installAdditionalDebuggers - ].forEach(item => debugMenu.append(item)); - } - - private setMacWindowMenu(macWindowMenu: Electron.Menu): void { - const minimize = new MenuItem({ label: nls.localize('mMinimize', "Minimize"), role: 'minimize', accelerator: 'Command+M', enabled: this.windowsMainService.getWindowCount() > 0 }); - const zoom = new MenuItem({ label: nls.localize('mZoom', "Zoom"), role: 'zoom', enabled: this.windowsMainService.getWindowCount() > 0 }); - const bringAllToFront = new MenuItem({ label: nls.localize('mBringToFront', "Bring All to Front"), role: 'front', enabled: this.windowsMainService.getWindowCount() > 0 }); - const switchWindow = this.createMenuItem(nls.localize({ key: 'miSwitchWindow', comment: ['&& denotes a mnemonic'] }, "Switch &&Window..."), 'workbench.action.switchWindow'); - - const nativeTabMenuItems: Electron.MenuItem[] = []; - if (this.currentEnableNativeTabs) { - nativeTabMenuItems.push(__separator__()); - - nativeTabMenuItems.push(this.createMenuItem(nls.localize('mNewTab', "New Tab"), 'workbench.action.newWindowTab')); - - nativeTabMenuItems.push(this.createRoleMenuItem(nls.localize('mShowPreviousTab', "Show Previous Tab"), 'workbench.action.showPreviousWindowTab', 'selectPreviousTab')); - nativeTabMenuItems.push(this.createRoleMenuItem(nls.localize('mShowNextTab', "Show Next Tab"), 'workbench.action.showNextWindowTab', 'selectNextTab')); - nativeTabMenuItems.push(this.createRoleMenuItem(nls.localize('mMoveTabToNewWindow', "Move Tab to New Window"), 'workbench.action.moveWindowTabToNewWindow', 'moveTabToNewWindow')); - nativeTabMenuItems.push(this.createRoleMenuItem(nls.localize('mMergeAllWindows', "Merge All Windows"), 'workbench.action.mergeAllWindowTabs', 'mergeAllWindows')); - } - - [ - minimize, - zoom, - switchWindow, - ...nativeTabMenuItems, - __separator__(), - bringAllToFront - ].forEach(item => macWindowMenu.append(item)); - } - - private toggleDevTools(): void { - const w = this.windowsMainService.getFocusedWindow(); - if (w && w.win) { - const contents = w.win.webContents; - if (isMacintosh && w.hasHiddenTitleBarStyle() && !w.win.isFullScreen() && !contents.isDevToolsOpened()) { - contents.openDevTools({ mode: 'undocked' }); // due to https://github.com/electron/electron/issues/3647 - } else { - contents.toggleDevTools(); - } - } - } - - private setHelpMenu(helpMenu: Electron.Menu): void { - const toggleDevToolsItem = new MenuItem(this.likeAction('workbench.action.toggleDevTools', { - label: this.mnemonicLabel(nls.localize({ key: 'miToggleDevTools', comment: ['&& denotes a mnemonic'] }, "&&Toggle Developer Tools")), - click: () => this.toggleDevTools(), - enabled: (this.windowsMainService.getWindowCount() > 0) - })); - - const showAccessibilityOptions = new MenuItem(this.likeAction('accessibilityOptions', { - label: this.mnemonicLabel(nls.localize({ key: 'miAccessibilityOptions', comment: ['&& denotes a mnemonic'] }, "Accessibility &&Options")), - accelerator: null, - click: () => { - this.openAccessibilityOptions(); - } - }, false)); - - const openProcessExplorer = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")), click: () => this.runActionInRenderer('workbench.action.openProcessExplorer') }); - - let reportIssuesItem: Electron.MenuItem = null; - if (product.reportIssueUrl) { - 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.openIssueReporter'); - } else { - reportIssuesItem = new MenuItem({ label: this.mnemonicLabel(label), click: () => this.openUrl(product.reportIssueUrl, 'openReportIssues') }); - } - } - - const keyboardShortcutsUrl = isLinux ? product.keyboardShortcutsUrlLinux : isMacintosh ? product.keyboardShortcutsUrlMac : product.keyboardShortcutsUrlWin; - arrays.coalesce([ - new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miWelcome', comment: ['&& denotes a mnemonic'] }, "&&Welcome")), click: () => this.runActionInRenderer('workbench.action.showWelcomePage'), enabled: (this.windowsMainService.getWindowCount() > 0) }), - new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miInteractivePlayground', comment: ['&& denotes a mnemonic'] }, "&&Interactive Playground")), click: () => this.runActionInRenderer('workbench.action.showInteractivePlayground'), enabled: (this.windowsMainService.getWindowCount() > 0) }), - product.documentationUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation")), click: () => this.runActionInRenderer('workbench.action.openDocumentationUrl'), enabled: (this.windowsMainService.getWindowCount() > 0) }) : null, - product.releaseNotesUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "&&Release Notes")), click: () => this.runActionInRenderer('update.showCurrentReleaseNotes'), enabled: (this.windowsMainService.getWindowCount() > 0) }) : null, - __separator__(), - keyboardShortcutsUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference")), click: () => this.runActionInRenderer('workbench.action.keybindingsReference'), enabled: (this.windowsMainService.getWindowCount() > 0) }) : null, - product.introductoryVideosUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miIntroductoryVideos', comment: ['&& denotes a mnemonic'] }, "Introductory &&Videos")), click: () => this.runActionInRenderer('workbench.action.openIntroductoryVideosUrl'), enabled: (this.windowsMainService.getWindowCount() > 0) }) : null, - product.tipsAndTricksUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "&&Tips and Tricks")), click: () => this.runActionInRenderer('workbench.action.openTipsAndTricksUrl'), enabled: (this.windowsMainService.getWindowCount() > 0) }) : null, - (product.introductoryVideosUrl || keyboardShortcutsUrl) ? __separator__() : null, - product.twitterUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join us on Twitter")), click: () => this.openUrl(product.twitterUrl, 'openTwitterUrl') }) : null, - product.requestFeatureUrl ? new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests")), click: () => this.openUrl(product.requestFeatureUrl, 'openUserVoiceUrl') }) : null, - reportIssuesItem, - (product.twitterUrl || product.requestFeatureUrl || product.reportIssueUrl) ? __separator__() : null, - product.licenseUrl ? new MenuItem({ - label: this.mnemonicLabel(nls.localize({ key: 'miLicense', comment: ['&& denotes a mnemonic'] }, "View &&License")), click: () => { - if (language) { - const queryArgChar = product.licenseUrl.indexOf('?') > 0 ? '&' : '?'; - this.openUrl(`${product.licenseUrl}${queryArgChar}lang=${language}`, 'openLicenseUrl'); - } else { - this.openUrl(product.licenseUrl, 'openLicenseUrl'); - } - } - }) : null, - product.privacyStatementUrl ? new MenuItem({ - label: this.mnemonicLabel(nls.localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "&&Privacy Statement")), click: () => { - if (language) { - const queryArgChar = product.licenseUrl.indexOf('?') > 0 ? '&' : '?'; - this.openUrl(`${product.privacyStatementUrl}${queryArgChar}lang=${language}`, 'openPrivacyStatement'); - } else { - this.openUrl(product.privacyStatementUrl, 'openPrivacyStatement'); - } - } - }) : null, - (product.licenseUrl || product.privacyStatementUrl) ? __separator__() : null, - toggleDevToolsItem, - openProcessExplorer, - isWindows && product.quality !== 'stable' ? showAccessibilityOptions : null, - ]).forEach(item => helpMenu.append(item)); - - if (!isMacintosh) { - const updateMenuItems = this.getUpdateMenuItems(); - if (updateMenuItems.length) { - helpMenu.append(__separator__()); - updateMenuItems.forEach(i => helpMenu.append(i)); - } - - helpMenu.append(__separator__()); - helpMenu.append(new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miAbout', comment: ['&& denotes a mnemonic'] }, "&&About")), click: () => this.windowsService.openAboutDialog() })); - } - } - - private openAccessibilityOptions(): void { - const win = new BrowserWindow({ - alwaysOnTop: true, - skipTaskbar: true, - resizable: false, - width: 450, - height: 300, - show: true, - title: nls.localize('accessibilityOptionsWindowTitle', "Accessibility Options"), - webPreferences: { - disableBlinkFeatures: 'Auxclick' - } - }); - - win.setMenuBarVisibility(false); - - win.loadURL('chrome://accessibility'); - } - - private getUpdateMenuItems(): Electron.MenuItem[] { - const state = this.updateService.state; - - switch (state.type) { - case StateType.Uninitialized: - return []; - - case StateType.Idle: - return [new MenuItem({ - label: this.mnemonicLabel(nls.localize('miCheckForUpdates', "Check for &&Updates...")), click: () => setTimeout(() => { - this.reportMenuActionTelemetry('CheckForUpdate'); - - const focusedWindow = this.windowsMainService.getFocusedWindow(); - const context = focusedWindow ? { windowId: focusedWindow.id } : null; - this.updateService.checkForUpdates(context); - }, 0) - })]; - - case StateType.CheckingForUpdates: - return [new MenuItem({ label: nls.localize('miCheckingForUpdates', "Checking For Updates..."), enabled: false })]; - - case StateType.AvailableForDownload: - return [new MenuItem({ - label: this.mnemonicLabel(nls.localize('miDownloadUpdate', "D&&ownload 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: this.mnemonicLabel(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: this.mnemonicLabel(nls.localize('miRestartToUpdate', "Restart to &&Update...")), click: () => { - this.reportMenuActionTelemetry('RestartToUpdate'); - this.updateService.quitAndInstall(); - } - })]; - } - } - - private createMenuItem(label: string, commandId: string | string[], enabled?: boolean, checked?: boolean): Electron.MenuItem; - private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): Electron.MenuItem; - private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): Electron.MenuItem { - const label = this.mnemonicLabel(arg1); - - const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: Electron.MenuItem, win: Electron.BrowserWindow, event: Electron.Event) => { - let commandId = arg2; - if (Array.isArray(arg2)) { - commandId = this.isOptionClick(event) ? arg2[1] : arg2[0]; // support alternative action if we got multiple action Ids and the option key was pressed while invoking - } - - this.runActionInRenderer(commandId); - }; - - const enabled = typeof arg3 === 'boolean' ? arg3 : this.windowsMainService.getWindowCount() > 0; - const checked = typeof arg4 === 'boolean' ? arg4 : false; - - const options: Electron.MenuItemConstructorOptions = { - label, - click, - enabled - }; - - if (checked) { - options['type'] = 'checkbox'; - options['checked'] = checked; - } - - let commandId: string; - if (typeof arg2 === 'string') { - commandId = arg2; - } else if (Array.isArray(arg2)) { - commandId = arg2[0]; - } - - return new MenuItem(this.withKeybinding(commandId, options)); - } - - private createContextAwareMenuItem(label: string, commandId: string, clickHandler: IMenuItemClickHandler): Electron.MenuItem { - return new MenuItem(this.withKeybinding(commandId, { - label: this.mnemonicLabel(label), - enabled: this.windowsMainService.getWindowCount() > 0, - click: () => { - - // No Active Window - const activeWindow = this.windowsMainService.getFocusedWindow(); - if (!activeWindow) { - return clickHandler.inNoWindow(); - } - - // DevTools focused - if (activeWindow.win.webContents.isDevToolsFocused()) { - return clickHandler.inDevTools(activeWindow.win.webContents.devToolsWebContents); - } - - // Finally execute command in Window - this.runActionInRenderer(commandId); - } - })); - } - - private runActionInRenderer(id: string): void { - // We make sure to not run actions when the window has no focus, this helps - // for https://github.com/Microsoft/vscode/issues/25907 and specifically for - // https://github.com/Microsoft/vscode/issues/11928 - const activeWindow = this.windowsMainService.getFocusedWindow(); - if (activeWindow) { - this.windowsMainService.sendToFocused('vscode:runAction', { id, from: 'menu' } as IRunActionInWindowRequest); - } - } - - private withKeybinding(commandId: string, options: Electron.MenuItemConstructorOptions): Electron.MenuItemConstructorOptions { - const binding = this.keybindingsResolver.getKeybinding(commandId); - - // Apply binding if there is one - if (binding && binding.label) { - - // if the binding is native, we can just apply it - if (binding.isNative) { - options.accelerator = binding.label; - } - - // the keybinding is not native so we cannot show it as part of the accelerator of - // the menu item. we fallback to a different strategy so that we always display it - else { - const bindingIndex = options.label.indexOf('['); - if (bindingIndex >= 0) { - options.label = `${options.label.substr(0, bindingIndex)} [${binding.label}]`; - } else { - options.label = `${options.label} [${binding.label}]`; - } - } - } - - // Unset bindings if there is none - else { - options.accelerator = void 0; - } - - return options; - } - - private likeAction(commandId: string, options: Electron.MenuItemConstructorOptions, setAccelerator = !options.accelerator): Electron.MenuItemConstructorOptions { - if (setAccelerator) { - options = this.withKeybinding(commandId, options); - } - - const originalClick = options.click; - options.click = (item, window, event) => { - this.reportMenuActionTelemetry(commandId); - if (originalClick) { - originalClick(item, window, event); - } - }; - - return options; - } - - private openUrl(url: string, id: string): void { - shell.openExternal(url); - this.reportMenuActionTelemetry(id); - } - - private reportMenuActionTelemetry(id: string): void { - /* __GDPR__ - "workbenchActionExecuted" : { - "id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "from": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('workbenchActionExecuted', { id, from: telemetryFrom }); - } - - private mnemonicLabel(label: string): string { - return baseMnemonicLabel(label, !this.currentEnableMenuBarMnemonics); - } -} - -function __separator__(): Electron.MenuItem { - return new MenuItem({ type: 'separator' }); -} diff --git a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts index 2b6a07650d2..05e59918069 100644 --- a/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts +++ b/src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts @@ -138,7 +138,7 @@ export class ViewCursor { width = dom.computeScreenAwareSize(1); } let left = visibleRange.left; - if (width >= 2) { + if (width >= 2 && left >= 1) { // try to center cursor left -= 1; } diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index dc5f8d54f0c..67bc8a7d23c 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -287,9 +287,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE action.label, action.alias, action.precondition, - (): void | TPromise => { + (): Promise => { return this._instantiationService.invokeFunction((accessor) => { - return action.runEditorCommand(accessor, this, null); + return Promise.resolve(action.runEditorCommand(accessor, this, null)); }); }, this._contextKeyService diff --git a/src/vs/editor/common/editorAction.ts b/src/vs/editor/common/editorAction.ts index b0f8fcbe71a..ce29a961c5d 100644 --- a/src/vs/editor/common/editorAction.ts +++ b/src/vs/editor/common/editorAction.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TPromise } from 'vs/base/common/winjs.base'; import { IEditorAction } from 'vs/editor/common/editorCommon'; import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -14,7 +13,7 @@ export class InternalEditorAction implements IEditorAction { public readonly alias: string; private readonly _precondition: ContextKeyExpr; - private readonly _run: () => void | TPromise; + private readonly _run: () => Promise; private readonly _contextKeyService: IContextKeyService; constructor( @@ -22,7 +21,7 @@ export class InternalEditorAction implements IEditorAction { label: string, alias: string, precondition: ContextKeyExpr, - run: () => void, + run: () => Promise, contextKeyService: IContextKeyService ) { this.id = id; @@ -37,12 +36,12 @@ export class InternalEditorAction implements IEditorAction { return this._contextKeyService.contextMatchesRules(this._precondition); } - public run(): TPromise { + public run(): Promise { if (!this.isSupported()) { - return TPromise.as(void 0); + return Promise.resolve(void 0); } const r = this._run(); - return r ? r : TPromise.as(void 0); + return r ? r : Promise.resolve(void 0); } } diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 5f940755d70..78829d1fe2b 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -5,7 +5,6 @@ import { IMarkdownString } from 'vs/base/common/htmlContent'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; 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'; @@ -185,7 +184,7 @@ export interface IEditorAction { readonly label: string; readonly alias: string; isSupported(): boolean; - run(): TPromise; + run(): Promise; } export type IEditorModel = ITextModel | IDiffEditorModel; diff --git a/src/vs/editor/common/model/indentationGuesser.ts b/src/vs/editor/common/model/indentationGuesser.ts index f08277d7be0..18b724df828 100644 --- a/src/vs/editor/common/model/indentationGuesser.ts +++ b/src/vs/editor/common/model/indentationGuesser.ts @@ -111,8 +111,8 @@ export function guessIndentation(source: ITextBuffer, defaultTabSize: number, de let previousLineText = ''; // content of latest line that contained non-whitespace chars let previousLineIndentation = 0; // index at which latest line contained the first non-whitespace char - const ALLOWED_TAB_SIZE_GUESSES = [2, 4, 6, 8]; // limit guesses for `tabSize` to 2, 4, 6 or 8. - const MAX_ALLOWED_TAB_SIZE_GUESS = 8; // max(2,4,6,8) = 8 + const ALLOWED_TAB_SIZE_GUESSES = [2, 4, 6, 8, 3, 5, 7]; // prefer even guesses for `tabSize`, limit to [2, 8]. + const MAX_ALLOWED_TAB_SIZE_GUESS = 8; // max(ALLOWED_TAB_SIZE_GUESSES) = 8 let spacesDiffCount = [0, 0, 0, 0, 0, 0, 0, 0, 0]; // `tabSize` scores let tmp = new SpacesDiffResult(); diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index 138c813fefc..c75b008b120 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -26,34 +26,6 @@ export class SearchParams { this.wordSeparators = wordSeparators; } - private static _isMultilineRegexSource(searchString: string): boolean { - if (!searchString || searchString.length === 0) { - return false; - } - - for (let i = 0, len = searchString.length; i < len; i++) { - const chCode = searchString.charCodeAt(i); - - if (chCode === CharCode.Backslash) { - - // move to next char - i++; - - if (i >= len) { - // string ends with a \ - break; - } - - const nextChCode = searchString.charCodeAt(i); - if (nextChCode === CharCode.n || nextChCode === CharCode.r || nextChCode === CharCode.W) { - return true; - } - } - } - - return false; - } - public parseSearchRequest(): SearchData { if (this.searchString === '') { return null; @@ -62,7 +34,7 @@ export class SearchParams { // Try to create a RegExp out of the params let multiline: boolean; if (this.isRegex) { - multiline = SearchParams._isMultilineRegexSource(this.searchString); + multiline = isMultilineRegexSource(this.searchString); } else { multiline = (this.searchString.indexOf('\n') >= 0); } @@ -93,6 +65,34 @@ export class SearchParams { } } +export function isMultilineRegexSource(searchString: string): boolean { + if (!searchString || searchString.length === 0) { + return false; + } + + for (let i = 0, len = searchString.length; i < len; i++) { + const chCode = searchString.charCodeAt(i); + + if (chCode === CharCode.Backslash) { + + // move to next char + i++; + + if (i >= len) { + // string ends with a \ + break; + } + + const nextChCode = searchString.charCodeAt(i); + if (nextChCode === CharCode.n || nextChCode === CharCode.r || nextChCode === CharCode.W) { + return true; + } + } + } + + return false; +} + export class SearchData { /** diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 4f7ec3433c3..c38a201b8b8 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IRequestHandler } from 'vs/base/common/worker/simpleWorker'; import { Range, IRange } from 'vs/editor/common/core/range'; @@ -336,7 +335,7 @@ export abstract class BaseEditorSimpleWorker { // ---- BEGIN diff -------------------------------------------------------------------------- - public computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): TPromise { + public computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { let original = this._getModel(originalUrl); let modified = this._getModel(modifiedUrl); if (!original || !modified) { @@ -351,10 +350,10 @@ export abstract class BaseEditorSimpleWorker { shouldIgnoreTrimWhitespace: ignoreTrimWhitespace, shouldMakePrettyDiff: true }); - return TPromise.as(diffComputer.computeDiff()); + return Promise.resolve(diffComputer.computeDiff()); } - public computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): TPromise { + public computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { let original = this._getModel(originalUrl); let modified = this._getModel(modifiedUrl); if (!original || !modified) { @@ -369,7 +368,7 @@ export abstract class BaseEditorSimpleWorker { shouldIgnoreTrimWhitespace: ignoreTrimWhitespace, shouldMakePrettyDiff: true }); - return TPromise.as(diffComputer.computeDiff()); + return Promise.resolve(diffComputer.computeDiff()); } // ---- END diff -------------------------------------------------------------------------- @@ -379,10 +378,10 @@ export abstract class BaseEditorSimpleWorker { private static readonly _diffLimit = 10000; - public computeMoreMinimalEdits(modelUrl: string, edits: TextEdit[]): TPromise { + public computeMoreMinimalEdits(modelUrl: string, edits: TextEdit[]): Promise { const model = this._getModel(modelUrl); if (!model) { - return TPromise.as(edits); + return Promise.resolve(edits); } const result: TextEdit[] = []; @@ -437,25 +436,25 @@ export abstract class BaseEditorSimpleWorker { result.push({ eol: lastEol, text: undefined, range: undefined }); } - return TPromise.as(result); + return Promise.resolve(result); } // ---- END minimal edits --------------------------------------------------------------- - public computeLinks(modelUrl: string): TPromise { + public computeLinks(modelUrl: string): Promise { let model = this._getModel(modelUrl); if (!model) { return null; } - return TPromise.as(computeLinks(model)); + return Promise.resolve(computeLinks(model)); } // ---- BEGIN suggest -------------------------------------------------------------------------- private static readonly _suggestionsLimit = 10000; - public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): TPromise { + public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise { const model = this._getModel(modelUrl); if (model) { const suggestions: CompletionItem[] = []; @@ -488,7 +487,7 @@ export abstract class BaseEditorSimpleWorker { }); } - return TPromise.as({ suggestions }); + return Promise.resolve({ suggestions }); } return undefined; } @@ -529,7 +528,7 @@ export abstract class BaseEditorSimpleWorker { //#endregion - public navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): TPromise { + public navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise { let model = this._getModel(modelUrl); if (!model) { return null; @@ -555,12 +554,12 @@ export abstract class BaseEditorSimpleWorker { } let result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up); - return TPromise.as(result); + return Promise.resolve(result); } // ---- BEGIN foreign module support -------------------------------------------------------------------------- - public loadForeignModule(moduleId: string, createData: any): TPromise { + public loadForeignModule(moduleId: string, createData: any): Promise { let ctx: IWorkerContext = { getMirrorModels: (): IMirrorModel[] => { return this._getModels(); @@ -576,10 +575,10 @@ export abstract class BaseEditorSimpleWorker { methods.push(prop); } } - return TPromise.as(methods); + return Promise.resolve(methods); } // ESM-comment-begin - return new TPromise((c, e) => { + return new Promise((resolve, reject) => { require([moduleId], (foreignModule: { create: IForeignModuleFactory }) => { this._foreignModule = foreignModule.create(ctx, createData); @@ -590,27 +589,27 @@ export abstract class BaseEditorSimpleWorker { } } - c(methods); + resolve(methods); - }, e); + }, reject); }); // ESM-comment-end // ESM-uncomment-begin - // return TPromise.wrapError(new Error(`Unexpected usage`)); + // return Promise.reject(new Error(`Unexpected usage`)); // ESM-uncomment-end } // foreign method request - public fmr(method: string, args: any[]): TPromise { + public fmr(method: string, args: any[]): Promise { if (!this._foreignModule || typeof this._foreignModule[method] !== 'function') { - return TPromise.wrapError(new Error('Missing requestHandler or method: ' + method)); + return Promise.reject(new Error('Missing requestHandler or method: ' + method)); } try { - return TPromise.as(this._foreignModule[method].apply(this._foreignModule, args)); + return Promise.resolve(this._foreignModule[method].apply(this._foreignModule, args)); } catch (e) { - return TPromise.wrapError(e); + return Promise.reject(e); } } diff --git a/src/vs/editor/common/services/editorWorkerService.ts b/src/vs/editor/common/services/editorWorkerService.ts index 5d96d912bda..ff2fa9eb212 100644 --- a/src/vs/editor/common/services/editorWorkerService.ts +++ b/src/vs/editor/common/services/editorWorkerService.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IChange, ILineChange } from 'vs/editor/common/editorCommon'; import { IInplaceReplaceSupportResult, TextEdit } from 'vs/editor/common/modes'; @@ -17,16 +16,16 @@ export interface IEditorWorkerService { _serviceBrand: any; canComputeDiff(original: URI, modified: URI): boolean; - computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise; + computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; canComputeDirtyDiff(original: URI, modified: URI): boolean; - computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise; + computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; - computeMoreMinimalEdits(resource: URI, edits: TextEdit[]): TPromise; + computeMoreMinimalEdits(resource: URI, edits: TextEdit[]): Promise; canComputeWordRanges(resource: URI): boolean; - computeWordRanges(resource: URI, range: IRange): TPromise<{ [word: string]: IRange[] }>; + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }>; canNavigateValueSet(resource: URI): boolean; - navigateValueSet(resource: URI, range: IRange, up: boolean): TPromise; + navigateValueSet(resource: URI, range: IRange, up: boolean): Promise; } diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index 8b14e5e2412..db899de6fdb 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -6,7 +6,6 @@ import { IntervalTimer } from 'vs/base/common/async'; import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { SimpleWorkerClient, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker'; import { DefaultWorkerFactory } from 'vs/base/worker/defaultWorkerFactory'; import * as editorCommon from 'vs/editor/common/editorCommon'; @@ -60,7 +59,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker this._register(modes.LinkProviderRegistry.register('*', { provideLinks: (model, token) => { if (!canSyncModel(this._modelService, model.uri)) { - return TPromise.as([]); // File too large + return Promise.resolve([]); // File too large } return this._workerManager.withWorker().then(client => client.computeLinks(model.uri)); } @@ -76,7 +75,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, original) && canSyncModel(this._modelService, modified)); } - public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise { + public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._workerManager.withWorker().then(client => client.computeDiff(original, modified, ignoreTrimWhitespace)); } @@ -84,16 +83,16 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, original) && canSyncModel(this._modelService, modified)); } - public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise { + public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace)); } - public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): TPromise { + public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): Promise { if (!Array.isArray(edits) || edits.length === 0) { - return TPromise.as(edits); + return Promise.resolve(edits); } else { if (!canSyncModel(this._modelService, resource)) { - return TPromise.as(edits); // File too large + return Promise.resolve(edits); // File too large } return this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits)); } @@ -103,7 +102,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, resource)); } - public navigateValueSet(resource: URI, range: IRange, up: boolean): TPromise { + public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { return this._workerManager.withWorker().then(client => client.navigateValueSet(resource, range, up)); } @@ -111,7 +110,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return canSyncModel(this._modelService, resource); } - computeWordRanges(resource: URI, range: IRange): TPromise<{ [word: string]: IRange[] }> { + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }> { return this._workerManager.withWorker().then(client => client.computeWordRanges(resource, range)); } } @@ -132,7 +131,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { this._modelService = modelService; } - provideCompletionItems(model: ITextModel, position: Position): TPromise { + provideCompletionItems(model: ITextModel, position: Position): Promise { const { wordBasedSuggestions } = this._configurationService.getValue(model.uri, position, 'editor'); if (!wordBasedSuggestions) { return undefined; @@ -200,12 +199,12 @@ class WorkerManager extends Disposable { } } - public withWorker(): TPromise { + public withWorker(): Promise { this._lastWorkerUsedTime = (new Date()).getTime(); if (!this._editorWorkerClient) { this._editorWorkerClient = new EditorWorkerClient(this._modelService, 'editorWorkerService'); } - return TPromise.as(this._editorWorkerClient); + return Promise.resolve(this._editorWorkerClient); } } @@ -308,17 +307,17 @@ class EditorModelManager extends Disposable { } interface IWorkerClient { - getProxyObject(): TPromise; + getProxyObject(): Promise; dispose(): void; } class SynchronousWorkerClient implements IWorkerClient { private _instance: T; - private _proxyObj: TPromise; + private _proxyObj: Promise; constructor(instance: T) { this._instance = instance; - this._proxyObj = TPromise.as(this._instance); + this._proxyObj = Promise.resolve(this._instance); } public dispose(): void { @@ -327,7 +326,7 @@ class SynchronousWorkerClient implements IWorkerClient this._proxyObj = null; } - public getProxyObject(): TPromise { + public getProxyObject(): Promise { return this._proxyObj; } } @@ -362,7 +361,7 @@ export class EditorWorkerClient extends Disposable { return this._worker; } - protected _getProxy(): TPromise { + protected _getProxy(): Promise { return this._getOrCreateWorker().getProxyObject().then(null, (err) => { logOnceWebWorkerWarning(err); this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null)); @@ -377,38 +376,38 @@ export class EditorWorkerClient extends Disposable { return this._modelManager; } - protected _withSyncedResources(resources: URI[]): TPromise { + protected _withSyncedResources(resources: URI[]): Promise { return this._getProxy().then((proxy) => { this._getOrCreateModelManager(proxy).esureSyncedResources(resources); return proxy; }); } - public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise { + public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._withSyncedResources([original, modified]).then(proxy => { return proxy.computeDiff(original.toString(), modified.toString(), ignoreTrimWhitespace); }); } - public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): TPromise { + public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._withSyncedResources([original, modified]).then(proxy => { return proxy.computeDirtyDiff(original.toString(), modified.toString(), ignoreTrimWhitespace); }); } - public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): TPromise { + public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): Promise { return this._withSyncedResources([resource]).then(proxy => { return proxy.computeMoreMinimalEdits(resource.toString(), edits); }); } - public computeLinks(resource: URI): TPromise { + public computeLinks(resource: URI): Promise { return this._withSyncedResources([resource]).then(proxy => { return proxy.computeLinks(resource.toString()); }); } - public textualSuggest(resource: URI, position: IPosition): TPromise { + public textualSuggest(resource: URI, position: IPosition): Promise { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { @@ -421,7 +420,7 @@ export class EditorWorkerClient extends Disposable { }); } - computeWordRanges(resource: URI, range: IRange): TPromise<{ [word: string]: IRange[] }> { + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }> { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { @@ -434,7 +433,7 @@ export class EditorWorkerClient extends Disposable { }); } - public navigateValueSet(resource: URI, range: IRange, up: boolean): TPromise { + public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { diff --git a/src/vs/editor/common/services/webWorker.ts b/src/vs/editor/common/services/webWorker.ts index 9646331f279..f0c97ae56a4 100644 --- a/src/vs/editor/common/services/webWorker.ts +++ b/src/vs/editor/common/services/webWorker.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IModelService } from 'vs/editor/common/services/modelService'; import { EditorWorkerClient } from 'vs/editor/common/services/editorWorkerServiceImpl'; @@ -27,12 +26,12 @@ export interface MonacoWebWorker { /** * Get a proxy to the arbitrary loaded code. */ - getProxy(): TPromise; + getProxy(): Promise; /** * Synchronize (send) the models at `resources` to the web worker, * making them available in the monaco.worker.getMirrorModels(). */ - withSyncedResources(resources: URI[]): TPromise; + withSyncedResources(resources: URI[]): Promise; } export interface IWebWorkerOptions { @@ -55,7 +54,7 @@ class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWork private _foreignModuleId: string; private _foreignModuleCreateData: any; - private _foreignProxy: TPromise; + private _foreignProxy: Promise; constructor(modelService: IModelService, opts: IWebWorkerOptions) { super(modelService, opts.label); @@ -64,18 +63,18 @@ class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWork this._foreignProxy = null; } - private _getForeignProxy(): TPromise { + private _getForeignProxy(): Promise { if (!this._foreignProxy) { this._foreignProxy = this._getProxy().then((proxy) => { return proxy.loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData).then((foreignMethods) => { this._foreignModuleId = null; this._foreignModuleCreateData = null; - let proxyMethodRequest = (method: string, args: any[]): TPromise => { + let proxyMethodRequest = (method: string, args: any[]): Promise => { return proxy.fmr(method, args); }; - let createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => TPromise): Function => { + let createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise): Function => { return function () { let args = Array.prototype.slice.call(arguments, 0); return proxyMethodRequest(method, args); @@ -94,11 +93,11 @@ class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWork return this._foreignProxy; } - public getProxy(): TPromise { + public getProxy(): Promise { return this._getForeignProxy(); } - public withSyncedResources(resources: URI[]): TPromise { + public withSyncedResources(resources: URI[]): Promise { return this._withSyncedResources(resources).then(_ => this.getProxy()); } } diff --git a/src/vs/editor/contrib/find/findWidget.css b/src/vs/editor/contrib/find/findWidget.css index eb838937d58..faf3f7efe98 100644 --- a/src/vs/editor/contrib/find/findWidget.css +++ b/src/vs/editor/contrib/find/findWidget.css @@ -36,13 +36,7 @@ height: 34px; /* find input height */ overflow: hidden; line-height: 19px; - - -webkit-transition: top 200ms linear; - -o-transition: top 200ms linear; - -moz-transition: top 200ms linear; - -ms-transition: top 200ms linear; transition: top 200ms linear; - padding: 0 4px; } /* Find widget when replace is toggled on */ @@ -253,7 +247,7 @@ /* COLLAPSED (SMALLER THAN NARROW) */ .monaco-editor .find-widget.collapsed-find-widget { - max-width: 111px !important; + max-width: 170px !important; } .monaco-editor .find-widget.collapsed-find-widget .button.previous, diff --git a/src/vs/editor/contrib/find/simpleFindWidget.css b/src/vs/editor/contrib/find/simpleFindWidget.css index 9037b26a7fc..cbcf1f1fc8b 100644 --- a/src/vs/editor/contrib/find/simpleFindWidget.css +++ b/src/vs/editor/contrib/find/simpleFindWidget.css @@ -22,11 +22,6 @@ padding: 4px; align-items: center; pointer-events: all; - - -webkit-transition: top 200ms linear; - -o-transition: top 200ms linear; - -moz-transition: top 200ms linear; - -ms-transition: top 200ms linear; transition: top 200ms linear; } diff --git a/src/vs/editor/contrib/parameterHints/parameterHints.css b/src/vs/editor/contrib/parameterHints/parameterHints.css index c65b3e07e8d..625740080a7 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHints.css +++ b/src/vs/editor/contrib/parameterHints/parameterHints.css @@ -22,9 +22,6 @@ } .monaco-editor .parameter-hints-widget.visible { - -webkit-transition: left .05s ease-in-out; - -moz-transition: left .05s ease-in-out; - -o-transition: left .05s ease-in-out; transition: left .05s ease-in-out; } diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 0f873ea9bc3..74a5df0502c 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -284,7 +284,7 @@ export class SuggestController implements IEditorContribution { /* __GDPR__ "acceptSuggestion" : { "type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "multiline" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + "multiline" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } } */ service.publicLog('acceptSuggestion', { diff --git a/src/vs/editor/standalone/browser/colorizer.ts b/src/vs/editor/standalone/browser/colorizer.ts index a0c88e7e18f..4e79aaaed50 100644 --- a/src/vs/editor/standalone/browser/colorizer.ts +++ b/src/vs/editor/standalone/browser/colorizer.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { IDisposable } from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModel } from 'vs/editor/common/model'; import { ColorId, MetadataConsts, FontStyle, TokenizationRegistry, ITokenizationSupport } from 'vs/editor/common/modes'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -26,7 +25,7 @@ export interface IColorizerElementOptions extends IColorizerOptions { export class Colorizer { - public static colorizeElement(themeService: IStandaloneThemeService, modeService: IModeService, domNode: HTMLElement, options: IColorizerElementOptions): TPromise { + public static colorizeElement(themeService: IStandaloneThemeService, modeService: IModeService, domNode: HTMLElement, options: IColorizerElementOptions): Promise { options = options || {}; let theme = options.theme || 'vs'; let mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang'); @@ -45,7 +44,7 @@ export class Colorizer { return this.colorize(modeService, text, mimeType, options).then(render, (err) => console.error(err)); } - public static colorize(modeService: IModeService, text: string, mimeType: string, options: IColorizerOptions): TPromise { + public static colorize(modeService: IModeService, text: string, mimeType: string, options: IColorizerOptions): Promise { if (strings.startsWithUTF8BOM(text)) { text = text.substr(1); } @@ -62,10 +61,10 @@ export class Colorizer { let tokenizationSupport = TokenizationRegistry.get(language); if (tokenizationSupport) { - return TPromise.as(_colorize(lines, options.tabSize, tokenizationSupport)); + return Promise.resolve(_colorize(lines, options.tabSize, tokenizationSupport)); } - return new TPromise((resolve, reject) => { + return new Promise((resolve, reject) => { let listener: IDisposable = null; let timeout: TimeoutTimer = null; diff --git a/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts b/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts index b7928bcbab6..b3b30c1b95b 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickCommand.ts @@ -6,7 +6,6 @@ import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import { matchesFuzzy } from 'vs/base/common/filters'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IContext, IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IAutoFocus, Mode } from 'vs/base/parts/quickopen/common/quickOpen'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -55,7 +54,7 @@ export class EditorActionCommandEntry extends QuickOpenEntryGroup { this.editor.focus(); try { - let promise = this.action.run() || TPromise.as(null); + let promise = this.action.run() || Promise.resolve(); promise.then(null, onUnexpectedError); } catch (error) { onUnexpectedError(error); diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index c3babe9b43a..f81c9c3801b 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -7,7 +7,6 @@ import 'vs/css!./quickOutline'; import * as nls from 'vs/nls'; import { matchesFuzzy } from 'vs/base/common/filters'; import * as strings from 'vs/base/common/strings'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IContext, IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IAutoFocus, Mode } from 'vs/base/parts/quickopen/common/quickOpen'; import { ScrollType } from 'vs/editor/common/editorCommon'; @@ -129,7 +128,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { }); } - public run(accessor: ServicesAccessor, editor: ICodeEditor): TPromise { + public run(accessor: ServicesAccessor, editor: ICodeEditor): Thenable { let model = editor.getModel(); @@ -138,13 +137,13 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { } // Resolve outline - return TPromise.wrap(getDocumentSymbols(model, true, CancellationToken.None).then((result: DocumentSymbol[]) => { + return getDocumentSymbols(model, true, CancellationToken.None).then((result: DocumentSymbol[]) => { if (result.length === 0) { return; } this._run(editor, result); - })); + }); } private _run(editor: ICodeEditor, result: DocumentSymbol[]): void { diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index 8e69016587e..0b8eb55f9ab 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands'; @@ -72,7 +71,7 @@ export interface IActionDescriptor { * Method that will be executed when the action is triggered. * @param editor The editor instance is passed in as a convinience */ - run(editor: ICodeEditor): void | TPromise; + run(editor: ICodeEditor): void | Promise; } /** @@ -221,9 +220,8 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon ); const contextMenuGroupId = _descriptor.contextMenuGroupId || null; const contextMenuOrder = _descriptor.contextMenuOrder || 0; - const run = (): TPromise => { - const r = _descriptor.run(this); - return r ? r : TPromise.as(void 0); + const run = (): Promise => { + return Promise.resolve(_descriptor.run(this)); }; diff --git a/src/vs/editor/standalone/browser/standaloneEditor.ts b/src/vs/editor/standalone/browser/standaloneEditor.ts index 2aa953c0596..a85dd145bea 100644 --- a/src/vs/editor/standalone/browser/standaloneEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneEditor.ts @@ -240,14 +240,14 @@ export function createWebWorker(opts: IWebWorkerOptions): MonacoWebWorker /** * Colorize the contents of `domNode` using attribute `data-lang`. */ -export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): TPromise { +export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): Promise { return Colorizer.colorizeElement(StaticServices.standaloneThemeService.get(), StaticServices.modeService.get(), domNode, options); } /** * Colorize `text` using language `languageId`. */ -export function colorize(text: string, languageId: string, options: IColorizerOptions): TPromise { +export function colorize(text: string, languageId: string, options: IColorizerOptions): Promise { return Colorizer.colorize(StaticServices.modeService.get(), text, languageId, options); } diff --git a/src/vs/editor/test/common/model/textModel.test.ts b/src/vs/editor/test/common/model/textModel.test.ts index 9bb198e4b7d..935001a2737 100644 --- a/src/vs/editor/test/common/model/textModel.test.ts +++ b/src/vs/editor/test/common/model/textModel.test.ts @@ -313,7 +313,7 @@ suite('Editor Model - TextModel', () => { ' ', ' ', ], 'whitespace lines don\'t count'); - assertGuess(true, 4, [ + assertGuess(true, 3, [ 'x', ' x', ' x', @@ -326,8 +326,8 @@ suite('Editor Model - TextModel', () => { ' x', ' x', ' x', - ], 'odd number is not allowed: 6x3, 3x4'); - assertGuess(true, 4, [ + ], '6x3, 3x4'); + assertGuess(true, 5, [ 'x', ' x', ' x', @@ -340,8 +340,12 @@ suite('Editor Model - TextModel', () => { ' x', ' x', ' x', - ], 'odd number is not allowed: 6x5, 3x4'); - assertGuess(true, 4, [ + ], '6x5, 3x4'); + assertGuess(true, 7, [ + 'x', + ' x', + ' x', + ' x', 'x', ' x', ' x', @@ -350,11 +354,7 @@ suite('Editor Model - TextModel', () => { ' x', ' x', ' x', - 'x', - ' x', - ' x', - ' x', - ], 'odd number is not allowed: 6x7, 3x4'); + ], '6x7, 1x5, 2x4'); assertGuess(true, 2, [ 'x', ' x', @@ -506,7 +506,7 @@ suite('Editor Model - TextModel', () => { ' x', ' x', ], '6x4, 2x5, 4x8'); - assertGuess(true, undefined, [ + assertGuess(true, 3, [ 'x', ' x', ' x', diff --git a/src/vs/editor/test/common/model/textModelSearch.test.ts b/src/vs/editor/test/common/model/textModelSearch.test.ts index 54c98e67f8d..3c9ced8ebd1 100644 --- a/src/vs/editor/test/common/model/textModelSearch.test.ts +++ b/src/vs/editor/test/common/model/textModelSearch.test.ts @@ -7,7 +7,7 @@ import { Position } from 'vs/editor/common/core/position'; import { FindMatch, EndOfLineSequence } from 'vs/editor/common/model'; import { Range } from 'vs/editor/common/core/range'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { TextModelSearch, SearchParams, SearchData } from 'vs/editor/common/model/textModelSearch'; +import { TextModelSearch, SearchParams, SearchData, isMultilineRegexSource } from 'vs/editor/common/model/textModelSearch'; import { getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier'; import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper'; @@ -720,4 +720,17 @@ suite('TextModelSearch', () => { ] ); }); + + test('isMultilineRegexSource', () => { + assert(!isMultilineRegexSource('foo')); + assert(!isMultilineRegexSource('')); + assert(!isMultilineRegexSource('foo\\sbar')); + assert(!isMultilineRegexSource('\\\\notnewline')); + + assert(isMultilineRegexSource('foo\\nbar')); + assert(isMultilineRegexSource('foo\\nbar\\s')); + assert(isMultilineRegexSource('foo\\r\\n')); + assert(isMultilineRegexSource('\\n')); + assert(isMultilineRegexSource('foo\\W')); + }); }); diff --git a/src/vs/editor/test/common/modes/languageSelector.test.ts b/src/vs/editor/test/common/modes/languageSelector.test.ts index f56c0368c59..8d43170b22c 100644 --- a/src/vs/editor/test/common/modes/languageSelector.test.ts +++ b/src/vs/editor/test/common/modes/languageSelector.test.ts @@ -94,4 +94,14 @@ suite('LanguageSelector', function () { assert.equal(score({ language: 'javascript', scheme: 'file', hasAccessToAllModels: true }, doc.uri, doc.langId, false), 10); assert.equal(score(['fooLang', '*', { language: '*', hasAccessToAllModels: true }], doc.uri, doc.langId, false), 5); }); + + test('Document selector match - unexpected result value #60232', function () { + let selector = { + language: 'json', + scheme: 'file', + pattern: '**/*.interface.json' + }; + let value = score(selector, URI.parse('file:///C:/Users/zlhe/Desktop/test.interface.json'), 'json', true); + assert.equal(value, 10); + }); }); diff --git a/src/vs/loader.js b/src/vs/loader.js index 04a325a8874..4f44a01db19 100644 --- a/src/vs/loader.js +++ b/src/vs/loader.js @@ -19,10 +19,11 @@ *--------------------------------------------------------------------------------------------- *--------------------------------------------------------------------------------------------*/ var _amdLoaderGlobal = this; +var _commonjsGlobal = typeof global === 'object' ? global : {}; var AMDLoader; (function (AMDLoader) { AMDLoader.global = _amdLoaderGlobal; - var Environment = /** @class */ (function () { + var Environment = (function () { function Environment() { this._detected = false; this._isWindows = false; @@ -93,7 +94,7 @@ var AMDLoader; *--------------------------------------------------------------------------------------------*/ var AMDLoader; (function (AMDLoader) { - var LoaderEvent = /** @class */ (function () { + var LoaderEvent = (function () { function LoaderEvent(type, detail, timestamp) { this.type = type; this.detail = detail; @@ -102,7 +103,7 @@ var AMDLoader; return LoaderEvent; }()); AMDLoader.LoaderEvent = LoaderEvent; - var LoaderEventRecorder = /** @class */ (function () { + var LoaderEventRecorder = (function () { function LoaderEventRecorder(loaderAvailableTimestamp) { this._events = [new LoaderEvent(1 /* LoaderAvailable */, '', loaderAvailableTimestamp)]; } @@ -115,7 +116,7 @@ var AMDLoader; return LoaderEventRecorder; }()); AMDLoader.LoaderEventRecorder = LoaderEventRecorder; - var NullLoaderEventRecorder = /** @class */ (function () { + var NullLoaderEventRecorder = (function () { function NullLoaderEventRecorder() { } NullLoaderEventRecorder.prototype.record = function (type, detail) { @@ -124,9 +125,9 @@ var AMDLoader; NullLoaderEventRecorder.prototype.getEvents = function () { return []; }; - NullLoaderEventRecorder.INSTANCE = new NullLoaderEventRecorder(); return NullLoaderEventRecorder; }()); + NullLoaderEventRecorder.INSTANCE = new NullLoaderEventRecorder(); AMDLoader.NullLoaderEventRecorder = NullLoaderEventRecorder; })(AMDLoader || (AMDLoader = {})); /*--------------------------------------------------------------------------------------------- @@ -135,7 +136,7 @@ var AMDLoader; *--------------------------------------------------------------------------------------------*/ var AMDLoader; (function (AMDLoader) { - var Utilities = /** @class */ (function () { + var Utilities = (function () { function Utilities() { } /** @@ -221,11 +222,11 @@ var AMDLoader; } return (this.HAS_PERFORMANCE_NOW ? AMDLoader.global.performance.now() : Date.now()); }; - Utilities.NEXT_ANONYMOUS_ID = 1; - Utilities.PERFORMANCE_NOW_PROBED = false; - Utilities.HAS_PERFORMANCE_NOW = false; return Utilities; }()); + Utilities.NEXT_ANONYMOUS_ID = 1; + Utilities.PERFORMANCE_NOW_PROBED = false; + Utilities.HAS_PERFORMANCE_NOW = false; AMDLoader.Utilities = Utilities; })(AMDLoader || (AMDLoader = {})); /*--------------------------------------------------------------------------------------------- @@ -234,7 +235,7 @@ var AMDLoader; *--------------------------------------------------------------------------------------------*/ var AMDLoader; (function (AMDLoader) { - var ConfigurationOptionsUtil = /** @class */ (function () { + var ConfigurationOptionsUtil = (function () { function ConfigurationOptionsUtil() { } /** @@ -343,7 +344,7 @@ var AMDLoader; return ConfigurationOptionsUtil; }()); AMDLoader.ConfigurationOptionsUtil = ConfigurationOptionsUtil; - var Configuration = /** @class */ (function () { + var Configuration = (function () { function Configuration(env, options) { this._env = env; this.options = ConfigurationOptionsUtil.mergeConfigurationOptions(options); @@ -554,7 +555,7 @@ var AMDLoader; /** * Load `scriptSrc` only once (avoid multiple