Merge branch 'master' into joh/extpack

This commit is contained in:
Johannes Rieken 2018-08-10 12:51:03 +02:00
commit ca3407b4d0
94 changed files with 1766 additions and 1112 deletions

View file

@ -10,7 +10,7 @@ import LinkProvider from '../features/documentLinkProvider';
import { InMemoryDocument } from './inMemoryDocument';
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
const noopToken = new class implements vscode.CancellationToken {
private _onCancellationRequestedEmitter = new vscode.EventEmitter<void>();

View file

@ -11,7 +11,7 @@ import { InMemoryDocument } from './inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
function getSymbolsForFile(fileContents: string) {

View file

@ -11,7 +11,7 @@ import MarkdownFoldingProvider from '../features/foldingProvider';
import { InMemoryDocument } from './inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
suite('markdown.FoldingProvider', () => {
test('Should not return anything for empty document', async () => {

View file

@ -11,7 +11,7 @@ import { TableOfContentsProvider } from '../tableOfContentsProvider';
import { InMemoryDocument } from './inMemoryDocument';
import { createNewMarkdownEngine } from './engine';
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
suite('markdown.TableOfContentsProvider', () => {
test('Lookup should not return anything for empty document', async () => {

View file

@ -22,7 +22,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
});
test('Should return symbols from workspace with one markdown file', async () => {
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
const provider = new MarkdownWorkspaceSymbolProvider(symbolProvider, new InMemoryWorkspaceMarkdownDocumentProvider([
new InMemoryDocument(testFileName, `# header1\nabc\n## header2`)
@ -49,7 +49,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
});
test('Should update results when markdown file changes symbols', async () => {
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
new InMemoryDocument(testFileName, `# header1`)
@ -68,7 +68,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
});
test('Should remove results when file is deleted', async () => {
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
new InMemoryDocument(testFileName, `# header1`)
@ -84,7 +84,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
});
test('Should update results when markdown file is created', async () => {
const testFileName = vscode.Uri.parse('test.md');
const testFileName = vscode.Uri.file('test.md');
const workspaceFileProvider = new InMemoryWorkspaceMarkdownDocumentProvider([
new InMemoryDocument(testFileName, `# header1`)
@ -94,7 +94,7 @@ suite('markdown.WorkspaceSymbolProvider', () => {
assert.strictEqual((await provider.provideWorkspaceSymbols('')).length, 1);
// Creat file
workspaceFileProvider.createDocument(new InMemoryDocument(vscode.Uri.parse('test2.md'), `# new header\nabc\n## header2`));
workspaceFileProvider.createDocument(new InMemoryDocument(vscode.Uri.file('test2.md'), `# new header\nabc\n## header2`));
const newSymbols = await provider.provideWorkspaceSymbols('');
assert.strictEqual(newSymbols.length, 3);
});
@ -105,7 +105,7 @@ class InMemoryWorkspaceMarkdownDocumentProvider implements WorkspaceMarkdownDocu
private readonly _documents = new Map<string, vscode.TextDocument>();
constructor(documents: vscode.TextDocument[]) {
for( const doc of documents) {
for (const doc of documents) {
this._documents.set(doc.fileName, doc);
}
}

View file

@ -688,7 +688,7 @@ suite('window namespace tests', () => {
const renderer = window.createTerminalRenderer('foo');
});
test('Terminal.sendText should fire Termnial.onInput', (done) => {
test('Terminal.sendText should fire Terminal.onInput', (done) => {
const reg1 = window.onDidOpenTerminal(terminal => {
reg1.dispose();
const reg2 = renderer.onDidAcceptInput(data => {

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.27.0",
"distro": "73cb7173636931afba8d741be343ceafb11a177e",
"distro": "a4155d9780fbbc94ead6cb3017dd0fc3806c57b8",
"author": {
"name": "Microsoft Corporation"
},
@ -50,7 +50,7 @@
"vscode-nsfw": "1.0.17",
"vscode-ripgrep": "^1.0.1",
"vscode-textmate": "^4.0.1",
"vscode-xterm": "3.7.0-beta3",
"vscode-xterm": "3.7.0-beta4",
"winreg": "^1.2.4",
"yauzl": "^2.9.1"
},

View file

@ -6,10 +6,8 @@
'use strict';
import 'vs/css!./progressbar';
import { TPromise, ValueCallback } from 'vs/base/common/winjs.base';
import * as assert from 'vs/base/common/assert';
import { Builder, $ } from 'vs/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
import { Disposable } from 'vs/base/common/lifecycle';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
@ -41,7 +39,6 @@ export class ProgressBar extends Disposable {
private element: Builder;
private bit: HTMLElement;
private totalWork: number;
private animationStopToken: ValueCallback;
private progressBarBackground: Color;
constructor(container: HTMLElement, options?: IProgressBarOptions) {
@ -60,19 +57,7 @@ export class ProgressBar extends Disposable {
private create(container: HTMLElement): void {
$(container).div({ 'class': css_progress_container }, builder => {
this.element = builder.clone();
builder.div({ 'class': css_progress_bit }).on([DOM.EventType.ANIMATION_START, DOM.EventType.ANIMATION_END, DOM.EventType.ANIMATION_ITERATION], (e: Event) => {
switch (e.type) {
case DOM.EventType.ANIMATION_ITERATION:
if (this.animationStopToken) {
this.animationStopToken(null);
}
break;
}
}, this.toDispose);
this.bit = builder.getHTMLElement();
this.bit = builder.div({ 'class': css_progress_bit }).getHTMLElement();
});
this.applyStyles();
@ -111,7 +96,7 @@ export class ProgressBar extends Disposable {
this.bit.style.width = 'inherit';
if (delayed) {
TPromise.timeout(200).then(() => this.off());
setTimeout(200, () => this.off());
} else {
this.off();
}
@ -121,7 +106,7 @@ export class ProgressBar extends Disposable {
else {
this.bit.style.opacity = '0';
if (delayed) {
TPromise.timeout(200).then(() => this.off());
setTimeout(200, () => this.off());
} else {
this.off();
}

View file

@ -7,6 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { isThenable } from 'vs/base/common/async';
export interface ITelemetryData {
from?: string;
@ -225,7 +226,7 @@ export class ActionRunner implements IActionRunner {
protected runAction(action: IAction, context?: any): TPromise<any> {
const res = context ? action.run(context) : action.run();
if (TPromise.is(res)) {
if (isThenable(res)) {
return res;
}

View file

@ -408,8 +408,12 @@ export function timeout(n: number): CancelablePromise<void> {
});
}
function isWinJSPromise(candidate: any): candidate is TPromise {
return TPromise.is(candidate) && typeof (<TPromise>candidate).done === 'function';
/**
*
* @returns `true` if candidate is a `WinJS.Promise`
*/
export function isWinJSPromise(candidate: any): candidate is TPromise {
return isThenable(candidate) && typeof (<TPromise>candidate).done === 'function';
}
/**

View file

@ -10,6 +10,7 @@ import * as paths from 'vs/base/common/paths';
import { LRUCache } from 'vs/base/common/map';
import { CharCode } from 'vs/base/common/charCode';
import { TPromise } from 'vs/base/common/winjs.base';
import { isThenable } from 'vs/base/common/async';
export interface IExpression {
[pattern: string]: boolean | SiblingClause | any;
@ -646,7 +647,7 @@ function parseExpressionPattern(pattern: string, value: any, options: IGlobOptio
const clausePattern = when.replace('$(basename)', name);
const matched = hasSibling(clausePattern);
return TPromise.is(matched) ?
return isThenable(matched) ?
matched.then(m => m ? pattern : null) :
matched ? pattern : null;
};
@ -699,4 +700,4 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE
const aggregatedPatterns = parsedPatterns.filter(parsedPattern => !(<ParsedStringPattern>parsedPattern).basenames);
aggregatedPatterns.push(aggregate);
return aggregatedPatterns;
}
}

View file

@ -34,7 +34,7 @@ export function dirname(path: string, separator = nativeSep): string {
return dirname(path.substring(0, path.length - 1));
} else {
let res = path.substring(0, ~idx);
if (isWindows && res.length === 2 && res[res.length - 1] === ':') {
if (isWindows && res[res.length - 1] === ':') {
res += separator; // make sure drive letters end with backslash
}
return res;

View file

@ -8,7 +8,7 @@ import * as paths from 'vs/base/common/paths';
import URI from 'vs/base/common/uri';
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { Schemas } from 'vs/base/common/network';
import { isLinux } from 'vs/base/common/platform';
import { isLinux, isWindows } from 'vs/base/common/platform';
import { CharCode } from 'vs/base/common/charCode';
export function getComparisonKey(resource: URI): string {
@ -28,9 +28,8 @@ export function basenameOrAuthority(resource: URI): string {
export function isEqualOrParent(resource: URI, candidate: URI, ignoreCase?: boolean): boolean {
if (resource.scheme === candidate.scheme && resource.authority === candidate.authority) {
if (resource.scheme === Schemas.file) {
return paths.isEqualOrParent(resource.path, candidate.path, ignoreCase);
return paths.isEqualOrParent(resource.fsPath, candidate.fsPath, ignoreCase);
}
return paths.isEqualOrParent(resource.path, candidate.path, ignoreCase, '/');
}
@ -82,7 +81,12 @@ export function dirname(resource: URI): URI {
* @returns The resulting URI.
*/
export function joinPath(resource: URI, pathFragment: string): URI {
const joinedPath = paths.join(resource.path || '/', pathFragment);
let joinedPath: string;
if (resource.scheme === Schemas.file) {
joinedPath = URI.file(paths.join(resource.fsPath, pathFragment)).path;
} else {
joinedPath = paths.join(resource.path, pathFragment);
}
return resource.with({
path: joinedPath
});
@ -95,7 +99,12 @@ export function joinPath(resource: URI, pathFragment: string): URI {
* @returns The URI with the normalized path.
*/
export function normalizePath(resource: URI): URI {
const normalizedPath = paths.normalize(resource.path, false);
let normalizedPath: string;
if (resource.scheme === Schemas.file) {
normalizedPath = URI.file(paths.normalize(resource.fsPath)).path;
} else {
normalizedPath = paths.normalize(resource.path);
}
return resource.with({
path: normalizedPath
});
@ -127,3 +136,11 @@ export function distinctParents<T>(items: T[], resourceAccessor: (item: T) => UR
return distinctParents;
}
export function isMalformedFileUri(candidate: URI): URI | undefined {
if (!candidate.scheme || isWindows && candidate.scheme.match(/^[a-zA-Z]$/)) {
return URI.file((candidate.scheme ? candidate.scheme + ':' : '') + candidate.path);
}
return void 0;
}

View file

@ -69,7 +69,7 @@ const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
/**
* Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
* This class is a simple parser which creates the basic component paths
* This class is a simple parser which creates the basic component parts
* (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
* and encoding.
*
@ -80,8 +80,6 @@ const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
* | _____________________|__
* / \ / \
* urn:example:animal:ferret:nose
*
*
*/
export default class URI implements UriComponents {
@ -165,9 +163,27 @@ export default class URI implements UriComponents {
/**
* Returns a string representing the corresponding file system path of this URI.
* Will handle UNC paths and normalize windows drive letters to lower-case. Also
* uses the platform specific path separator. Will *not* validate the path for
* invalid characters and semantics. Will *not* look at the scheme of this URI.
* Will handle UNC paths, normalizes windows drive letters to lower-case, and uses the
* platform specific path separator.
*
* * Will *not* validate the path for invalid characters and semantics.
* * Will *not* look at the scheme of this URI.
* * The result shall *not* be used for display purposes but for accessing a file on disk.
*
*
* The *difference* to `URI#path` is the use of the platform specific separator and the handling
* of UNC paths. See the below sample of a file-uri with an authority (UNC path).
*
* ```ts
const u = URI.parse('file://server/c$/folder/file.txt')
u.authority === 'server'
u.path === '/shares/c$/file.txt'
u.fsPath === '\\server\c$\folder\file.txt'
```
*
* Using `URI#path` to read a file (using fs-apis) would not be enough because parts of the path,
* namely the server name, would be missing. Therefore `URI#fsPath` exists - it's sugar to ease working
* with URIs that represent files on disk (`file` scheme).
*/
get fsPath(): string {
return _makeFsPath(this);
@ -175,7 +191,7 @@ export default class URI implements UriComponents {
// ---- modify to new -------------------------
public with(change: { scheme?: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
public with(change: { scheme?: string; authority?: string | null; path?: string | null; query?: string | null; fragment?: string | null }): URI {
if (!change) {
return this;
@ -222,6 +238,12 @@ export default class URI implements UriComponents {
// ---- parse & validate ------------------------
/**
* Creates a new URI from a string, e.g. `http://www.msft.com/some/path`,
* `file:///usr/home`, or `scheme:with/path`.
*
* @param value A string which represents an URI (see `URI#toString`).
*/
public static parse(value: string): URI {
const match = _regexp.exec(value);
if (!match) {
@ -236,6 +258,28 @@ export default class URI implements UriComponents {
);
}
/**
* Creates a new URI from a file system path, e.g. `c:\my\files`,
* `/usr/home`, or `\\server\share\some\path`.
*
* The *difference* between `URI#parse` and `URI#file` is that the latter treats the argument
* as path, not as stringified-uri. E.g. `URI.file(path)` is **not the same as**
* `URI.parse('file://' + path)` because the path might contain characters that are
* interpreted (# and ?). See the following sample:
* ```ts
const good = URI.file('/coding/c#/project1');
good.scheme === 'file';
good.path === '/coding/c#/project1';
good.fragment === '';
const bad = URI.parse('file://' + '/coding/c#/project1');
bad.scheme === 'file';
bad.path === '/coding/c'; // path is now broken
bad.fragment === '/project1';
```
*
* @param path A file system path (see `URI#fsPath`)
*/
public static file(path: string): URI {
let authority = _empty;
@ -263,7 +307,7 @@ export default class URI implements UriComponents {
return new _URI('file', authority, path, _empty, _empty);
}
public static from(components: { scheme?: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
public static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
return new _URI(
components.scheme,
components.authority,
@ -276,6 +320,13 @@ export default class URI implements UriComponents {
// ---- printing/externalize ---------------------------
/**
* Creates a string presentation for this URI. It's guardeed that calling
* `URI.parse` with the result of this function creates an URI which is equal
* to this URI.
*
* * The result shall *not* be used for display purposes but for externalization or transport.
* * The result will be encoded using the percentage encoding and encoding happens mostly
* ignore the scheme-specific encoding rules.
*
* @param skipEncoding Do not encode the result, default is `false`
*/

View file

@ -29,8 +29,6 @@ export class Promise<T = any> {
public static as<T, SomePromise extends PromiseLike<T>>(value: SomePromise): SomePromise;
public static as<T>(value: T): Promise<T>;
public static is(value: any): value is PromiseLike<any>;
public static timeout(delay: number): Promise<void>;
public static join<T1, T2>(promises: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;

View file

@ -5,6 +5,7 @@
import { Promise as WinJSPromise } from './winjs.base';
import * as platform from 'vs/base/common/platform';
import { isWinJSPromise } from 'vs/base/common/async';
/**
* A polyfill for the native promises. The implementation is based on
@ -45,7 +46,7 @@ export class PolyfillPromise<T = any> implements Promise<T> {
constructor(callback: (resolve: (value?: T) => void, reject: (err?: any) => void) => any);
constructor(initOrPromise: WinJSPromise | ((resolve: (value?: T) => void, reject: (err?: any) => void) => any)) {
if (WinJSPromise.is(initOrPromise)) {
if (isWinJSPromise(initOrPromise)) {
this._winjsPromise = initOrPromise;
} else {
this._winjsPromise = new WinJSPromise((resolve, reject) => {

View file

@ -6,7 +6,6 @@
import 'vs/css!./quickopen';
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import * as platform from 'vs/base/common/platform';
import * as types from 'vs/base/common/types';
import * as errors from 'vs/base/common/errors';
@ -980,11 +979,8 @@ export class QuickOpenWidget extends Disposable implements IModelProvider {
}
this.isLoosingFocus = true;
TPromise.timeout(0).then(() => {
if (!this.isLoosingFocus) {
return;
}
if (this.isDisposed) {
setTimeout(() => {
if (!this.isLoosingFocus || this.isDisposed) {
return;
}
@ -992,7 +988,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider {
if (!veto) {
this.hide(HideReason.FOCUS_LOST);
}
});
}, 0);
}
dispose(): void {

View file

@ -5,7 +5,7 @@
'use strict';
import * as assert from 'assert';
import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath } from 'vs/base/common/resources';
import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, isMalformedFileUri } from 'vs/base/common/resources';
import URI from 'vs/base/common/uri';
import { isWindows } from 'vs/base/common/platform';
@ -204,4 +204,24 @@ suite('Resources', () => {
assert.equal(isEqualOrParent(fileURI3, fileURI, true), false, '15');
assert.equal(isEqualOrParent(fileURI5, fileURI5, true), true, '16');
});
function assertMalformedFileUri(path: string, expected: string) {
const newURI = isMalformedFileUri(URI.parse(path));
assert.equal(newURI && newURI.toString(), expected);
}
test('isMalformedFileUri', () => {
if (isWindows) {
assertMalformedFileUri('c:/foo/bar', 'file:///c%3A/foo/bar');
assertMalformedFileUri('c:\\foo\\bar', 'file:///c%3A/foo/bar');
assertMalformedFileUri('\\\\localhost\\c$\\devel\\test', 'file://localhost/c%24/devel/test');
}
assertMalformedFileUri('/foo/bar', 'file:///foo/bar');
assertMalformedFileUri('file:///foo/bar', void 0);
assertMalformedFileUri('file:///c%3A/foo/bar', void 0);
assertMalformedFileUri('file://localhost/c$/devel/test', void 0);
assertMalformedFileUri('foo://dadie/foo/bar', void 0);
assertMalformedFileUri('foo:///dadie/foo/bar', void 0);
});
});

View file

@ -65,6 +65,7 @@ import { MenubarService } from 'vs/platform/menubar/electron-main/menubarService
import { MenubarChannel } from 'vs/platform/menubar/common/menubarIpc';
import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
import { CodeMenu } from 'vs/code/electron-main/menus';
import { RunOnceScheduler } from 'vs/base/common/async';
export class CodeApplication {
@ -529,7 +530,9 @@ export class CodeApplication {
this.historyMainService.onRecentlyOpenedChange(() => this.historyMainService.updateWindowsJumpList());
// Start shared process after a while
TPromise.timeout(3000).then(() => this.sharedProcess.spawn());
const sharedProcess = new RunOnceScheduler(() => this.sharedProcess.spawn(), 3000);
sharedProcess.schedule();
this.toDispose.push(sharedProcess);
}
private dispose(): void {

View file

@ -944,7 +944,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
clonedOptions.folding = false;
clonedOptions.codeLens = false;
clonedOptions.fixedOverflowWidgets = true;
clonedOptions.lineDecorationsWidth = '2ch';
// clonedOptions.lineDecorationsWidth = '2ch';
if (!clonedOptions.minimap) {
clonedOptions.minimap = {};
}

View file

@ -41,6 +41,8 @@
opacity: 0.7;
background-repeat: no-repeat;
background-position: 50% 50%;
background-position: center;
background-size: 11px 11px;
}
.monaco-editor.hc-black .insert-sign,
.monaco-diff-editor.hc-black .insert-sign,

View file

@ -28,6 +28,7 @@ import { overviewRulerWarning, overviewRulerError, overviewRulerInfo } from 'vs/
import { ITextModel, IModelDeltaDecoration, IModelDecorationOptions, TrackedRangeStickiness, OverviewRulerLane, DefaultEndOfLine, ITextModelCreationOptions, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBufferFactory, ITextBuffer, EndOfLinePreference } from 'vs/editor/common/model';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { basename } from 'vs/base/common/paths';
import { isThenable } from 'vs/base/common/async';
function MODEL_ID(resource: URI): string {
return resource.toString();
@ -500,7 +501,7 @@ export class ModelServiceImpl implements IModelService {
public createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise<IMode> | IMode, resource: URI, isForSimpleWidget: boolean = false): ITextModel {
let modelData: ModelData;
if (!modeOrPromise || TPromise.is(modeOrPromise)) {
if (!modeOrPromise || isThenable(modeOrPromise)) {
modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource, isForSimpleWidget);
this.setMode(modelData.model, modeOrPromise);
} else {
@ -521,7 +522,7 @@ export class ModelServiceImpl implements IModelService {
if (!modeOrPromise) {
return;
}
if (TPromise.is(modeOrPromise)) {
if (isThenable(modeOrPromise)) {
modeOrPromise.then((mode) => {
if (!model.isDisposed()) {
model.setMode(mode.getLanguageIdentifier());

View file

@ -332,10 +332,13 @@ export class FoldingController implements IEditorContribution {
switch (e.target.type) {
case MouseTargetType.GUTTER_LINE_DECORATIONS:
const data = e.target.detail as IMarginData;
const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
const offsetLeftInGutter = (e.target.element as HTMLElement).offsetLeft;
const gutterOffsetX = data.offsetX - offsetLeftInGutter;
// const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
// TODO@joao TODO@alex TODO@martin this is such that we don't collide with dirty diff
if (gutterOffsetX <= 10) {
if (gutterOffsetX < 10) {
return;
}

View file

@ -26,6 +26,7 @@ import { ITextModel, IWordAtPosition } from 'vs/editor/common/model';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { createCancelablePromise } from 'vs/base/common/async';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
export class DefinitionActionConfig {
@ -375,3 +376,31 @@ registerEditorAction(GoToImplementationAction);
registerEditorAction(PeekImplementationAction);
registerEditorAction(GoToTypeDefinitionAction);
registerEditorAction(PeekTypeDefinitionAction);
// Go to menu
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToDeclaration',
title: nls.localize({ key: 'miGotoDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Definition")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToTypeDefinition',
title: nls.localize({ key: 'miGotoTypeDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Type Definition")
},
order: 5
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToImplementation',
title: nls.localize({ key: 'miGotoImplementation', comment: ['&& denotes a mnemonic'] }, "Go to &&Implementation")
},
order: 6
});

View file

@ -8,7 +8,6 @@
import 'vs/css!./parameterHints';
import * as nls from 'vs/nls';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import * as dom from 'vs/base/browser/dom';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { SignatureHelp, SignatureInformation, SignatureHelpProviderRegistry } from 'vs/editor/common/modes';
@ -294,7 +293,7 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable {
this.keyVisible.set(true);
this.visible = true;
TPromise.timeout(100).done(() => dom.addClass(this.element, 'visible'));
setTimeout(() => dom.addClass(this.element, 'visible'), 100);
this.editor.layoutContentWidget(this);
}

View file

@ -14,6 +14,7 @@ import { LineTokens, IViewLineTokens } from 'vs/editor/common/core/lineTokens';
import * as strings from 'vs/base/common/strings';
import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
import { timeout } from 'vs/base/common/async';
export interface IColorizerOptions {
tabSize?: number;
@ -85,7 +86,7 @@ export class Colorizer {
}
// wait 500ms for mode to load, then give up
return TPromise.any([this._tokenizationSupportChangedPromise(language), TPromise.timeout(500)]).then(_ => {
return TPromise.any([this._tokenizationSupportChangedPromise(language), timeout(500)]).then(_ => {
let tokenizationSupport = TokenizationRegistry.get(language);
if (tokenizationSupport) {
return _colorize(lines, options.tabSize, tokenizationSupport);

View file

@ -50,7 +50,7 @@ export class EditorActionCommandEntry extends QuickOpenEntryGroup {
if (mode === Mode.OPEN) {
// Use a timeout to give the quick open widget a chance to close itself first
TPromise.timeout(50).done(() => {
setTimeout(() => {
// Some actions are enabled only when editor has focus
this.editor.focus();
@ -61,7 +61,7 @@ export class EditorActionCommandEntry extends QuickOpenEntryGroup {
} catch (error) {
onUnexpectedError(error);
}
}, onUnexpectedError);
}, 50);
return true;
}

75
src/vs/monaco.d.ts vendored
View file

@ -72,8 +72,6 @@ declare namespace monaco {
public static as<T, SomePromise extends PromiseLike<T>>(value: SomePromise): SomePromise;
public static as<T>(value: T): Promise<T>;
public static is(value: any): value is PromiseLike<any>;
public static timeout(delay: number): Promise<void>;
public static join<T1, T2>(promises: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
@ -102,7 +100,7 @@ declare namespace monaco {
}
/**
* Uniform Resource Identifier (Uri) http://tools.ietf.org/html/rfc3986.
* This class is a simple parser which creates the basic component paths
* This class is a simple parser which creates the basic component parts
* (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
* and encoding.
*
@ -113,8 +111,6 @@ declare namespace monaco {
* | _____________________|__
* / \ / \
* urn:example:animal:ferret:nose
*
*
*/
export class Uri implements UriComponents {
static isUri(thing: any): thing is Uri;
@ -142,28 +138,81 @@ declare namespace monaco {
readonly fragment: string;
/**
* Returns a string representing the corresponding file system path of this Uri.
* Will handle UNC paths and normalize windows drive letters to lower-case. Also
* uses the platform specific path separator. Will *not* validate the path for
* invalid characters and semantics. Will *not* look at the scheme of this Uri.
* Will handle UNC paths, normalizes windows drive letters to lower-case, and uses the
* platform specific path separator.
*
* * Will *not* validate the path for invalid characters and semantics.
* * Will *not* look at the scheme of this Uri.
* * The result shall *not* be used for display purposes but for accessing a file on disk.
*
*
* The *difference* to `Uri#path` is the use of the platform specific separator and the handling
* of UNC paths. See the below sample of a file-uri with an authority (UNC path).
*
* ```ts
const u = Uri.parse('file://server/c$/folder/file.txt')
u.authority === 'server'
u.path === '/shares/c$/file.txt'
u.fsPath === '\\server\c$\folder\file.txt'
```
*
* Using `Uri#path` to read a file (using fs-apis) would not be enough because parts of the path,
* namely the server name, would be missing. Therefore `Uri#fsPath` exists - it's sugar to ease working
* with URIs that represent files on disk (`file` scheme).
*/
readonly fsPath: string;
with(change: {
scheme?: string;
authority?: string;
path?: string;
query?: string;
fragment?: string;
authority?: string | null;
path?: string | null;
query?: string | null;
fragment?: string | null;
}): Uri;
/**
* Creates a new Uri from a string, e.g. `http://www.msft.com/some/path`,
* `file:///usr/home`, or `scheme:with/path`.
*
* @param value A string which represents an Uri (see `Uri#toString`).
*/
static parse(value: string): Uri;
/**
* Creates a new Uri from a file system path, e.g. `c:\my\files`,
* `/usr/home`, or `\\server\share\some\path`.
*
* The *difference* between `Uri#parse` and `Uri#file` is that the latter treats the argument
* as path, not as stringified-uri. E.g. `Uri.file(path)` is **not the same as**
* `Uri.parse('file://' + path)` because the path might contain characters that are
* interpreted (# and ?). See the following sample:
* ```ts
const good = Uri.file('/coding/c#/project1');
good.scheme === 'file';
good.path === '/coding/c#/project1';
good.fragment === '';
const bad = Uri.parse('file://' + '/coding/c#/project1');
bad.scheme === 'file';
bad.path === '/coding/c'; // path is now broken
bad.fragment === '/project1';
```
*
* @param path A file system path (see `Uri#fsPath`)
*/
static file(path: string): Uri;
static from(components: {
scheme?: string;
scheme: string;
authority?: string;
path?: string;
query?: string;
fragment?: string;
}): Uri;
/**
* Creates a string presentation for this Uri. It's guardeed that calling
* `Uri.parse` with the result of this function creates an Uri which is equal
* to this Uri.
*
* * The result shall *not* be used for display purposes but for externalization or transport.
* * The result will be encoded using the percentage encoding and encoding happens mostly
* ignore the scheme-specific encoding rules.
*
* @param skipEncoding Do not encode the result, default is `false`
*/

View file

@ -7,6 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { isThenable } from 'vs/base/common/async';
export const ILifecycleService = createDecorator<ILifecycleService>('lifecycleService');
@ -23,7 +24,7 @@ export interface ShutdownEvent {
/**
* Allows to veto the shutdown. The veto can be a long running operation.
*/
veto(value: boolean | TPromise<boolean>): void;
veto(value: boolean | Thenable<boolean>): void;
/**
* The reason why Code is shutting down.
@ -108,12 +109,12 @@ export const NullLifecycleService: ILifecycleService = {
};
// Shared veto handling across main and renderer
export function handleVetos(vetos: (boolean | TPromise<boolean>)[], onError: (error: Error) => void): TPromise<boolean /* veto */> {
export function handleVetos(vetos: (boolean | Thenable<boolean>)[], onError: (error: Error) => void): TPromise<boolean /* veto */> {
if (vetos.length === 0) {
return TPromise.as(false);
}
const promises: TPromise<void>[] = [];
const promises: Thenable<void>[] = [];
let lazyValue = false;
for (let valueOrPromise of vetos) {
@ -123,7 +124,7 @@ export function handleVetos(vetos: (boolean | TPromise<boolean>)[], onError: (er
return TPromise.as(true);
}
if (TPromise.is(valueOrPromise)) {
if (isThenable(valueOrPromise)) {
promises.push(valueOrPromise.then(value => {
if (value) {
lazyValue = true; // veto, done

View file

@ -83,7 +83,7 @@ export class LifecycleService implements ILifecycleService {
}
private onBeforeUnload(reason: ShutdownReason): TPromise<boolean> {
const vetos: (boolean | TPromise<boolean>)[] = [];
const vetos: (boolean | Thenable<boolean>)[] = [];
this._onWillShutdown.fire({
veto(value) {

View file

@ -12,6 +12,7 @@ import URI from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
export interface IQuickPickItem {
type?: 'item';
id?: string;
label: string;
description?: string;
@ -21,6 +22,17 @@ export interface IQuickPickItem {
picked?: boolean;
}
export interface IQuickPickSeparator {
type: 'separator';
border?: boolean;
label?: string;
}
export interface IKeyMods {
readonly ctrlCmd: boolean;
readonly alt: boolean;
}
export interface IQuickNavigateConfiguration {
keybindings: ResolvedKeybinding[];
}
@ -67,6 +79,7 @@ export interface IPickOptions<T extends IQuickPickItem> {
*/
activeItem?: TPromise<T> | T;
onKeyMods?: (keyMods: IKeyMods) => void;
onDidFocus?: (entry: T) => void;
onDidTriggerItemButton?: (context: IQuickPickItemButtonContext<T>) => void;
}
@ -147,7 +160,7 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
readonly onDidTriggerItemButton: Event<IQuickPickItemButtonEvent<T>>;
items: ReadonlyArray<T>;
items: ReadonlyArray<T | IQuickPickSeparator>;
canSelectMany: boolean;
@ -164,6 +177,8 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
selectedItems: ReadonlyArray<T>;
readonly onDidChangeSelection: Event<T[]>;
readonly keyMods: IKeyMods;
}
export interface IInputBox extends IQuickInput {
@ -208,6 +223,8 @@ export const IQuickInputService = createDecorator<IQuickInputService>('quickInpu
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export type QuickPickInput<T = IQuickPickItem> = T | IQuickPickSeparator;
export interface IQuickInputService {
_serviceBrand: any;
@ -215,9 +232,9 @@ export interface IQuickInputService {
/**
* Opens the quick input box for selecting items and returns a promise with the user selected item(s) if any.
*/
pick<T extends IQuickPickItem>(picks: TPromise<T[]> | T[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): TPromise<T[]>;
pick<T extends IQuickPickItem>(picks: TPromise<T[]> | T[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): TPromise<T>;
pick<T extends IQuickPickItem>(picks: TPromise<T[]> | T[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): TPromise<T>;
pick<T extends IQuickPickItem>(picks: TPromise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): TPromise<T[]>;
pick<T extends IQuickPickItem>(picks: TPromise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): TPromise<T>;
pick<T extends IQuickPickItem>(picks: TPromise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): TPromise<T>;
/**
* Opens the quick input box for text input and returns a promise with the user typed value if any.

View file

@ -5,6 +5,7 @@
'use strict';
import URI from 'vs/base/common/uri';
import { isMalformedFileUri } from 'vs/base/common/resources';
import * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands';
@ -48,9 +49,11 @@ export class OpenFolderAPICommand {
if (!uri) {
return executor.executeCommand('_files.pickFolderAndOpen', forceNewWindow);
}
if (!uri.scheme) {
console.warn(`'vscode.openFolder' command invoked with an invalid URI (scheme missing): '${uri}'. Converted to a 'file://' URI.`);
uri = URI.file(uri.toString());
let correctedUri = isMalformedFileUri(uri);
if (correctedUri) {
// workaround for #55916 and #55891, will be removed in 1.28
console.warn(`'vscode.openFolder' command invoked with an invalid URI (file:// scheme missing): '${uri}'. Converted to a 'file://' URI: ${correctedUri}`);
uri = correctedUri;
}
return executor.executeCommand('_files.windowOpen', [uri], forceNewWindow);

View file

@ -21,7 +21,7 @@ import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colo
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ActivityAction, ActivityActionItem, ICompositeBarColors, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { ActivityAction, ActivityActionItem, ICompositeBarColors, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositeBarActions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import URI from 'vs/base/common/uri';

View file

@ -22,7 +22,7 @@ import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar';
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
import { isMacintosh } from 'vs/base/common/platform';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { scheduleAtNextAnimationFrame, Dimension, addClass } from 'vs/base/browser/dom';
@ -30,7 +30,7 @@ import { Color } from 'vs/base/common/color';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import URI from 'vs/base/common/uri';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
interface IPlaceholderComposite {

View file

@ -14,7 +14,7 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
import { TPromise } from 'vs/base/common/winjs.base';
import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';

View file

@ -671,3 +671,177 @@ MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
},
order: 9
});
// Main Menu Bar Contributions:
// Forward/Back
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
command: {
id: 'workbench.action.navigateBack',
title: nls.localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back"),
precondition: ContextKeyExpr.has('canNavigateBack')
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
command: {
id: 'workbench.action.navigateForward',
title: nls.localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward"),
precondition: ContextKeyExpr.has('canNavigateForward')
},
order: 2
});
// Switch Editor
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '1_any',
command: {
id: 'workbench.action.nextEditor',
title: nls.localize({ key: 'miNextEditor', comment: ['&& denotes a mnemonic'] }, "&&Next Editor")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '1_any',
command: {
id: 'workbench.action.previousEditor',
title: nls.localize({ key: 'miPreviousEditor', comment: ['&& denotes a mnemonic'] }, "&&Previous Editor")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '2_used',
command: {
id: 'workbench.action.openNextRecentlyUsedEditorInGroup',
title: nls.localize({ key: 'miNextEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Used Editor in Group")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '2_used',
command: {
id: 'workbench.action.openPreviousRecentlyUsedEditorInGroup',
title: nls.localize({ key: 'miPreviousEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Used Editor in Group")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
title: nls.localize({ key: 'miSwitchEditor', comment: ['&& denotes a mnemonic'] }, "Switch &&Editor"),
submenu: MenuId.MenubarSwitchEditorMenu,
order: 1
});
// Switch Group
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFirstEditorGroup',
title: nls.localize({ key: 'miFocusFirstGroup', comment: ['&& denotes a mnemonic'] }, "Group &&1")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusSecondEditorGroup',
title: nls.localize({ key: 'miFocusSecondGroup', comment: ['&& denotes a mnemonic'] }, "Group &&2")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusThirdEditorGroup',
title: nls.localize({ key: 'miFocusThirdGroup', comment: ['&& denotes a mnemonic'] }, "Group &&3")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFourthEditorGroup',
title: nls.localize({ key: 'miFocusFourthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&4")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFifthEditorGroup',
title: nls.localize({ key: 'miFocusFifthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&5")
},
order: 5
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '2_next_prev',
command: {
id: 'workbench.action.focusNextGroup',
title: nls.localize({ key: 'miNextGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Group")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '2_next_prev',
command: {
id: 'workbench.action.focusPreviousGroup',
title: nls.localize({ key: 'miPreviousGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Group")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusLeftGroup',
title: nls.localize({ key: 'miFocusLeftGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Left")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusRightGroup',
title: nls.localize({ key: 'miFocusRightGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Right")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusAboveGroup',
title: nls.localize({ key: 'miFocusAboveGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Above")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusBelowGroup',
title: nls.localize({ key: 'miFocusBelowGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Below")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
title: nls.localize({ key: 'miSwitchGroup', comment: ['&& denotes a mnemonic'] }, "Switch &&Group"),
submenu: MenuId.MenubarSwitchGroupMenu,
order: 2
});

View file

@ -31,7 +31,7 @@ import { IndentUsingSpaces, IndentUsingTabs, DetectIndentation, IndentationToSpa
import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/binaryEditor';
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { SUPPORTED_ENCODINGS, IFileService, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -58,7 +58,8 @@ import { Schemas } from 'vs/base/common/network';
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
import { Themable } from 'vs/workbench/common/theme';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { getIconClasses } from 'vs/workbench/browser/labels';
class SideBySideEditorEncodingSupport implements IEncodingSupport {
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
@ -834,7 +835,6 @@ export class ChangeModeAction extends Action {
@IModelService private modelService: IModelService,
@IEditorService private editorService: IEditorService,
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService,
@IPreferencesService private preferencesService: IPreferencesService,
@IInstantiationService private instantiationService: IInstantiationService,
@ -867,7 +867,7 @@ export class ChangeModeAction extends Action {
// All languages are valid picks
const languages = this.modeService.getRegisteredLanguageNames();
const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => {
const picks: QuickPickInput[] = languages.sort().map((lang, index) => {
let description: string;
if (currentModeId === lang) {
description = nls.localize('languageDescription', "({0}) - Configured Language", this.modeService.getModeIdForLanguageName(lang.toLowerCase()));
@ -887,20 +887,20 @@ export class ChangeModeAction extends Action {
}
}
return <IFilePickOpenEntry>{
return <IQuickPickItem>{
label: lang,
resource: fakeResource,
iconClasses: getIconClasses(this.modelService, this.modeService, fakeResource),
description
};
});
if (hasLanguageSupport) {
picks[0].separator = { border: true, label: nls.localize('languagesPicks', "languages (identifier)") };
picks.unshift({ type: 'separator', border: true, label: nls.localize('languagesPicks', "languages (identifier)") });
}
// Offer action to configure via settings
let configureModeAssociations: IPickOpenEntry;
let configureModeSettings: IPickOpenEntry;
let configureModeAssociations: IQuickPickItem;
let configureModeSettings: IQuickPickItem;
let galleryAction: Action;
if (hasLanguageSupport) {
const ext = paths.extname(resource.fsPath) || paths.basename(resource.fsPath);
@ -917,7 +917,7 @@ export class ChangeModeAction extends Action {
}
// Offer to "Auto Detect"
const autoDetectMode: IPickOpenEntry = {
const autoDetectMode: IQuickPickItem = {
label: nls.localize('autoDetect', "Auto Detect")
};
@ -925,7 +925,7 @@ export class ChangeModeAction extends Action {
picks.unshift(autoDetectMode);
}
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickLanguage', "Select Language Mode"), matchOnDescription: true }).then(pick => {
return this.quickInputService.pick(picks, { placeHolder: nls.localize('pickLanguage', "Select Language Mode"), matchOnDescription: true }).then(pick => {
if (!pick) {
return;
}
@ -999,7 +999,7 @@ export class ChangeModeAction extends Action {
};
});
TPromise.timeout(50 /* quick open is sensitive to being opened so soon after another */).done(() => {
setTimeout(() => {
this.quickInputService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).done(language => {
if (language) {
const fileAssociationsConfig = this.configurationService.inspect(FILES_ASSOCIATIONS_CONFIG);
@ -1027,8 +1027,8 @@ export class ChangeModeAction extends Action {
this.configurationService.updateValue(FILES_ASSOCIATIONS_CONFIG, currentAssociations, target);
}
});
});
}, error => errors.onUnexpectedError(error));
}, 50 /* quick open is sensitive to being opened so soon after another */);
}
}
@ -1045,7 +1045,6 @@ class ChangeIndentationAction extends Action {
actionId: string,
actionLabel: string,
@IEditorService private editorService: IEditorService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService
) {
super(actionId, actionLabel);
@ -1061,7 +1060,7 @@ class ChangeIndentationAction extends Action {
return this.quickInputService.pick([{ label: nls.localize('noWritableCodeEditor', "The active code editor is read-only.") }]);
}
const picks = [
const picks: QuickPickInput<IQuickPickItem & { run(): void }>[] = [
activeTextEditorWidget.getAction(IndentUsingSpaces.ID),
activeTextEditorWidget.getAction(IndentUsingTabs.ID),
activeTextEditorWidget.getAction(DetectIndentation.ID),
@ -1080,10 +1079,10 @@ class ChangeIndentationAction extends Action {
};
});
(<IPickOpenEntry>picks[0]).separator = { label: nls.localize('indentView', "change view") };
(<IPickOpenEntry>picks[3]).separator = { label: nls.localize('indentConvert', "convert file"), border: true };
picks.splice(3, 0, { type: 'separator', label: nls.localize('indentConvert', "convert file"), border: true });
picks.unshift({ type: 'separator', label: nls.localize('indentView', "change view") });
return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true }).then(action => action && action.run());
return this.quickInputService.pick(picks, { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true }).then(action => action && action.run());
}
}
@ -1141,7 +1140,6 @@ export class ChangeEncodingAction extends Action {
actionId: string,
actionLabel: string,
@IEditorService private editorService: IEditorService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService,
@ITextResourceConfigurationService private textResourceConfigurationService: ITextResourceConfigurationService,
@IFileService private fileService: IFileService
@ -1204,7 +1202,7 @@ export class ChangeEncodingAction extends Action {
let aliasMatchIndex: number;
// All encodings are valid picks
const picks: IPickOpenEntry[] = Object.keys(SUPPORTED_ENCODINGS)
const picks: QuickPickInput[] = Object.keys(SUPPORTED_ENCODINGS)
.sort((k1, k2) => {
if (k1 === configuredEncoding) {
return -1;
@ -1233,13 +1231,14 @@ export class ChangeEncodingAction extends Action {
// If we have a guessed encoding, show it first unless it matches the configured encoding
if (guessedEncoding && configuredEncoding !== guessedEncoding && SUPPORTED_ENCODINGS[guessedEncoding]) {
picks[0].separator = { border: true };
picks.unshift({ type: 'separator', border: true });
picks.unshift({ id: guessedEncoding, label: SUPPORTED_ENCODINGS[guessedEncoding].labelLong, description: nls.localize('guessedEncoding', "Guessed from content") });
}
return this.quickOpenService.pick(picks, {
const items = picks.filter(p => p.type !== 'separator') as IQuickPickItem[];
return this.quickInputService.pick(picks, {
placeHolder: isReopenWithEncoding ? nls.localize('pickEncodingForReopen', "Select File Encoding to Reopen File") : nls.localize('pickEncodingForSave', "Select File Encoding to Save with"),
autoFocus: { autoFocusIndex: typeof directMatchIndex === 'number' ? directMatchIndex : typeof aliasMatchIndex === 'number' ? aliasMatchIndex : void 0 }
activeItem: items[typeof directMatchIndex === 'number' ? directMatchIndex : typeof aliasMatchIndex === 'number' ? aliasMatchIndex : -1]
}).then(encoding => {
if (encoding) {
activeControl = this.editorService.activeControl;

View file

@ -79,6 +79,7 @@
display: flex;
flex: initial;
opacity: 0.5;
height: 35px;
}
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .title-actions {

View file

@ -232,6 +232,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
const options: IDiffEditorOptions = super.getConfigurationOverrides();
options.readOnly = this.isReadOnly();
options.lineDecorationsWidth = '2ch';
return options;
}

View file

@ -1,50 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .part.menubar {
display: flex;
flex-shrink: 1;
box-sizing: border-box;
height: 30px;
-webkit-app-region: no-drag;
overflow: hidden;
flex-wrap: wrap;
}
.monaco-workbench.fullscreen .part.menubar {
margin: 0px;
padding: 0px 5px;
}
.monaco-workbench .part.menubar > .menubar-menu-button {
align-items: center;
box-sizing: border-box;
padding: 0px 8px;
cursor: default;
-webkit-app-region: no-drag;
zoom: 1;
white-space: nowrap;
}
.monaco-workbench .part.menubar .menubar-menu-items-holder {
position: absolute;
left: 0px;
opacity: 1;
z-index: 2000;
}
.monaco-workbench .part.menubar .menubar-menu-items-holder.monaco-menu-container {
font-family: "Segoe WPC", "Segoe UI", ".SFNSDisplay-Light", "SFUIText-Light", "HelveticaNeue-Light", sans-serif, "Droid Sans Fallback";
outline: 0;
border: none;
}
.monaco-workbench .part.menubar .menubar-menu-items-holder.monaco-menu-container :focus {
outline: 0;
}
.hc-black .monaco-workbench .part.menubar .menubar-menu-items-holder.monaco-menu-container {
border: 2px solid #6FC3DF;
}

View file

@ -1,402 +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 { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { isMacintosh } from 'vs/base/common/platform';
goMenuRegistration();
if (isMacintosh) {
windowMenuRegistration();
}
helpMenuRegistration();
// Menu registration
function goMenuRegistration() {
// Forward/Back
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
command: {
id: 'workbench.action.navigateBack',
title: nls.localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '1_fwd_back',
command: {
id: 'workbench.action.navigateForward',
title: nls.localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward")
},
order: 2
});
// Switch Editor
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '1_any',
command: {
id: 'workbench.action.nextEditor',
title: nls.localize({ key: 'miNextEditor', comment: ['&& denotes a mnemonic'] }, "&&Next Editor")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '1_any',
command: {
id: 'workbench.action.previousEditor',
title: nls.localize({ key: 'miPreviousEditor', comment: ['&& denotes a mnemonic'] }, "&&Previous Editor")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '2_used',
command: {
id: 'workbench.action.openNextRecentlyUsedEditorInGroup',
title: nls.localize({ key: 'miNextEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Used Editor in Group")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
group: '2_used',
command: {
id: 'workbench.action.openPreviousRecentlyUsedEditorInGroup',
title: nls.localize({ key: 'miPreviousEditorInGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Used Editor in Group")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
title: nls.localize({ key: 'miSwitchEditor', comment: ['&& denotes a mnemonic'] }, "Switch &&Editor"),
submenu: MenuId.MenubarSwitchEditorMenu,
order: 1
});
// Switch Group
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFirstEditorGroup',
title: nls.localize({ key: 'miFocusFirstGroup', comment: ['&& denotes a mnemonic'] }, "Group &&1")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusSecondEditorGroup',
title: nls.localize({ key: 'miFocusSecondGroup', comment: ['&& denotes a mnemonic'] }, "Group &&2")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusThirdEditorGroup',
title: nls.localize({ key: 'miFocusThirdGroup', comment: ['&& denotes a mnemonic'] }, "Group &&3")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFourthEditorGroup',
title: nls.localize({ key: 'miFocusFourthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&4")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '1_focus_index',
command: {
id: 'workbench.action.focusFifthEditorGroup',
title: nls.localize({ key: 'miFocusFifthGroup', comment: ['&& denotes a mnemonic'] }, "Group &&5")
},
order: 5
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '2_next_prev',
command: {
id: 'workbench.action.focusNextGroup',
title: nls.localize({ key: 'miNextGroup', comment: ['&& denotes a mnemonic'] }, "&&Next Group")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '2_next_prev',
command: {
id: 'workbench.action.focusPreviousGroup',
title: nls.localize({ key: 'miPreviousGroup', comment: ['&& denotes a mnemonic'] }, "&&Previous Group")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusLeftGroup',
title: nls.localize({ key: 'miFocusLeftGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Left")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusRightGroup',
title: nls.localize({ key: 'miFocusRightGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Right")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusAboveGroup',
title: nls.localize({ key: 'miFocusAboveGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Above")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
group: '3_directional',
command: {
id: 'workbench.action.focusBelowGroup',
title: nls.localize({ key: 'miFocusBelowGroup', comment: ['&& denotes a mnemonic'] }, "Group &&Below")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '2_switch',
title: nls.localize({ key: 'miSwitchGroup', comment: ['&& denotes a mnemonic'] }, "Switch &&Group"),
submenu: MenuId.MenubarSwitchGroupMenu,
order: 2
});
// Go to
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.quickOpen',
title: nls.localize({ key: 'miGotoFile', comment: ['&& denotes a mnemonic'] }, "Go to &&File...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.gotoSymbol',
title: nls.localize({ key: 'miGotoSymbolInFile', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in File...")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.showAllSymbols',
title: nls.localize({ key: 'miGotoSymbolInWorkspace', comment: ['&& denotes a mnemonic'] }, "Go to Symbol in &&Workspace...")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToDeclaration',
title: nls.localize({ key: 'miGotoDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Definition")
},
order: 4
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToTypeDefinition',
title: nls.localize({ key: 'miGotoTypeDefinition', comment: ['&& denotes a mnemonic'] }, "Go to &&Type Definition")
},
order: 5
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'editor.action.goToImplementation',
title: nls.localize({ key: 'miGotoImplementation', comment: ['&& denotes a mnemonic'] }, "Go to &&Implementation")
},
order: 6
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.gotoLine',
title: nls.localize({ key: 'miGotoLine', comment: ['&& denotes a mnemonic'] }, "Go to &&Line...")
},
order: 7
});
}
function windowMenuRegistration() {
}
function helpMenuRegistration() {
// Welcome
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.showWelcomePage',
title: nls.localize({ key: 'miWelcome', comment: ['&& denotes a mnemonic'] }, "&&Welcome")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.showInteractivePlayground',
title: nls.localize({ key: 'miInteractivePlayground', comment: ['&& denotes a mnemonic'] }, "&&Interactive Playground")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.openDocumentationUrl',
title: nls.localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'update.showCurrentReleaseNotes',
title: nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "&&Release Notes")
},
order: 4
});
// Reference
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.keybindingsReference',
title: nls.localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openIntroductoryVideosUrl',
title: nls.localize({ key: 'miIntroductoryVideos', comment: ['&& denotes a mnemonic'] }, "Introductory &&Videos")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openTipsAndTricksUrl',
title: nls.localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "&&Tips and Tricks")
},
order: 3
});
// Feedback
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openTwitterUrl',
title: nls.localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join us on Twitter")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openRequestFeatureUrl',
title: nls.localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openIssueReporter',
title: nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue")
},
order: 3
});
// Legal
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '4_legal',
command: {
id: 'workbench.action.openLicenseUrl',
title: nls.localize({ key: 'miLicense', comment: ['&& denotes a mnemonic'] }, "View &&License")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '4_legal',
command: {
id: 'workbench.action.openPrivacyStatementUrl',
title: nls.localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "&&Privacy Statement")
},
order: 2
});
// Tools
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '5_tools',
command: {
id: 'workbench.action.toggleDevTools',
title: nls.localize({ key: 'miToggleDevTools', comment: ['&& denotes a mnemonic'] }, "&&Toggle Developer Tools")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '5_tools',
command: {
id: 'workbench.action.openProcessExplorer',
title: nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")
},
order: 2
});
if (!isMacintosh) {
// About
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: 'z_about',
command: {
id: 'workbench.action.showAboutDialog',
title: nls.localize({ key: 'miAbout', comment: ['&& denotes a mnemonic'] }, "&&About")
},
order: 1
});
}
}

View file

@ -14,7 +14,7 @@ import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/
import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/actions';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
import { ActivityAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { ActivityAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { IActivity } from 'vs/workbench/common/activity';
export class ClosePanelAction extends Action {

View file

@ -23,8 +23,8 @@ import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, Toggl
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Dimension } from 'vs/base/browser/dom';

View file

@ -170,6 +170,21 @@
font-weight: bold;
}
.quick-input-list .quick-input-list-separator {
margin-right: 18px;
}
.quick-input-list .quick-input-list-entry.has-actions:hover .quick-input-list-separator,
.quick-input-list .monaco-list-row.focused .quick-input-list-entry.has-actions .quick-input-list-separator {
margin-right: 0;
}
.quick-input-list .quick-input-list-separator-border {
border-top-width: 1px;
border-top-style: solid;
box-sizing: border-box;
}
.quick-input-list .quick-input-list-entry-action-bar {
display: none;
flex: 0;
@ -184,8 +199,16 @@
background-repeat: no-repeat;
}
.quick-input-list .quick-input-list-entry-action-bar {
margin-top: 1px;
}
.quick-input-list .quick-input-list-entry-action-bar ul:first-child .action-label.icon {
margin-left: 2px;
}
.quick-input-list .quick-input-list-entry-action-bar ul:last-child .action-label.icon {
margin-right: 3px;
margin-right: 8px;
}
.quick-input-list .quick-input-list-entry:hover .quick-input-list-entry-action-bar,

View file

@ -7,7 +7,7 @@
import 'vs/css!./quickInput';
import { Component } from 'vs/workbench/common/component';
import { IQuickInputService, IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods } from 'vs/platform/quickinput/common/quickInput';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import * as dom from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -46,6 +46,8 @@ import { getIconClass } from 'vs/workbench/browser/parts/quickinput/quickInputUt
const $ = dom.$;
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
const backButton = {
iconPath: {
dark: URI.parse(require.toUrl('vs/workbench/browser/parts/quickinput/media/dark/arrow-left.svg')),
@ -70,6 +72,7 @@ interface QuickInputUI {
onDidAccept: Event<void>;
onDidTriggerButton: Event<IQuickInputButton>;
ignoreFocusOut: boolean;
keyMods: Writeable<IKeyMods>;
show(controller: QuickInput): void;
setVisibilities(visibilities: Visibilities): void;
setEnabled(enabled: boolean): void;
@ -298,7 +301,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
private _placeholder;
private onDidChangeValueEmitter = new Emitter<string>();
private onDidAcceptEmitter = new Emitter<string>();
private _items: T[] = [];
private _items: (T | IQuickPickSeparator)[] = [];
private itemsUpdated = false;
private _canSelectMany = false;
private _matchOnDescription = false;
@ -352,7 +355,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
return this._items;
}
set items(items: T[]) {
set items(items: (T | IQuickPickSeparator)[]) {
this._items = items;
this.itemsUpdated = true;
this.update();
@ -407,6 +410,10 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.update();
}
get keyMods() {
return this.ui.keyMods;
}
onDidChangeSelection = this.onDidChangeSelectionEmitter.event;
onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;
@ -950,6 +957,30 @@ export class QuickInputService extends Component implements IQuickInputService {
break;
}
}));
this._register(dom.addDisposableListener(container, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
switch (event.keyCode) {
case KeyCode.Ctrl:
case KeyCode.Meta:
this.ui.keyMods.ctrlCmd = true;
break;
case KeyCode.Alt:
this.ui.keyMods.alt = true;
break;
}
}));
this._register(dom.addDisposableListener(container, dom.EventType.KEY_UP, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
switch (event.keyCode) {
case KeyCode.Ctrl:
case KeyCode.Meta:
this.ui.keyMods.ctrlCmd = false;
break;
case KeyCode.Alt:
this.ui.keyMods.alt = false;
break;
}
}));
this._register(this.quickOpenService.onShow(() => this.hide(true)));
@ -968,6 +999,7 @@ export class QuickInputService extends Component implements IQuickInputService {
onDidAccept: this.onDidAcceptEmitter.event,
onDidTriggerButton: this.onDidTriggerButtonEmitter.event,
ignoreFocusOut: false,
keyMods: { ctrlCmd: false, alt: false },
show: controller => this.show(controller),
hide: () => this.hide(),
setVisibilities: visibilities => this.setVisibilities(visibilities),
@ -977,8 +1009,15 @@ export class QuickInputService extends Component implements IQuickInputService {
this.updateStyles();
}
pick<T extends IQuickPickItem, O extends IPickOptions<T>>(picks: TPromise<T[]> | T[], options: O = <O>{}, token: CancellationToken = CancellationToken.None): TPromise<O extends { canPickMany: true } ? T[] : T> {
return new TPromise<O extends { canPickMany: true } ? T[] : T>((resolve, reject) => {
pick<T extends IQuickPickItem, O extends IPickOptions<T>>(picks: TPromise<QuickPickInput<T>[]> | QuickPickInput<T>[], options: O = <O>{}, token: CancellationToken = CancellationToken.None): TPromise<O extends { canPickMany: true } ? T[] : T> {
return new TPromise<O extends { canPickMany: true } ? T[] : T>((doResolve, reject) => {
let resolve = (result: any) => {
resolve = doResolve;
if (options.onKeyMods) {
options.onKeyMods(input.keyMods);
}
doResolve(result);
};
if (token.isCancellationRequested) {
resolve(undefined);
return;
@ -1045,7 +1084,7 @@ export class QuickInputService extends Component implements IQuickInputService {
input.busy = false;
input.items = items;
if (input.canSelectMany) {
input.selectedItems = items.filter(item => item.picked);
input.selectedItems = items.filter(item => item.type !== 'separator' && item.picked) as T[];
}
if (activeItem) {
input.activeItems = [activeItem];
@ -1154,6 +1193,8 @@ export class QuickInputService extends Component implements IQuickInputService {
this.ui.list.matchOnDescription = false;
this.ui.list.matchOnDetail = false;
this.ui.ignoreFocusOut = false;
this.ui.keyMods.ctrlCmd = false;
this.ui.keyMods.alt = false;
const keybinding = this.keybindingService.lookupKeybinding(BackAction.ID);
backButton.tooltip = keybinding ? localize('quickInput.backWithKeybinding', "Back ({0})", keybinding.getLabel()) : localize('quickInput.back', "Back");

View file

@ -11,7 +11,7 @@ import * as dom from 'vs/base/browser/dom';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IQuickPickItem, IQuickPickItemButtonEvent } from 'vs/platform/quickinput/common/quickInput';
import { IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IMatch } from 'vs/base/common/filters';
import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon';
import { compareAnything } from 'vs/base/common/comparers';
@ -24,7 +24,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte
import { memoize } from 'vs/base/common/decorators';
import { range } from 'vs/base/common/arrays';
import * as platform from 'vs/base/common/platform';
import { listFocusBackground } from 'vs/platform/theme/common/colorRegistry';
import { listFocusBackground, pickerGroupBorder, pickerGroupForeground } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
@ -36,6 +36,7 @@ interface IListElement {
index: number;
item: IQuickPickItem;
checked: boolean;
separator: IQuickPickSeparator;
fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
}
@ -56,6 +57,7 @@ class ListElement implements IListElement {
this._onChecked.fire(value);
}
}
separator: IQuickPickSeparator;
labelHighlights?: IMatch[];
descriptionHighlights?: IMatch[];
detailHighlights?: IMatch[];
@ -67,9 +69,11 @@ class ListElement implements IListElement {
}
interface IListElementTemplateData {
entry: HTMLDivElement;
checkbox: HTMLInputElement;
label: IconLabel;
detail: HighlightedLabel;
separator: HTMLDivElement;
actionBar: ActionBar;
element: ListElement;
toDisposeElement: IDisposable[];
@ -89,10 +93,10 @@ class ListElementRenderer implements IRenderer<ListElement, IListElementTemplate
data.toDisposeElement = [];
data.toDisposeTemplate = [];
const entry = dom.append(container, $('.quick-input-list-entry'));
data.entry = dom.append(container, $('.quick-input-list-entry'));
// Checkbox
const label = dom.append(entry, $('label.quick-input-list-label'));
const label = dom.append(data.entry, $('label.quick-input-list-label'));
data.checkbox = <HTMLInputElement>dom.append(label, $('input.quick-input-list-checkbox'));
data.checkbox.type = 'checkbox';
data.toDisposeTemplate.push(dom.addStandardDisposableListener(data.checkbox, dom.EventType.CHANGE, e => {
@ -111,8 +115,11 @@ class ListElementRenderer implements IRenderer<ListElement, IListElementTemplate
const detailContainer = dom.append(row2, $('.quick-input-list-label-meta'));
data.detail = new HighlightedLabel(detailContainer);
// Separator
data.separator = dom.append(data.entry, $('.quick-input-list-separator'));
// Actions
data.actionBar = new ActionBar(entry);
data.actionBar = new ActionBar(data.entry);
data.actionBar.domNode.classList.add('quick-input-list-entry-action-bar');
data.toDisposeTemplate.push(data.actionBar);
@ -138,10 +145,24 @@ class ListElementRenderer implements IRenderer<ListElement, IListElementTemplate
// Meta
data.detail.set(element.item.detail, detailHighlights);
// Separator
if (element.separator && element.separator.label) {
data.separator.textContent = element.separator.label;
data.separator.style.display = null;
} else {
data.separator.style.display = 'none';
}
if (element.separator && element.separator.border) {
dom.addClass(data.entry, 'quick-input-list-separator-border');
} else {
dom.removeClass(data.entry, 'quick-input-list-separator-border');
}
// Actions
data.actionBar.clear();
if (element.item.buttons) {
data.actionBar.push(element.item.buttons.map((button, index) => {
const buttons = element.item.buttons;
if (buttons && buttons.length) {
data.actionBar.push(buttons.map((button, index) => {
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
element.fireButtonTriggered({
button,
@ -152,6 +173,9 @@ class ListElementRenderer implements IRenderer<ListElement, IListElementTemplate
action.tooltip = button.tooltip;
return action;
}), { icon: true, label: false });
dom.addClass(data.entry, 'has-actions');
} else {
dom.removeClass(data.entry, 'has-actions');
}
}
@ -180,6 +204,7 @@ export class QuickInputList {
private container: HTMLElement;
private list: WorkbenchList<ListElement>;
private inputElements: (IQuickPickItem | IQuickPickSeparator)[];
private elements: ListElement[] = [];
private elementsToIndexes = new Map<IQuickPickItem, number>();
matchOnDescription = false;
@ -314,15 +339,23 @@ export class QuickInputList {
}
}
setElements(elements: IQuickPickItem[]): void {
setElements(inputElements: (IQuickPickItem | IQuickPickSeparator)[]): void {
this.elementDisposables = dispose(this.elementDisposables);
const fireButtonTriggered = (event: IQuickPickItemButtonEvent<IQuickPickItem>) => this.fireButtonTriggered(event);
this.elements = elements.map((item, index) => new ListElement({
index,
item,
checked: false,
fireButtonTriggered
}));
this.inputElements = inputElements;
this.elements = inputElements.reduce((result, item, index) => {
if (item.type !== 'separator') {
const previous = index && inputElements[index - 1];
result.push(new ListElement({
index,
item,
checked: false,
separator: previous && previous.type === 'separator' ? previous : undefined,
fireButtonTriggered
}));
}
return result;
}, [] as ListElement[]);
this.elementDisposables.push(...this.elements.map(element => element.onChecked(() => this.fireCheckedEvents())));
this.elementsToIndexes = this.elements.reduce((map, element, index) => {
@ -419,6 +452,8 @@ export class QuickInputList {
element.descriptionHighlights = undefined;
element.detailHighlights = undefined;
element.hidden = false;
const previous = element.index && this.inputElements[element.index - 1];
element.separator = previous && previous.type === 'separator' ? previous : undefined;
});
}
@ -440,19 +475,19 @@ export class QuickInputList {
element.detailHighlights = undefined;
element.hidden = true;
}
element.separator = undefined;
});
}
const shownElements = this.elements.filter(element => !element.hidden);
// Sort by value
const normalizedSearchValue = query.toLowerCase();
shownElements.sort((a, b) => {
if (!query) {
return a.index - b.index; // restore natural order
}
return compareEntries(a, b, normalizedSearchValue);
});
if (query) {
const normalizedSearchValue = query.toLowerCase();
shownElements.sort((a, b) => {
return compareEntries(a, b, normalizedSearchValue);
});
}
this.elementsToIndexes = shownElements.reduce((map, element, index) => {
map.set(element.item, index);
@ -528,4 +563,12 @@ registerThemingParticipant((theme, collector) => {
collector.addRule(`.quick-input-list .monaco-list .monaco-list-row.focused { background-color: ${listInactiveFocusBackground}; }`);
collector.addRule(`.quick-input-list .monaco-list .monaco-list-row.focused:hover { background-color: ${listInactiveFocusBackground}; }`);
}
const pickerGroupBorderColor = theme.getColor(pickerGroupBorder);
if (pickerGroupBorderColor) {
collector.addRule(`.quick-input-list .quick-input-list-entry { border-top-color: ${pickerGroupBorderColor}; }`);
}
const pickerGroupForegroundColor = theme.getColor(pickerGroupForeground);
if (pickerGroupForegroundColor) {
collector.addRule(`.quick-input-list .quick-input-list-separator { color: ${pickerGroupForegroundColor}; }`);
}
});

View file

@ -56,6 +56,7 @@ import { Dimension, addClass } from 'vs/base/browser/dom';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
import { isThenable, timeout } from 'vs/base/common/async';
const HELP_PREFIX = '?';
@ -157,7 +158,7 @@ export class QuickOpenController extends Component implements IQuickOpenService
let arrayPromise: TPromise<string[] | IPickOpenEntry[]>;
if (Array.isArray(arg1)) {
arrayPromise = TPromise.as(arg1);
} else if (TPromise.is(arg1)) {
} else if (isThenable(arg1)) {
arrayPromise = arg1;
} else {
throw new Error('illegal input');
@ -393,11 +394,11 @@ export class QuickOpenController extends Component implements IQuickOpenService
});
// Progress if task takes a long time
TPromise.timeout(800).then(() => {
setTimeout(() => {
if (!picksPromiseDone && this.currentPickerToken === currentPickerToken) {
this.pickOpenWidget.getProgressBar().infinite().show();
}
});
}, 800);
// Show picker empty if resolving takes a while
if (!picksPromiseDone) {
@ -669,11 +670,11 @@ export class QuickOpenController extends Component implements IQuickOpenService
this.previousActiveHandlerDescriptor = handlerDescriptor;
// Progress if task takes a long time
TPromise.timeout(instantProgress ? 0 : 800).then(() => {
setTimeout(() => {
if (!resultPromiseDone && currentResultToken === this.currentResultToken) {
this.quickOpenWidget.getProgressBar().infinite().show();
}
});
}, instantProgress ? 0 : 800);
// Promise done handling
resultPromise.done(() => {
@ -708,7 +709,14 @@ export class QuickOpenController extends Component implements IQuickOpenService
const previousInput = this.quickOpenWidget.getInput();
const wasShowingHistory = previousInput && previousInput.entries && previousInput.entries.some(e => e instanceof EditorHistoryEntry || e instanceof EditorHistoryEntryGroup);
if (wasShowingHistory || matchingHistoryEntries.length > 0) {
(resolvedHandler.hasShortResponseTime() ? TPromise.timeout(QuickOpenController.MAX_SHORT_RESPONSE_TIME) : TPromise.as(undefined)).then(() => {
let responseDelay: Thenable<void>;
if (resolvedHandler.hasShortResponseTime()) {
responseDelay = timeout(QuickOpenController.MAX_SHORT_RESPONSE_TIME);
} else {
responseDelay = Promise.resolve(void 0);
}
responseDelay.then(() => {
if (this.currentResultToken === currentResultToken && !inputSet) {
this.quickOpenWidget.setInput(quickOpenModel, { autoFocusFirstEntry: true });
inputSet = true;
@ -1074,7 +1082,17 @@ class EditorHistoryHandler {
// Massage search for scoring
const query = prepareQuery(searchValue);
const history = this.historyService.getHistory()
// Just return all if we are not searching
const history = this.historyService.getHistory();
if (!query.value) {
return history.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input));
}
// Otherwise filter by search value and sort by score. Include matches on description
// in case the user is explicitly including path separators.
const accessor = query.containsPathSeparator ? MatchOnDescription : DoNotMatchOnDescription;
return history
// For now, only support to match on inputs that provide resource information
.filter(input => {
let resource: URI;
@ -1088,17 +1106,8 @@ class EditorHistoryHandler {
})
// Conver to quick open entries
.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input));
.map(input => this.instantiationService.createInstance(EditorHistoryEntry, input))
// Just return all if we are not searching
if (!query.value) {
return history;
}
// Otherwise filter by search value and sort by score. Include matches on description
// in case the user is explicitly including path separators.
const accessor = query.containsPathSeparator ? MatchOnDescription : DoNotMatchOnDescription;
return history
// Make sure the search value is matching
.filter(e => {
const itemScore = scoreItem(e, query, false, accessor, this.scorerCache);

View file

@ -150,4 +150,52 @@
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon.window-close:hover {
background-color: white;
}
/* Menubar styles */
.monaco-workbench .menubar {
display: flex;
flex-shrink: 1;
box-sizing: border-box;
height: 30px;
-webkit-app-region: no-drag;
overflow: hidden;
flex-wrap: wrap;
}
.monaco-workbench.fullscreen .menubar {
margin: 0px;
padding: 0px 5px;
}
.monaco-workbench .menubar > .menubar-menu-button {
align-items: center;
box-sizing: border-box;
padding: 0px 8px;
cursor: default;
-webkit-app-region: no-drag;
zoom: 1;
white-space: nowrap;
}
.monaco-workbench .menubar .menubar-menu-items-holder {
position: absolute;
left: 0px;
opacity: 1;
z-index: 2000;
}
.monaco-workbench .menubar .menubar-menu-items-holder.monaco-menu-container {
font-family: "Segoe WPC", "Segoe UI", ".SFNSDisplay-Light", "SFUIText-Light", "HelveticaNeue-Light", sans-serif, "Droid Sans Fallback";
outline: 0;
border: none;
}
.monaco-workbench .menubar .menubar-menu-items-holder.monaco-menu-container :focus {
outline: 0;
}
.hc-black .monaco-workbench .menubar .menubar-menu-items-holder.monaco-menu-container {
border: 2px solid #6FC3DF;
}

View file

@ -5,11 +5,8 @@
'use strict';
import 'vs/workbench/browser/parts/menubar/menubar.contribution';
import 'vs/css!./media/menubarpart';
import * as nls from 'vs/nls';
import * as browser from 'vs/base/browser/browser';
import { Part } from 'vs/workbench/browser/part';
import { IMenubarMenu, IMenubarMenuItemAction, IMenubarMenuItemSubmenu, IMenubarKeybinding } from 'vs/platform/menubar/common/menubar';
import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
@ -26,7 +23,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable, dispose } from 'vs/base/common/lifecycle';
import { domEvent } from 'vs/base/browser/event';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
@ -52,7 +49,7 @@ enum MenubarState {
OPEN
}
export class MenubarPart extends Part {
export class MenubarControl extends Disposable {
private keys = [
'files.autoSave',
@ -126,7 +123,8 @@ export class MenubarPart extends Part {
@IUriDisplayService private uriDisplayService: IUriDisplayService,
@IUpdateService private updateService: IUpdateService
) {
super(id, { hasTitle: false }, themeService);
super();
this.topLevelMenus = {
'File': this._register(this.menuService.createMenu(MenuId.MenubarFileMenu, this.contextKeyService)),
@ -315,7 +313,6 @@ export class MenubarPart extends Part {
private onDidChangeFullscreen(): void {
this.setUnfocusedState();
this.updateStyles();
}
private onDidChangeWindowFocus(hasFocus: boolean): void {
@ -525,7 +522,7 @@ export class MenubarPart extends Part {
const result: IAction[] = [];
if (workspaces.length > 0) {
for (let i = 0; i < MenubarPart.MAX_MENU_RECENT_ENTRIES && i < workspaces.length; i++) {
for (let i = 0; i < MenubarControl.MAX_MENU_RECENT_ENTRIES && i < workspaces.length; i++) {
result.push(this.createOpenRecentMenuAction(workspaces[i], 'openRecentWorkspace', false));
}
@ -533,7 +530,7 @@ export class MenubarPart extends Part {
}
if (files.length > 0) {
for (let i = 0; i < MenubarPart.MAX_MENU_RECENT_ENTRIES && i < files.length; i++) {
for (let i = 0; i < MenubarControl.MAX_MENU_RECENT_ENTRIES && i < files.length; i++) {
result.push(this.createOpenRecentMenuAction(files[i], 'openRecentFile', false));
}
@ -991,14 +988,16 @@ export class MenubarPart extends Part {
return this._onVisibilityChange.event;
}
public layout(dimension: Dimension): Dimension[] {
public layout(dimension: Dimension) {
if (this.container) {
this.container.style({ height: `${dimension.height}px` });
}
if (!this.isVisible) {
this.hideMenubar();
} else {
this.showMenubar();
}
return super.layout(dimension);
}
public getMenubarItemsDimensions(): Dimension {
@ -1011,7 +1010,7 @@ export class MenubarPart extends Part {
return new Dimension(0, 0);
}
public createContentArea(parent: HTMLElement): HTMLElement {
public create(parent: HTMLElement): HTMLElement {
this.container = $(parent);
// Build the menubar
@ -1031,7 +1030,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const menubarActiveWindowFgColor = theme.getColor(TITLE_BAR_ACTIVE_FOREGROUND);
if (menubarActiveWindowFgColor) {
collector.addRule(`
.monaco-workbench .part.menubar > .menubar-menu-button {
.monaco-workbench .menubar > .menubar-menu-button {
color: ${menubarActiveWindowFgColor};
}
`);
@ -1040,7 +1039,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const menubarInactiveWindowFgColor = theme.getColor(TITLE_BAR_INACTIVE_FOREGROUND);
if (menubarInactiveWindowFgColor) {
collector.addRule(`
.monaco-workbench .part.menubar.inactive > .menubar-menu-button {
.monaco-workbench .menubar.inactive > .menubar-menu-button {
color: ${menubarInactiveWindowFgColor};
}
`);
@ -1050,9 +1049,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const menubarSelectedFgColor = theme.getColor(MENUBAR_SELECTION_FOREGROUND);
if (menubarSelectedFgColor) {
collector.addRule(`
.monaco-workbench .part.menubar > .menubar-menu-button.open,
.monaco-workbench .part.menubar > .menubar-menu-button:focus,
.monaco-workbench .part.menubar > .menubar-menu-button:hover {
.monaco-workbench .menubar > .menubar-menu-button.open,
.monaco-workbench .menubar > .menubar-menu-button:focus,
.monaco-workbench .menubar > .menubar-menu-button:hover {
color: ${menubarSelectedFgColor};
}
`);
@ -1061,9 +1060,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const menubarSelectedBgColor = theme.getColor(MENUBAR_SELECTION_BACKGROUND);
if (menubarSelectedBgColor) {
collector.addRule(`
.monaco-workbench .part.menubar > .menubar-menu-button.open,
.monaco-workbench .part.menubar > .menubar-menu-button:focus,
.monaco-workbench .part.menubar > .menubar-menu-button:hover {
.monaco-workbench .menubar > .menubar-menu-button.open,
.monaco-workbench .menubar > .menubar-menu-button:focus,
.monaco-workbench .menubar > .menubar-menu-button:hover {
background-color: ${menubarSelectedBgColor};
}
`);
@ -1072,18 +1071,18 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const menubarSelectedBorderColor = theme.getColor(MENUBAR_SELECTION_BORDER);
if (menubarSelectedBorderColor) {
collector.addRule(`
.monaco-workbench .part.menubar > .menubar-menu-button:hover {
.monaco-workbench .menubar > .menubar-menu-button:hover {
outline: dashed 1px;
}
.monaco-workbench .part.menubar > .menubar-menu-button.open,
.monaco-workbench .part.menubar > .menubar-menu-button:focus {
.monaco-workbench .menubar > .menubar-menu-button.open,
.monaco-workbench .menubar > .menubar-menu-button:focus {
outline: solid 1px;
}
.monaco-workbench .part.menubar > .menubar-menu-button.open,
.monaco-workbench .part.menubar > .menubar-menu-button:focus,
.monaco-workbench .part.menubar > .menubar-menu-button:hover {
.monaco-workbench .menubar > .menubar-menu-button.open,
.monaco-workbench .menubar > .menubar-menu-button:focus,
.monaco-workbench .menubar > .menubar-menu-button:hover {
outline-offset: -1px;
outline-color: ${menubarSelectedBorderColor};
}

View file

@ -31,7 +31,7 @@ import URI from 'vs/base/common/uri';
import { Color } from 'vs/base/common/color';
import { trim } from 'vs/base/common/strings';
import { addDisposableListener, EventType, EventHelper, Dimension } from 'vs/base/browser/dom';
import { MenubarPart } from 'vs/workbench/browser/parts/menubar/menubarPart';
import { MenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { template, getBaseLabel } from 'vs/base/common/labels';
import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
@ -52,7 +52,7 @@ export class TitlebarPart extends Part implements ITitleService {
private windowControls: Builder;
private maxRestoreControl: Builder;
private appIcon: Builder;
private menubarPart: MenubarPart;
private menubarPart: MenubarControl;
private menubar: Builder;
private resizer: Builder;
@ -273,10 +273,10 @@ export class TitlebarPart extends Part implements ITitleService {
}
// Menubar: the menubar part which is responsible for populating both the custom and native menubars
this.menubarPart = this.instantiationService.createInstance(MenubarPart, 'workbench.parts.menubar');
this.menubarPart = this.instantiationService.createInstance(MenubarControl, 'workbench.parts.titlebar.menubar');
this.menubar = $(this.titleContainer).div({
'class': ['part', 'menubar'],
id: 'workbench.parts.menubar',
'class': ['menubar'],
id: 'workbench.parts.titlebar.menubar',
role: 'menubar'
});

View file

@ -504,7 +504,7 @@ class TreeRenderer implements IRenderer {
if ((resource || node.themeIcon) && !icon) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
templateData.resourceLabel.setLabel({ name: label, resource: resource ? resource : URI.parse('_icon_resource') }, { fileKind: this.getFileKind(node), title, fileDecorations: fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'] });
templateData.resourceLabel.setLabel({ name: label, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, fileDecorations: fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'] });
} else {
templateData.resourceLabel.setLabel({ name: label }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'] });
}

View file

@ -9,7 +9,7 @@ import 'vs/css!./media/actions';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { Action, IAction } from 'vs/base/common/actions';
import { Action } from 'vs/base/common/actions';
import { IWindowService, IWindowsService, MenuBarVisibility } from 'vs/platform/windows/common/windows';
import * as nls from 'vs/nls';
import product from 'vs/platform/node/product';
@ -20,10 +20,8 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { isMacintosh, isLinux, language } from 'vs/base/common/platform';
import { IQuickOpenService, IFilePickOpenEntry, ISeparator, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen';
import * as browser from 'vs/base/browser/browser';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import { ITimerService, IStartupMetrics } from 'vs/workbench/services/timer/common/timerService';
import { IEditorGroupsService, GroupDirection, GroupLocation, IFindGroupScope } from 'vs/workbench/services/group/common/editorGroupsService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
@ -37,7 +35,6 @@ import { IViewlet } from 'vs/workbench/common/viewlet';
import { IPanel } from 'vs/workbench/common/panel';
import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { FileKind } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService, ActivationTimes } from 'vs/workbench/services/extensions/common/extensions';
import { getEntries } from 'vs/base/common/performance';
import { IssueType } from 'vs/platform/issue/common/issue';
@ -53,7 +50,7 @@ import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
import { dirname } from 'vs/base/common/resources';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IQuickInputService, IQuickPickItem, IQuickInputButton } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, IQuickInputButton, IQuickPickSeparator, IKeyMods } from 'vs/platform/quickinput/common/quickInput';
import { getIconClasses } from 'vs/workbench/browser/labels';
// --- actions
@ -654,7 +651,6 @@ export class SwitchWindow extends BaseSwitchWindow {
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
}
@ -678,7 +674,6 @@ export class QuickSwitchWindow extends BaseSwitchWindow {
@IKeybindingService keybindingService: IKeybindingService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
}
@ -692,16 +687,23 @@ export const inRecentFilesPickerContextKey = 'inRecentFilesPicker';
export abstract class BaseOpenRecentAction extends Action {
private removeFromRecentlyOpened: IQuickInputButton = {
iconClass: 'action-remove-from-recently-opened',
tooltip: nls.localize('remove', "Remove from Recently Opened")
};
constructor(
id: string,
label: string,
private windowService: IWindowService,
private quickOpenService: IQuickOpenService,
private windowsService: IWindowsService,
private quickInputService: IQuickInputService,
private contextService: IWorkspaceContextService,
private environmentService: IEnvironmentService,
private uriDisplayService: IUriDisplayService,
private keybindingService: IKeybindingService,
private instantiationService: IInstantiationService
private modelService: IModelService,
private modeService: IModeService,
) {
super(id, label);
}
@ -715,7 +717,7 @@ export abstract class BaseOpenRecentAction extends Action {
private openRecent(recentWorkspaces: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)[], recentFiles: string[]): void {
function toPick(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string, separator: ISeparator, fileKind: FileKind, environmentService: IEnvironmentService, uriDisplayService: IUriDisplayService, action: IAction): IFilePickOpenEntry {
const toPick = (workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string, fileKind: FileKind, environmentService: IEnvironmentService, uriDisplayService: IUriDisplayService, buttons: IQuickInputButton[]) => {
let resource: URI;
let label: string;
let description: string;
@ -734,63 +736,51 @@ export abstract class BaseOpenRecentAction extends Action {
}
return {
resource,
fileKind,
iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
label,
description,
separator,
run: context => {
setTimeout(() => {
// Bug: somehow when not running this code in a timeout, it is not possible to use this picker
// with quick navigate keys (not able to trigger quick navigate once running it once).
runPick(resource, fileKind === FileKind.FILE, context);
});
},
action
buttons,
workspace,
resource,
fileKind,
};
}
const runPick = (resource: URI, isFile: boolean, context: IEntryRunContext) => {
const forceNewWindow = context.keymods.ctrlCmd;
this.windowService.openWindow([resource], { forceNewWindow, forceOpenWorkspaceAsFile: isFile });
};
const workspacePicks: IFilePickOpenEntry[] = recentWorkspaces.map((workspace, index) => toPick(workspace, index === 0 ? { label: nls.localize('workspaces', "workspaces") } : void 0, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.environmentService, this.uriDisplayService, !this.isQuickNavigate() ? this.instantiationService.createInstance(RemoveFromRecentlyOpened, workspace) : void 0));
const filePicks: IFilePickOpenEntry[] = recentFiles.map((p, index) => toPick(p, index === 0 ? { label: nls.localize('files', "files"), border: true } : void 0, FileKind.FILE, this.environmentService, this.uriDisplayService, !this.isQuickNavigate() ? this.instantiationService.createInstance(RemoveFromRecentlyOpened, p) : void 0));
const runPick = (resource: URI, isFile: boolean, keyMods: IKeyMods) => {
const forceNewWindow = keyMods.ctrlCmd;
return this.windowService.openWindow([resource], { forceNewWindow, forceOpenWorkspaceAsFile: isFile });
};
const workspacePicks = recentWorkspaces.map(workspace => toPick(workspace, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.environmentService, this.uriDisplayService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : void 0));
const filePicks = recentFiles.map(p => toPick(p, FileKind.FILE, this.environmentService, this.uriDisplayService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : void 0));
// focus second entry if the first recent workspace is the current workspace
let autoFocusSecondEntry: boolean = recentWorkspaces[0] && this.contextService.isCurrentWorkspace(recentWorkspaces[0]);
this.quickOpenService.pick([...workspacePicks, ...filePicks], {
let keyMods: IKeyMods;
const workspaceSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('workspaces', "workspaces") };
const fileSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('files', "files"), border: true };
const picks = [workspaceSeparator, ...workspacePicks, fileSeparator, ...filePicks];
this.quickInputService.pick(picks, {
contextKey: inRecentFilesPickerContextKey,
autoFocus: { autoFocusFirstEntry: !autoFocusSecondEntry, autoFocusSecondEntry: autoFocusSecondEntry },
activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0],
placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"),
matchOnDescription: true,
quickNavigateConfiguration: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : void 0
}).done(null, errors.onUnexpectedError);
}
}
class RemoveFromRecentlyOpened extends Action implements IPickOpenAction {
static readonly ID = 'workbench.action.removeFromRecentlyOpened';
static readonly LABEL = nls.localize('remove', "Remove from Recently Opened");
constructor(
private path: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | string),
@IWindowsService private windowsService: IWindowsService
) {
super(RemoveFromRecentlyOpened.ID, RemoveFromRecentlyOpened.LABEL);
this.class = 'action-remove-from-recently-opened';
}
run(item: IPickOpenItem): TPromise<boolean> {
return this.windowsService.removeFromRecentlyOpened([this.path]).then(() => {
item.remove();
return true;
});
onKeyMods: mods => keyMods = mods,
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : void 0,
onDidTriggerItemButton: context => {
this.windowsService.removeFromRecentlyOpened([context.item.workspace]).then(() => {
context.removeItem();
}).then(null, errors.onUnexpectedError);
}
})
.then(pick => {
if (pick) {
return runPick(pick.resource, pick.fileKind === FileKind.FILE, keyMods);
}
return null;
})
.done(null, errors.onUnexpectedError);
}
}
@ -803,14 +793,16 @@ export class OpenRecentAction extends BaseOpenRecentAction {
id: string,
label: string,
@IWindowService windowService: IWindowService,
@IQuickOpenService quickOpenService: IQuickOpenService,
@IWindowsService windowsService: IWindowsService,
@IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IEnvironmentService environmentService: IEnvironmentService,
@IKeybindingService keybindingService: IKeybindingService,
@IInstantiationService instantiationService: IInstantiationService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IUriDisplayService uriDisplayService: IUriDisplayService
) {
super(id, label, windowService, quickOpenService, contextService, environmentService, uriDisplayService, keybindingService, instantiationService);
super(id, label, windowService, windowsService, quickInputService, contextService, environmentService, uriDisplayService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {
@ -827,14 +819,16 @@ export class QuickOpenRecentAction extends BaseOpenRecentAction {
id: string,
label: string,
@IWindowService windowService: IWindowService,
@IQuickOpenService quickOpenService: IQuickOpenService,
@IWindowsService windowsService: IWindowsService,
@IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IEnvironmentService environmentService: IEnvironmentService,
@IKeybindingService keybindingService: IKeybindingService,
@IInstantiationService instantiationService: IInstantiationService,
@IModelService modelService: IModelService,
@IModeService modeService: IModeService,
@IUriDisplayService uriDisplayService: IUriDisplayService
) {
super(id, label, windowService, quickOpenService, contextService, environmentService, uriDisplayService, keybindingService, instantiationService);
super(id, label, windowService, windowsService, quickInputService, contextService, environmentService, uriDisplayService, keybindingService, modelService, modeService);
}
protected isQuickNavigate(): boolean {

View file

@ -341,6 +341,131 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
order: 3
});
// Help
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.openDocumentationUrl',
title: nls.localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation")
},
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'update.showCurrentReleaseNotes',
title: nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "&&Release Notes")
},
order: 4
});
// Reference
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.keybindingsReference',
title: nls.localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openIntroductoryVideosUrl',
title: nls.localize({ key: 'miIntroductoryVideos', comment: ['&& denotes a mnemonic'] }, "Introductory &&Videos")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '2_reference',
command: {
id: 'workbench.action.openTipsAndTricksUrl',
title: nls.localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "&&Tips and Tricks")
},
order: 3
});
// Feedback
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openTwitterUrl',
title: nls.localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join us on Twitter")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openRequestFeatureUrl',
title: nls.localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '3_feedback',
command: {
id: 'workbench.action.openIssueReporter',
title: nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue")
},
order: 3
});
// Legal
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '4_legal',
command: {
id: 'workbench.action.openLicenseUrl',
title: nls.localize({ key: 'miLicense', comment: ['&& denotes a mnemonic'] }, "View &&License")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '4_legal',
command: {
id: 'workbench.action.openPrivacyStatementUrl',
title: nls.localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "&&Privacy Statement")
},
order: 2
});
// Tools
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '5_tools',
command: {
id: 'workbench.action.toggleDevTools',
title: nls.localize({ key: 'miToggleDevTools', comment: ['&& denotes a mnemonic'] }, "&&Toggle Developer Tools")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '5_tools',
command: {
id: 'workbench.action.openProcessExplorer',
title: nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")
},
order: 2
});
// About
if (!isMacintosh) {
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: 'z_about',
command: {
id: 'workbench.action.showAboutDialog',
title: nls.localize({ key: 'miAbout', comment: ['&& denotes a mnemonic'] }, "&&About")
},
order: 1
});
}
// Configuration: Workbench
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
@ -510,7 +635,11 @@ configurationRegistry.registerConfiguration({
},
'workbench.settings.settingsSearchTocBehavior': {
'type': 'string',
'enum': ['hide', 'filter', 'show'],
'enum': ['hide', 'filter'],
'enumDescriptions': [
nls.localize('settingsSearchTocBehavior.hide', "Hide the Table of Contents while searching."),
nls.localize('settingsSearchTocBehavior.filter', "Filter the Table of Contents to just categories that have matching settings. Clicking a category will filter the results to that category."),
],
'description': nls.localize('settingsSearchTocBehavior', "Controls the behavior of the settings editor Table of Contents while searching."),
'default': 'filter',
'scope': ConfigurationScope.WINDOW

View file

@ -9,6 +9,7 @@ import * as nls from 'vs/nls';
import URI from 'vs/base/common/uri';
import * as errors from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import * as arrays from 'vs/base/common/arrays';
import * as objects from 'vs/base/common/objects';
import * as DOM from 'vs/base/browser/dom';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
@ -41,6 +42,8 @@ import { AccessibilitySupport, isRootUser, isWindows, isMacintosh } from 'vs/bas
import product from 'vs/platform/node/product';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)),
@ -74,7 +77,9 @@ export class ElectronWindow extends Themable {
@IWorkbenchThemeService protected themeService: IWorkbenchThemeService,
@INotificationService private notificationService: INotificationService,
@ICommandService private commandService: ICommandService,
@IExtensionService private extensionService: IExtensionService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IKeybindingService private keybindingService: IKeybindingService,
@ITelemetryService private telemetryService: ITelemetryService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@IFileService private fileService: IFileService,
@ -136,6 +141,22 @@ export class ElectronWindow extends Themable {
});
});
// Support resolve keybindings event
ipc.on('vscode:resolveKeybindings', (event: any, rawActionIds: string) => {
let actionIds: string[] = [];
try {
actionIds = JSON.parse(rawActionIds);
} catch (error) {
// should not happen
}
// Resolve keys using the keybinding service and send back to browser process
this.resolveKeybindings(actionIds).done(keybindings => {
if (keybindings.length) {
ipc.send('vscode:keybindingsResolved', JSON.stringify(keybindings));
}
}, () => errors.onUnexpectedError);
});
ipc.on('vscode:reportError', (event: any, error: string) => {
if (error) {
const errorParsed = JSON.parse(error);
@ -354,6 +375,28 @@ export class ElectronWindow extends Themable {
}
}
private resolveKeybindings(actionIds: string[]): TPromise<{ id: string; label: string, isNative: boolean; }[]> {
return TPromise.join([this.lifecycleService.when(LifecyclePhase.Running), this.extensionService.whenInstalledExtensionsRegistered()]).then(() => {
return arrays.coalesce(actionIds.map(id => {
const binding = this.keybindingService.lookupKeybinding(id);
if (!binding) {
return null;
}
// first try to resolve a native accelerator
const electronAccelerator = binding.getElectronAccelerator();
if (electronAccelerator) {
return { id, label: electronAccelerator, isNative: true };
}
// we need this fallback to support keybindings that cannot show in electron menus (e.g. chords)
const acceleratorLabel = binding.getLabel();
if (acceleratorLabel) {
return { id, label: acceleratorLabel, isNative: false };
}
return null;
}));
});
}
private onAddFoldersRequest(request: IAddFoldersRequest): void {
// Buffer all pending requests

View file

@ -24,6 +24,7 @@ import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol';
import URI from 'vs/base/common/uri';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { timeout } from 'vs/base/common/async';
const nativeExit = process.exit.bind(process);
function patchProcess(allowExit: boolean) {
@ -179,7 +180,7 @@ export class ExtensionHostMain {
// Give extensions 1 second to wrap up any async dispose, then exit
setTimeout(() => {
TPromise.any<void>([TPromise.timeout(4000), extensionsDeactivated]).then(() => exit(), () => exit());
TPromise.any<void>([timeout(4000), extensionsDeactivated]).then(() => exit(), () => exit());
}, 1000);
}

View file

@ -4,37 +4,38 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ICodeEditor, IContentWidget, IContentWidgetPosition, ContentWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, IContentWidgetPosition, ContentWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
export class CommentGlyphWidget implements IContentWidget {
private _id: string;
export class CommentGlyphWidget {
private _lineNumber: number;
private _domNode: HTMLDivElement;
private _editor: ICodeEditor;
private commentsDecorations: string[] = [];
private _commentsOptions: ModelDecorationOptions;
constructor(id: string, editor: ICodeEditor, lineNumber: number, disabled: boolean, onClick: () => void) {
this._id = id;
this._domNode = document.createElement('div');
this._domNode.className = disabled ? 'comment-hint commenting-disabled' : 'comment-hint';
this._domNode.addEventListener('click', onClick);
constructor(editor: ICodeEditor, lineNumber: number, commentsOptions: ModelDecorationOptions, onClick: () => void) {
this._commentsOptions = commentsOptions;
this._lineNumber = lineNumber;
this._editor = editor;
this._editor.addContentWidget(this);
this.update();
}
getDomNode(): HTMLElement {
return this._domNode;
}
update() {
let commentsDecorations = [{
range: {
startLineNumber: this._lineNumber, startColumn: 1,
endLineNumber: this._lineNumber, endColumn: 1
},
options: this._commentsOptions
}];
getId(): string {
return this._id;
this.commentsDecorations = this._editor.getModel().deltaDecorations(this.commentsDecorations, commentsDecorations);
}
setLineNumber(lineNumber: number): void {
this._lineNumber = lineNumber;
this.update();
}
getPosition(): IContentWidgetPosition {
@ -46,4 +47,10 @@ export class CommentGlyphWidget implements IContentWidget {
preference: [ContentWidgetPositionPreference.EXACT]
};
}
dispose() {
if (this.commentsDecorations) {
this._editor.deltaDecorations(this.commentsDecorations, []);
}
}
}

View file

@ -25,7 +25,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IModelService } from 'vs/editor/common/services/modelService';
import { SimpleCommentEditor } from './simpleCommentEditor';
import URI from 'vs/base/common/uri';
import { transparent, editorForeground, textLinkActiveForeground, textLinkForeground, focusBorder, textBlockQuoteBackground, textBlockQuoteBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { transparent, editorForeground, textLinkActiveForeground, textLinkForeground, focusBorder, textBlockQuoteBackground, textBlockQuoteBorder, contrastBorder, inputValidationErrorBorder, inputValidationErrorBackground } from 'vs/platform/theme/common/colorRegistry';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
@ -34,6 +34,8 @@ import { Range, IRange } from 'vs/editor/common/core/range';
import { IPosition } from 'vs/editor/common/core/position';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
const EXPAND_ACTION_CLASS = 'expand-review-action octicon octicon-chevron-down';
@ -45,9 +47,11 @@ export class CommentNode {
private _body: HTMLElement;
private _md: HTMLElement;
private _clearTimeout: any;
public get domNode(): HTMLElement {
return this._domNode;
}
constructor(
public comment: modes.Comment,
private markdownRenderer: MarkdownRenderer,
@ -115,6 +119,7 @@ export class ReviewZoneWidget extends ZoneWidget {
private _localToDispose: IDisposable[];
private _markdownRenderer: MarkdownRenderer;
private _styleElement: HTMLStyleElement;
private _error: HTMLElement;
public get owner(): number {
return this._owner;
@ -284,14 +289,13 @@ export class ReviewZoneWidget extends ZoneWidget {
}
protected _doLayout(heightInPixel: number, widthInPixel: number): void {
this._commentEditor.layout({ height: (this._commentEditor.hasWidgetFocus() ? 5 : 1) * 18, width: widthInPixel - 40 /* margin */ });
this._commentEditor.layout({ height: (this._commentEditor.hasWidgetFocus() ? 5 : 1) * 18, width: widthInPixel - 42 /* margin */ });
}
display(lineNumber: number) {
this._commentGlyph = new CommentGlyphWidget(`review_${lineNumber}`, this.editor, lineNumber, false, () => {
display(lineNumber: number, commentsOptions: ModelDecorationOptions) {
this._commentGlyph = new CommentGlyphWidget(this.editor, lineNumber, commentsOptions, () => {
this.toggleExpand();
});
this.editor.layoutContentWidget(this._commentGlyph);
this._localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
this._localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
@ -300,7 +304,6 @@ export class ReviewZoneWidget extends ZoneWidget {
if (this.position) {
if (this.position.lineNumber !== this._commentGlyph.getPosition().position.lineNumber) {
this._commentGlyph.setLineNumber(this.position.lineNumber);
this.editor.layoutContentWidget(this._commentGlyph);
}
} else {
// Otherwise manually calculate position change :(
@ -312,7 +315,6 @@ export class ReviewZoneWidget extends ZoneWidget {
}
}).reduce((prev, curr) => prev + curr, 0);
this._commentGlyph.setLineNumber(this._commentGlyph.getPosition().position.lineNumber + positionChange);
this.editor.layoutContentWidget(this._commentGlyph);
}
}));
var headHeight = Math.ceil(this.editor.getConfiguration().lineHeight * 1.2);
@ -364,8 +366,15 @@ export class ReviewZoneWidget extends ZoneWidget {
this.dispose();
}
}
if (this._commentEditor.getModel().getValueLength() !== 0 && ev.keyCode === KeyCode.Enter && ev.ctrlKey) {
let lineNumber = this._commentGlyph.getPosition().position.lineNumber;
this.createComment(lineNumber);
}
}));
this._error = $('.validation-error.hidden').appendTo(this._commentForm).getHTMLElement();
const formActions = $('.form-actions').appendTo(this._commentForm).getHTMLElement();
const button = new Button(formActions);
@ -382,36 +391,8 @@ export class ReviewZoneWidget extends ZoneWidget {
}));
button.onDidClick(async () => {
let newCommentThread;
if (this._commentThread.threadId) {
// reply
newCommentThread = await this.commentService.replyToCommentThread(
this._owner,
this.editor.getModel().uri,
new Range(lineNumber, 1, lineNumber, 1),
this._commentThread,
this._commentEditor.getValue()
);
} else {
newCommentThread = await this.commentService.createNewCommentThread(
this._owner,
this.editor.getModel().uri,
new Range(lineNumber, 1, lineNumber, 1),
this._commentEditor.getValue()
);
this.createReplyButton();
this.createParticipantsLabel();
}
this._commentEditor.setValue('');
if (dom.hasClass(this._commentForm, 'expand')) {
dom.removeClass(this._commentForm, 'expand');
}
if (newCommentThread) {
this.update(newCommentThread);
}
let lineNumber = this._commentGlyph.getPosition().position.lineNumber;
this.createComment(lineNumber);
});
this._resizeObserver = new MutationObserver(this._refresh.bind(this));
@ -433,6 +414,52 @@ export class ReviewZoneWidget extends ZoneWidget {
}
}
private async createComment(lineNumber: number): Promise<void> {
try {
let newCommentThread;
if (this._commentThread.threadId) {
// reply
newCommentThread = await this.commentService.replyToCommentThread(
this._owner,
this.editor.getModel().uri,
new Range(lineNumber, 1, lineNumber, 1),
this._commentThread,
this._commentEditor.getValue()
);
} else {
newCommentThread = await this.commentService.createNewCommentThread(
this._owner,
this.editor.getModel().uri,
new Range(lineNumber, 1, lineNumber, 1),
this._commentEditor.getValue()
);
if (newCommentThread) {
this.createReplyButton();
this.createParticipantsLabel();
}
}
if (newCommentThread) {
this._commentEditor.setValue('');
if (dom.hasClass(this._commentForm, 'expand')) {
dom.removeClass(this._commentForm, 'expand');
}
this._commentEditor.getDomNode().style.outline = '';
this._error.textContent = '';
dom.addClass(this._error, 'hidden');
this.update(newCommentThread);
}
} catch (e) {
this._error.textContent = e.message
? nls.localize('commentCreationError', "Adding a comment failed: {0}.", e.message)
: nls.localize('commentCreationDefaultError', "Adding a comment failed. Please try again or report an issue with the extension if the problem persists.");
this._commentEditor.getDomNode().style.outline = `1px solid ${this.themeService.getTheme().getColor(inputValidationErrorBorder)}`;
dom.removeClass(this._error, 'hidden');
}
}
createParticipantsLabel() {
const primaryHeading = 'Participants:';
$(this._primaryHeading).safeInnerHtml(primaryHeading);
@ -480,7 +507,7 @@ export class ReviewZoneWidget extends ZoneWidget {
if (model) {
let valueLength = model.getValueLength();
const hasExistingComments = this._commentThread.comments.length > 0;
let placeholder = valueLength > 0 ? '' : (hasExistingComments ? 'Reply...' : 'Type a new comment');
let placeholder = valueLength > 0 ? '' : (hasExistingComments ? 'Reply... (press Ctrl+Enter to submit)' : 'Type a new comment (press Ctrl+Enter to submit)');
const decorations = [{
range: {
startLineNumber: 0,
@ -500,61 +527,72 @@ export class ReviewZoneWidget extends ZoneWidget {
}
}
private mouseDownInfo: { lineNumber: number, iconClicked: boolean };
private mouseDownInfo: { lineNumber: number };
private onEditorMouseDown(e: IEditorMouseEvent): void {
if (!e.event.leftButton) {
return;
}
this.mouseDownInfo = null;
const range = e.target.range;
let range = e.target.range;
if (!range) {
return;
}
let iconClicked = false;
switch (e.target.type) {
case MouseTargetType.GUTTER_GLYPH_MARGIN:
iconClicked = true;
break;
default:
return;
if (!e.event.leftButton) {
return;
}
this.mouseDownInfo = { lineNumber: range.startLineNumber, iconClicked };
if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) {
return;
}
const data = e.target.detail as IMarginData;
const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
// don't collide with folding and git decorations
if (gutterOffsetX > 14) {
return;
}
this.mouseDownInfo = { lineNumber: range.startLineNumber };
}
private onEditorMouseUp(e: IEditorMouseEvent): void {
if (!this.mouseDownInfo) {
return;
}
let lineNumber = this.mouseDownInfo.lineNumber;
let iconClicked = this.mouseDownInfo.iconClicked;
let range = e.target.range;
const { lineNumber } = this.mouseDownInfo;
this.mouseDownInfo = null;
const range = e.target.range;
if (!range || range.startLineNumber !== lineNumber) {
return;
}
if (this.position && this.position.lineNumber !== lineNumber) {
if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) {
return;
}
if (!this.position && lineNumber !== this._commentThread.range.startLineNumber) {
if (!e.target.element) {
return;
}
if (iconClicked) {
if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN) {
return;
if (this._commentGlyph && this._commentGlyph.getPosition().position.lineNumber !== lineNumber) {
return;
}
if (e.target.element.className.indexOf('comment-thread') >= 0) {
if (this._isCollapsed) {
this.show({ lineNumber: lineNumber, column: 1 }, 2);
} else {
this.hide();
if (this._commentThread === null) {
this.dispose();
}
}
}
if (this._isCollapsed) {
this.show({ lineNumber: lineNumber, column: 1 }, 2);
} else {
this.hide();
}
}
private _applyTheme(theme: ITheme) {
@ -597,6 +635,16 @@ export class ReviewZoneWidget extends ZoneWidget {
content.push(`.monaco-editor .review-widget .body .comment-form .monaco-editor { outline: 1px solid ${hcBorder}; }`);
}
const errorBorder = theme.getColor(inputValidationErrorBorder);
if (errorBorder) {
content.push(`.monaco-editor .review-widget .body .comment-form .validation-error { border: 1px solid ${errorBorder}; }`);
}
const errorBackground = theme.getColor(inputValidationErrorBackground);
if (errorBackground) {
content.push(`.monaco-editor .review-widget .body .comment-form .validation-error { background: ${errorBackground}; }`);
}
this._styleElement.innerHTML = content.join('\n');
// Editor decorations should also be responsive to theme changes
@ -622,7 +670,7 @@ export class ReviewZoneWidget extends ZoneWidget {
}
if (this._commentGlyph) {
this.editor.removeContentWidget(this._commentGlyph);
this._commentGlyph.dispose();
this._commentGlyph = null;
}

View file

@ -10,27 +10,30 @@ import { $ } from 'vs/base/browser/builder';
import { findFirstInSorted } from 'vs/base/common/arrays';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ICodeEditor, IEditorMouseEvent, IViewZone } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, IEditorMouseEvent, IViewZone, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { registerEditorContribution, EditorAction, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { IRange } from 'vs/editor/common/core/range';
import * as modes from 'vs/editor/common/modes';
import { peekViewEditorBackground, peekViewResultsBackground, peekViewResultsSelectionBackground } from 'vs/editor/contrib/referenceSearch/referencesWidget';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { editorForeground, registerColor } from 'vs/platform/theme/common/colorRegistry';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { CommentThreadCollapsibleState } from 'vs/workbench/api/node/extHostTypes';
import { ReviewModel } from 'vs/workbench/parts/comments/common/reviewModel';
import { CommentGlyphWidget } from 'vs/workbench/parts/comments/electron-browser/commentGlyphWidget';
import { ReviewZoneWidget, COMMENTEDITOR_DECORATION_KEY } from 'vs/workbench/parts/comments/electron-browser/commentThreadWidget';
import { ICommentService } from 'vs/workbench/parts/comments/electron-browser/commentService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { IModelDecorationOptions } from 'vs/editor/common/model';
import { Color, RGBA } from 'vs/base/common/color';
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
export const ctxReviewPanelVisible = new RawContextKey<boolean>('reviewPanelVisible', false);
@ -53,6 +56,103 @@ export class ReviewViewZone implements IViewZone {
}
}
const overviewRulerDefault = new Color(new RGBA(197, 197, 197, 1));
export const overviewRulerCommentingRangeForeground = registerColor('editorGutter.commentRangeForeground', { dark: overviewRulerDefault, light: overviewRulerDefault, hc: overviewRulerDefault }, nls.localize('editorGutterCommentRangeForeground', 'Editor gutter decoration color for commenting ranges.'));
class CommentingRangeDecoration {
private _decorationId: string;
constructor(private _editor: ICodeEditor, private _ownerId: number, private _range: IRange, private _reply: modes.Command, commentingOptions: ModelDecorationOptions) {
const startLineNumber = _range.startLineNumber;
const endLineNumber = _range.endLineNumber;
let commentingRangeDecorations = [{
range: {
startLineNumber: startLineNumber, startColumn: 1,
endLineNumber: endLineNumber, endColumn: 1
},
options: commentingOptions
}];
let model = this._editor.getModel();
if (model) {
this._decorationId = model.deltaDecorations([this._decorationId], commentingRangeDecorations)[0];
}
}
getCommentAction(): { replyCommand: modes.Command, ownerId: number } {
return {
replyCommand: this._reply,
ownerId: this._ownerId
};
}
getOriginalRange() {
return this._range;
}
getActiveRange() {
return this._editor.getModel().getDecorationRange(this._decorationId);
}
}
class CommentingRangeDecorator {
static createDecoration(className: string, foregroundColor: string, options: { gutter: boolean, overview: boolean }): ModelDecorationOptions {
const decorationOptions: IModelDecorationOptions = {
isWholeLine: true,
};
decorationOptions.linesDecorationsClassName = `comment-range-glyph ${className}`;
return ModelDecorationOptions.createDynamic(decorationOptions);
}
private commentingOptions: ModelDecorationOptions;
public commentsOptions: ModelDecorationOptions;
private commentingRangeDecorations: CommentingRangeDecoration[] = [];
private disposables: IDisposable[] = [];
constructor(
) {
const options = { gutter: true, overview: false };
this.commentingOptions = CommentingRangeDecorator.createDecoration('comment-diff-added', overviewRulerCommentingRangeForeground, options);
this.commentsOptions = CommentingRangeDecorator.createDecoration('comment-thread', overviewRulerCommentingRangeForeground, options);
}
update(editor: ICodeEditor, commentInfos: modes.CommentInfo[]) {
let model = editor.getModel();
if (!model) {
return;
}
let commentingRangeDecorations = [];
for (let i = 0; i < commentInfos.length; i++) {
let info = commentInfos[i];
info.commentingRanges.forEach(range => {
commentingRangeDecorations.push(new CommentingRangeDecoration(editor, info.owner, range, info.reply, this.commentingOptions));
});
}
this.commentingRangeDecorations = commentingRangeDecorations;
}
getMatchedCommentAction(line: number) {
for (let i = 0; i < this.commentingRangeDecorations.length; i++) {
let range = this.commentingRangeDecorations[i].getActiveRange();
if (range.startLineNumber <= line && line <= range.endLineNumber) {
return this.commentingRangeDecorations[i].getCommentAction();
}
}
return null;
}
dispose(): void {
this.disposables = dispose(this.disposables);
this.commentingRangeDecorations = [];
}
}
export class ReviewController implements IEditorContribution {
private globalToDispose: IDisposable[];
private localToDispose: IDisposable[];
@ -62,15 +162,17 @@ export class ReviewController implements IEditorContribution {
private _reviewPanelVisible: IContextKey<boolean>;
private _commentInfos: modes.CommentInfo[];
private _reviewModel: ReviewModel;
private _newCommentGlyph: CommentGlyphWidget;
private _hasSetComments: boolean;
// private _hasSetComments: boolean;
private _commentingRangeDecorator: CommentingRangeDecorator;
private mouseDownInfo: { lineNumber: number } | null = null;
private _commentingRangeSpaceReserved = false;
constructor(
editor: ICodeEditor,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService private themeService: IThemeService,
@ICommentService private commentService: ICommentService,
@INotificationService private notificationService: INotificationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IModeService private modeService: IModeService,
@IModelService private modelService: IModelService,
@ -83,11 +185,11 @@ export class ReviewController implements IEditorContribution {
this._commentInfos = [];
this._commentWidgets = [];
this._newCommentWidget = null;
this._newCommentGlyph = null;
this._hasSetComments = false;
// this._hasSetComments = false;
this._reviewPanelVisible = ctxReviewPanelVisible.bindTo(contextKeyService);
this._reviewModel = new ReviewModel();
this._commentingRangeDecorator = new CommentingRangeDecorator();
this._reviewModel.onDidChangeStyle(style => {
if (this._newCommentWidget) {
@ -102,7 +204,7 @@ export class ReviewController implements IEditorContribution {
this._commentInfos.forEach(info => {
info.threads.forEach(thread => {
let zoneWidget = new ReviewZoneWidget(this.instantiationService, this.modeService, this.modelService, this.themeService, this.commentService, this.openerService, this.editor, info.owner, thread, {});
zoneWidget.display(thread.range.startLineNumber);
zoneWidget.display(thread.range.startLineNumber, this._commentingRangeDecorator.commentsOptions);
this._commentWidgets.push(zoneWidget);
});
});
@ -115,11 +217,6 @@ export class ReviewController implements IEditorContribution {
this._newCommentWidget = null;
}
if (this._newCommentGlyph) {
this.editor.removeContentWidget(this._newCommentGlyph);
this._newCommentGlyph = null;
}
this.getComments();
}));
@ -232,23 +329,14 @@ export class ReviewController implements IEditorContribution {
this._newCommentWidget = null;
}
if (this._newCommentGlyph) {
this.editor.removeContentWidget(this._newCommentGlyph);
this._newCommentGlyph = null;
}
this._commentWidgets.forEach(zone => {
zone.dispose();
});
this._commentWidgets = [];
this.localToDispose.push(this.editor.onMouseMove(e => this.onEditorMouseMove(e)));
this.localToDispose.push(this.editor.onMouseLeave(() => this.onMouseLeave()));
this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
this.localToDispose.push(this.editor.onDidChangeModelContent(() => {
if (this._newCommentGlyph) {
this.editor.removeContentWidget(this._newCommentGlyph);
this._newCommentGlyph = null;
}
}));
this.localToDispose.push(this.commentService.onDidUpdateCommentThreads(e => {
const editorURI = this.editor && this.editor.getModel() && this.editor.getModel().uri;
@ -277,7 +365,7 @@ export class ReviewController implements IEditorContribution {
});
added.forEach(thread => {
let zoneWidget = new ReviewZoneWidget(this.instantiationService, this.modeService, this.modelService, this.themeService, this.commentService, this.openerService, this.editor, e.owner, thread, {});
zoneWidget.display(thread.range.startLineNumber);
zoneWidget.display(thread.range.startLineNumber, this._commentingRangeDecorator.commentsOptions);
this._commentWidgets.push(zoneWidget);
this._commentInfos.filter(info => info.owner === e.owner)[0].threads.push(thread);
});
@ -285,7 +373,7 @@ export class ReviewController implements IEditorContribution {
}
private addComment(lineNumber: number) {
let newCommentInfo = this.getNewCommentAction(lineNumber);
let newCommentInfo = this._commentingRangeDecorator.getMatchedCommentAction(lineNumber);
if (!newCommentInfo) {
return;
}
@ -310,82 +398,91 @@ export class ReviewController implements IEditorContribution {
this._newCommentWidget.onDidClose(e => {
this._newCommentWidget = null;
});
this._newCommentWidget.display(lineNumber);
this._newCommentWidget.display(lineNumber, this._commentingRangeDecorator.commentsOptions);
}
private onEditorMouseMove(e: IEditorMouseEvent): void {
if (!this._hasSetComments) {
private onEditorMouseDown(e: IEditorMouseEvent): void {
this.mouseDownInfo = null;
const range = e.target.range;
if (!range) {
return;
}
const hasCommentingRanges = this._commentInfos.length && this._commentInfos.some(info => !!info.commentingRanges.length);
if (hasCommentingRanges && e.target.position && e.target.position.lineNumber !== undefined) {
if (this._newCommentGlyph && e.target.element.className !== 'comment-hint') {
this.editor.removeContentWidget(this._newCommentGlyph);
}
if (!e.event.leftButton) {
return;
}
if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) {
return;
}
const data = e.target.detail as IMarginData;
const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
// don't collide with folding and git decorations
if (gutterOffsetX > 14) {
return;
}
this.mouseDownInfo = { lineNumber: range.startLineNumber };
}
private onEditorMouseUp(e: IEditorMouseEvent): void {
if (!this.mouseDownInfo) {
return;
}
const { lineNumber } = this.mouseDownInfo;
this.mouseDownInfo = null;
const range = e.target.range;
if (!range || range.startLineNumber !== lineNumber) {
return;
}
if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) {
return;
}
if (!e.target.element) {
return;
}
if (e.target.element.className.indexOf('comment-diff-added') >= 0) {
const lineNumber = e.target.position.lineNumber;
if (!this.isExistingCommentThreadAtLine(lineNumber)) {
this._newCommentGlyph = this.isLineInCommentingRange(lineNumber)
? this._newCommentGlyph = new CommentGlyphWidget('comment-hint', this.editor, lineNumber, false, () => {
this.addComment(lineNumber);
})
: this._newCommentGlyph = new CommentGlyphWidget('comment-hint', this.editor, lineNumber, true, () => {
this.notificationService.warn('Commenting is not supported outside of diff hunk areas.');
});
this.editor.layoutContentWidget(this._newCommentGlyph);
}
this.addComment(lineNumber);
}
}
private onMouseLeave(): void {
if (this._newCommentGlyph) {
this.editor.removeContentWidget(this._newCommentGlyph);
}
}
private getNewCommentAction(line: number): { replyCommand: modes.Command, ownerId: number } {
for (let i = 0; i < this._commentInfos.length; i++) {
const commentInfo = this._commentInfos[i];
const lineWithinRange = commentInfo.commentingRanges.some(range =>
range.startLineNumber <= line && line <= range.endLineNumber
);
if (lineWithinRange) {
return {
replyCommand: commentInfo.reply,
ownerId: commentInfo.owner
};
}
}
return null;
}
private isLineInCommentingRange(line: number): boolean {
return this._commentInfos.some(commentInfo => {
return commentInfo.commentingRanges.some(range =>
range.startLineNumber <= line && line <= range.endLineNumber
);
});
}
private isExistingCommentThreadAtLine(line: number): boolean {
const existingThread = this._commentInfos.some(commentInfo => {
return commentInfo.threads.some(thread =>
thread.range.startLineNumber === line
);
});
const existingNewComment = this._newCommentWidget && this._newCommentWidget.position && this._newCommentWidget.position.lineNumber === line;
return existingThread || existingNewComment;
}
setComments(commentInfos: modes.CommentInfo[]): void {
this._commentInfos = commentInfos;
this._hasSetComments = true;
let lineDecorationsWidth: number = this.editor.getConfiguration().layoutInfo.decorationsWidth;
if (this._commentInfos.some(info => Boolean(info.commentingRanges && info.commentingRanges.length))) {
if (!this._commentingRangeSpaceReserved) {
this._commentingRangeSpaceReserved = true;
let extraEditorClassName = [];
if (this.editor.getRawConfiguration().extraEditorClassName) {
extraEditorClassName = this.editor.getRawConfiguration().extraEditorClassName.split(' ');
}
if (this.editor.getConfiguration().contribInfo.folding) {
lineDecorationsWidth -= 16;
}
lineDecorationsWidth += 9;
extraEditorClassName.push('inline-comment');
this.editor.updateOptions({
extraEditorClassName: extraEditorClassName.join(' '),
lineDecorationsWidth: lineDecorationsWidth
});
this.editor.layout();
}
}
// this._hasSetComments = true;
// create viewzones
this._commentWidgets.forEach(zone => {
@ -395,12 +492,17 @@ export class ReviewController implements IEditorContribution {
this._commentInfos.forEach(info => {
info.threads.forEach(thread => {
let zoneWidget = new ReviewZoneWidget(this.instantiationService, this.modeService, this.modelService, this.themeService, this.commentService, this.openerService, this.editor, info.owner, thread, {});
zoneWidget.display(thread.range.startLineNumber);
zoneWidget.display(thread.range.startLineNumber, this._commentingRangeDecorator.commentsOptions);
this._commentWidgets.push(zoneWidget);
});
});
}
const commentingRanges = [];
this._commentInfos.forEach(info => {
commentingRanges.push(...info.commentingRanges);
});
this._commentingRangeDecorator.update(this.editor, this._commentInfos);
}
public closeWidget(): void {
this._reviewPanelVisible.reset();
@ -518,4 +620,22 @@ registerThemingParticipant((theme, collector) => {
`}`
);
}
const commentingRangeForeground = theme.getColor(overviewRulerCommentingRangeForeground);
if (commentingRangeForeground) {
collector.addRule(`
.monaco-editor .comment-diff-added {
border-left: 3px solid ${commentingRangeForeground};
}
.monaco-editor .comment-diff-added:before {
background: ${commentingRangeForeground};
}
.monaco-editor .comment-thread {
border-left: 3px solid ${commentingRangeForeground};
}
.monaco-editor .comment-thread:before {
background: ${commentingRangeForeground};
}
`);
}
});

View file

@ -10,7 +10,7 @@
background-position: center center;
}
.monaco-editor .comment-hint{
.monaco-editor .comment-hint {
height: 20px;
width: 20px;
padding-left: 2px;
@ -126,6 +126,29 @@
padding: 8px 0;
}
.monaco-editor .review-widget .body .comment-form .validation-error {
display: inline-block;
overflow: hidden;
text-align: left;
width: 100%;
box-sizing: border-box;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
padding: 0.4em;
font-size: 12px;
line-height: 17px;
min-height: 34px;
margin-top: -1px;
margin-left: -1px;
word-wrap: break-word;
}
.monaco-editor .review-widget .body .comment-form .validation-error.hidden {
display: none;
}
.monaco-editor .review-widget .body .comment-form.expand .review-thread-reply-button {
display: none;
}
@ -239,4 +262,52 @@
.monaco-editor .review-widget>.body {
border-top: 1px solid;
position: relative;
}
}
.monaco-editor .comment-range-glyph {
margin-left: 5px;
width: 4px !important;
cursor: pointer;
z-index: 10;
}
.monaco-editor .comment-range-glyph:before {
position: absolute;
content: '';
height: 100%;
width: 0;
left: -2px;
transition: width 80ms linear, left 80ms linear;
}
.monaco-editor .margin-view-overlays>div:hover>.comment-range-glyph.comment-diff-added:before {
position: absolute;
content: '+';
height: 100%;
width: 9px;
left: -6px;
z-index: 10;
color: black;
}
.monaco-editor .comment-range-glyph.comment-thread {
z-index: 20;
}
.monaco-editor .comment-range-glyph.comment-thread:before {
position: absolute;
content: '·';
height: 100%;
width: 9px;
left: -6px;
z-index: 20;
color: black;
}
.monaco-editor.inline-comment .margin-view-overlays .folding {
margin-left: 14px;
}
.monaco-editor.inline-comment .margin-view-overlays .dirty-diff-glyph {
margin-left: 14px;
}

View file

@ -25,7 +25,6 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IAdapterExecutable, IDebugAdapterProvider, IDebugAdapter, ITerminalSettings, ITerminalLauncher } from 'vs/workbench/parts/debug/common/debug';
import { Debugger } from 'vs/workbench/parts/debug/node/debugger';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
@ -33,6 +32,7 @@ import { TerminalLauncher } from 'vs/workbench/parts/debug/electron-browser/term
import { Registry } from 'vs/platform/registry/common/platform';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { launchSchema, debuggersExtPoint, breakpointsExtPoint } from 'vs/workbench/parts/debug/common/debugSchemas';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema(launchSchemaId, launchSchema);
@ -57,7 +57,7 @@ export class ConfigurationManager implements IConfigurationManager {
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IEditorService private editorService: IEditorService,
@IConfigurationService private configurationService: IConfigurationService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService,
@IInstantiationService private instantiationService: IInstantiationService,
@ICommandService private commandService: ICommandService,
@IStorageService private storageService: IStorageService,
@ -347,10 +347,11 @@ export class ConfigurationManager implements IConfigurationManager {
}
candidates = candidates.sort((first, second) => first.label.localeCompare(second.label));
return this.quickOpenService.pick([...candidates, { label: 'More...', separator: { border: true } }], { placeHolder: nls.localize('selectDebug', "Select Environment") })
const picks = candidates.map(c => ({ label: c.label, debugger: c }));
return this.quickInputService.pick<(typeof picks)[0]>([...picks, { type: 'separator', border: true }, { label: 'More...', debugger: undefined }], { placeHolder: nls.localize('selectDebug', "Select Environment") })
.then(picked => {
if (picked instanceof Debugger) {
return picked;
if (picked.debugger) {
return picked.debugger;
}
if (picked) {
this.commandService.executeCommand('debug.installAdditionalDebuggers');

View file

@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import URI from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources';
@ -27,7 +26,7 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
import { ResourceQueue } from 'vs/base/common/async';
import { ResourceQueue, timeout } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
export class FileEditorTracker extends Disposable implements IWorkbenchContribution {
@ -170,14 +169,14 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
// file is really gone and not just a faulty file event.
// This only applies to external file events, so we need to check for the isExternal
// flag.
let checkExists: TPromise<boolean>;
let checkExists: Thenable<boolean>;
if (isExternal) {
checkExists = TPromise.timeout(100).then(() => this.fileService.existsFile(resource));
checkExists = timeout(100).then(() => this.fileService.existsFile(resource));
} else {
checkExists = TPromise.as(false);
checkExists = Promise.resolve(false);
}
checkExists.done(exists => {
checkExists.then(exists => {
if (!exists && !editor.isDisposed()) {
editor.dispose();
} else if (this.environmentService.verbose) {

View file

@ -15,7 +15,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { toResource, IEditorIdentifier, IEditorInput } from 'vs/workbench/common/editor';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { startsWith, startsWithIgnoreCase, rtrim } from 'vs/base/common/strings';
import { rtrim } from 'vs/base/common/strings';
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
export class Model {
@ -342,9 +342,7 @@ export class ExplorerItem {
*/
public find(resource: URI): ExplorerItem {
// Return if path found
if (resource && this.resource.scheme === resource.scheme && this.resource.authority === resource.authority &&
(isLinux ? startsWith(resource.path, this.resource.path) : startsWithIgnoreCase(resource.path, this.resource.path))
) {
if (resource && resources.isEqualOrParent(resource, this.resource)) {
return this.findByPath(rtrim(resource.path, paths.sep), this.resource.path.length);
}

View file

@ -544,3 +544,14 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
},
order: 2
});
// Go to menu
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.quickOpen',
title: nls.localize({ key: 'miGotoFile', comment: ['&& denotes a mnemonic'] }, "Go to &&File...")
},
order: 1
});

View file

@ -18,7 +18,12 @@ function createStat(path: string, name: string, isFolder: boolean, hasChildren:
}
function toResource(path) {
return URI.file(join('C:\\', path));
if (isWindows) {
return URI.file(join('C:\\', path));
} else {
return URI.file(join('/home/john', path));
}
}
suite('Files - View Model', () => {

View file

@ -71,11 +71,17 @@
display: none;
}
.monaco-tree.focused .selected .outline-element-label, .monaco-tree.focused .selected .outline-element-decoration {
.monaco-tree.focused .selected .outline-element-label, .monaco-tree.focused .selected .outline-element-decoration{
/* make sure selection color wins when a label is being selected */
color: inherit !important;
}
.monaco-tree.focused .selected .outline-element-label .monaco-highlighted-label .highlight,
.monaco-tree.focused .selected .monaco-icon-label .monaco-highlighted-label .highlight{
/* allows text color to use the default when selected */
color: inherit !important;
}
.monaco-workbench .outline-panel.no-icons .outline-element .outline-element-icon {
display: none;
}

View file

@ -13,7 +13,7 @@ import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { Action, IAction, RadioGroup } from 'vs/base/common/actions';
import { firstIndex } from 'vs/base/common/arrays';
import { asDisposablePromise, setDisposableTimeout, createCancelablePromise } from 'vs/base/common/async';
import { asDisposablePromise, setDisposableTimeout, createCancelablePromise, timeout } from 'vs/base/common/async';
import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors';
import { Emitter } from 'vs/base/common/event';
import { defaultGenerator } from 'vs/base/common/idGenerator';
@ -496,7 +496,7 @@ export class OutlinePanel extends ViewletPanel {
let oldRatio = oldSize / oldLength;
if (newRatio <= oldRatio * 0.5 || newRatio >= oldRatio * 1.5) {
if (!await asDisposablePromise(
TPromise.timeout(2000).then(_ => true),
timeout(2000).then(_ => true),
false,
this._editorDisposables).promise
) {

View file

@ -19,6 +19,7 @@ import { localize } from 'vs/nls';
import { readdir, del, readFile } from 'vs/base/node/pfs';
import { basename } from 'vs/base/common/paths';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { timeout } from 'vs/base/common/async';
class StartupProfiler implements IWorkbenchContribution {
@ -52,7 +53,7 @@ class StartupProfiler implements IWorkbenchContribution {
const removeArgs: string[] = ['--prof-startup'];
const markerFile = readFile(profileFilenamePrefix).then(value => removeArgs.push(...value.toString().split('|')))
.then(() => del(profileFilenamePrefix))
.then(() => TPromise.timeout(1000));
.then(() => timeout(1000));
markerFile.then(() => {
return readdir(dir).then(files => files.filter(value => value.indexOf(prefix) === 0));

View file

@ -109,14 +109,6 @@
background-size: 16px;
}
.vs .settings-editor > .settings-header > .settings-header-controls .settings-header-controls-right .toolbar-toggle-more {
background-image: url('ellipsis.svg');
}
.vs-dark .settings-editor > .settings-header > .settings-header-controls .settings-header-controls-right .toolbar-toggle-more {
background-image: url('ellipsis-inverse.svg');
}
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item {
padding: 0px; /* padding must be on action-label because it has the bottom-border, because that's where the .checked class is */
}
@ -327,7 +319,8 @@
background: url('check.svg') center center no-repeat;
}
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked {
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked,
.hc-black .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked {
background: url('check-inverse.svg') center center no-repeat;
}

View file

@ -302,12 +302,6 @@ export class SettingsEditor2 extends BaseEditor {
this.settingsTree.reveal(lastElement, 0.9);
return true;
}
} else {
const controls = this.settingsTree.getHTMLElement().querySelectorAll(SettingsRenderer.CONTROL_SELECTOR);
const lastControl = controls && controls[controls.length];
if (lastControl) {
(<HTMLElement>lastControl).focus();
}
}
return false;
@ -336,7 +330,7 @@ export class SettingsEditor2 extends BaseEditor {
}
private createTOC(parent: HTMLElement): void {
this.tocTreeModel = new TOCTreeModel();
this.tocTreeModel = new TOCTreeModel(this.viewState);
this.tocTreeContainer = DOM.append(parent, $('.settings-toc-container'));
const tocRenderer = this.instantiationService.createInstance(TOCRenderer);
@ -673,22 +667,54 @@ export class SettingsEditor2 extends BaseEditor {
this.searchInProgress = null;
});
} else {
if (this.viewState.tagFilters && this.viewState.tagFilters.size) {
this.searchResultModel = this.createFilterModel();
} else {
this.searchResultModel = null;
}
this.localSearchDelayer.cancel();
this.remoteSearchThrottle.cancel();
if (this.searchInProgress && this.searchInProgress.cancel) {
this.searchInProgress.cancel();
}
this.searchResultModel = null;
this.tocTreeModel.currentSearchModel = null;
this.viewState.filterToCategory = null;
this.tocTreeModel.currentSearchModel = this.searchResultModel;
this.tocTree.refresh();
this.toggleSearchMode();
collapseAll(this.tocTree);
return this.settingsTree.setInput(this.settingsTreeModel.root);
if (this.searchResultModel) {
return this.settingsTree.setInput(this.searchResultModel);
} else {
return this.settingsTree.setInput(this.settingsTreeModel.root);
}
}
}
/**
* Return a fake SearchResultModel which can hold a flat list of all settings, to be filtered (@modified etc)
*/
private createFilterModel(): SearchResultModel {
const filterModel = this.instantiationService.createInstance(SearchResultModel, this.viewState);
const fullResult: ISearchResult = {
filterMatches: []
};
for (let g of this.defaultSettingsEditorModel.settingsGroups.slice(1)) {
for (let sect of g.sections) {
for (let setting of sect.settings) {
fullResult.filterMatches.push({ setting, matches: [], score: 0 });
}
}
}
filterModel.setResult(0, fullResult);
return filterModel;
}
private reportFilteringUsed(query: string, results: ISearchResult[]): void {
const nlpResult = results[SearchResultIdx.Remote];
const nlpMetadata = nlpResult && nlpResult.metadata;

View file

@ -45,7 +45,7 @@ export const tocData: ITOCEntry = {
},
{
id: 'editor/format',
label: localize('format', "Format"),
label: localize('formatting', "Formatting"),
settings: ['editor.format*']
},
{

View file

@ -52,6 +52,7 @@ export abstract class SettingsTreeElement {
export class SettingsTreeGroupElement extends SettingsTreeElement {
children: (SettingsTreeGroupElement | SettingsTreeSettingElement)[];
count?: number;
label: string;
level: number;
isFirstGroup: boolean;
@ -91,6 +92,22 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
overriddenScopeList: string[];
description: string;
valueType: 'enum' | 'string' | 'integer' | 'number' | 'boolean' | 'exclude' | 'complex';
matchesAllTags(tagFilters?: Set<string>): boolean {
if (!tagFilters || !tagFilters.size) {
return true;
}
if (this.tags) {
let hasFilteredTag = true;
tagFilters.forEach(tag => {
hasFilteredTag = hasFilteredTag && this.tags.has(tag);
});
return hasFilteredTag;
} else {
return false;
}
}
}
export interface ITOCEntry {
@ -174,7 +191,7 @@ function sanitizeId(id: string): string {
return id.replace(/[\.\/]/, '_');
}
function createSettingsTreeSettingElement(setting: ISetting, parent: any, settingsTarget: SettingsTarget, configurationService: IConfigurationService): SettingsTreeSettingElement {
function createSettingsTreeSettingElement(setting: ISetting, parent: SearchResultModel | SettingsTreeGroupElement, settingsTarget: SettingsTarget, configurationService: IConfigurationService): SettingsTreeSettingElement {
const element = new SettingsTreeSettingElement();
element.id = sanitizeId(parent.id + '_' + setting.key);
element.parent = parent;
@ -1287,25 +1304,22 @@ export class SettingsTreeFilter implements IFilter {
) { }
isVisible(tree: ITree, element: SettingsTreeElement): boolean {
// Filter during search
if (this.viewState.filterToCategory && element instanceof SettingsTreeSettingElement) {
if (!this.settingContainedInGroup(element.setting, this.viewState.filterToCategory)) {
return false;
}
}
if (element instanceof SettingsTreeSettingElement && this.viewState.tagFilters && this.viewState.tagFilters.size) {
if (element.tags) {
let hasFilteredTag = true;
this.viewState.tagFilters.forEach(tag => {
hasFilteredTag = hasFilteredTag && element.tags.has(tag);
});
return hasFilteredTag;
} else {
return false;
}
if (element instanceof SettingsTreeSettingElement && this.viewState.tagFilters) {
return element.matchesAllTags(this.viewState.tagFilters);
}
if (element instanceof SettingsTreeGroupElement && this.viewState.tagFilters && this.viewState.tagFilters.size) {
if (element instanceof SettingsTreeGroupElement) {
if (typeof element.count === 'number') {
return element.count > 0;
}
return element.children.some(child => this.isVisible(tree, child));
}
@ -1419,15 +1433,15 @@ export class SearchResultModel {
return this.rawSearchResults;
}
setResult(type: SearchResultIdx, result: ISearchResult): void {
setResult(order: SearchResultIdx, result: ISearchResult): void {
this.cachedUniqueSearchResults = null;
this.rawSearchResults = this.rawSearchResults || [];
if (!result) {
delete this.rawSearchResults[type];
delete this.rawSearchResults[order];
return;
}
this.rawSearchResults[type] = result;
this.rawSearchResults[order] = result;
this.updateChildren();
}
@ -1482,6 +1496,54 @@ class NonExpandableOrSelectableTree extends Tree {
public focusPrevious(count?: number, eventPayload?: any): void {
return;
}
public focusParent(eventPayload?: any): void {
return;
}
public focusFirstChild(eventPayload?: any): void {
return;
}
public focusFirst(eventPayload?: any, from?: any): void {
return;
}
public focusNth(index: number, eventPayload?: any): void {
return;
}
public focusLast(eventPayload?: any, from?: any): void {
return;
}
public focusNextPage(eventPayload?: any): void {
return;
}
public focusPreviousPage(eventPayload?: any): void {
return;
}
public select(element: any, eventPayload?: any): void {
return;
}
public selectRange(fromElement: any, toElement: any, eventPayload?: any): void {
return;
}
public selectAll(elements: any[], eventPayload?: any): void {
return;
}
public setSelection(elements: any[], eventPayload?: any): void {
return;
}
public toggleSelection(element: any, eventPayload?: any): void {
return;
}
}
export class SettingsTree extends NonExpandableOrSelectableTree {
@ -1556,6 +1618,8 @@ export class SettingsTree extends NonExpandableOrSelectableTree {
listFocusForeground: foreground,
listHoverForeground: foreground,
listHoverBackground: editorBackground,
listHoverOutline: editorBackground,
listFocusOutline: editorBackground,
listInactiveSelectionBackground: editorBackground,
listInactiveSelectionForeground: foreground
}, colors => {

View file

@ -25,6 +25,10 @@ export class TOCTreeModel {
private _currentSearchModel: SearchResultModel;
private _settingsTreeRoot: SettingsTreeGroupElement;
constructor(private viewState: ISettingsEditorViewState) {
}
public set settingsTreeRoot(value: SettingsTreeGroupElement) {
this._settingsTreeRoot = value;
this.update();
@ -44,7 +48,7 @@ export class TOCTreeModel {
}
private updateGroupCount(group: SettingsTreeGroupElement): void {
(<any>group).count = this._currentSearchModel ?
group.count = this._currentSearchModel ?
this.getSearchResultChildrenCount(group) :
undefined;
@ -64,7 +68,7 @@ export class TOCTreeModel {
private groupContainsSetting(group: SettingsTreeGroupElement, setting: ISetting): boolean {
return group.children.some(child => {
if (child instanceof SettingsTreeSettingElement) {
return child.setting.key === setting.key;
return child.setting.key === setting.key && child.matchesAllTags(this.viewState.tagFilters);
} else if (child instanceof SettingsTreeGroupElement) {
return this.groupContainsSetting(child, setting);
} else {
@ -77,11 +81,6 @@ export class TOCTreeModel {
export type TOCTreeElement = SettingsTreeGroupElement | TOCTreeModel;
export class TOCDataSource implements IDataSource {
constructor(
@IConfigurationService private configService: IConfigurationService
) {
}
getId(tree: ITree, element: SettingsTreeGroupElement): string {
return element.id;
}
@ -96,14 +95,6 @@ export class TOCDataSource implements IDataSource {
}
private _getChildren(element: TOCTreeElement): SettingsTreeElement[] {
// TODO@roblou hack. Clean up or remove this option
if (this.configService.getValue('workbench.settings.settingsSearchTocBehavior') === 'filter') {
const children = element.children as SettingsTreeElement[]; // TS????
return children.filter(group => {
return (<any>group).count !== 0;
});
}
return element.children;
}
@ -136,7 +127,7 @@ export class TOCRenderer implements IRenderer {
}
renderElement(tree: ITree, element: SettingsTreeGroupElement, templateId: string, template: ITOCEntryTemplate): void {
const count = (<any>element).count;
const count = element.count;
const label = element.label;
DOM.toggleClass(template.labelElement, 'no-results', count === 0);

View file

@ -293,7 +293,7 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup {
this.onBeforeRun(this.commandId);
// Use a timeout to give the quick open widget a chance to close itself first
TPromise.timeout(50).done(() => {
setTimeout(() => {
if (action && (!(action instanceof Action) || action.enabled)) {
try {
/* __GDPR__
@ -314,7 +314,7 @@ abstract class BaseCommandEntry extends QuickOpenEntryGroup {
} else {
this.notificationService.info(nls.localize('actionNotEnabled', "Command '{0}' is not enabled in the current context.", this.getLabel()));
}
}, err => this.onError(err));
}, 50);
}
private onError(error?: Error): void {

View file

@ -165,3 +165,23 @@ MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
},
order: 2
});
// Go to menu
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.gotoSymbol',
title: nls.localize({ key: 'miGotoSymbolInFile', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in File...")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.gotoLine',
title: nls.localize({ key: 'miGotoLine', comment: ['&& denotes a mnemonic'] }, "Go to &&Line...")
},
order: 7
});

View file

@ -703,11 +703,16 @@ export class DirtyDiffController implements IEditorContribution {
return;
}
if (e.target.element.className.indexOf('dirty-diff-glyph') < 0) {
return;
}
const data = e.target.detail as IMarginData;
const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
const offsetLeftInGutter = (e.target.element as HTMLElement).offsetLeft;
const gutterOffsetX = data.offsetX - offsetLeftInGutter;
// TODO@joao TODO@alex TODO@martin this is such that we don't collide with folding
if (gutterOffsetX > 10) {
if (gutterOffsetX < 0 || gutterOffsetX > 10) {
return;
}

View file

@ -6,6 +6,7 @@
.monaco-editor .dirty-diff-glyph {
margin-left: 5px;
cursor: pointer;
z-index: 5;
}
.monaco-editor .dirty-diff-deleted:after {

View file

@ -642,3 +642,14 @@ MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
},
order: 2
});
// Go to menu
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: 'z_go_to',
command: {
id: 'workbench.action.showAllSymbols',
title: nls.localize({ key: 'miGotoSymbolInWorkspace', comment: ['&& denotes a mnemonic'] }, "Go to Symbol in &&Workspace...")
},
order: 3
});

View file

@ -9,7 +9,6 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { writeFile, exists } from 'vs/base/node/pfs';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { join, basename, dirname, extname } from 'path';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
@ -18,6 +17,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
import URI from 'vs/base/common/uri';
import { ISnippetsService } from 'vs/workbench/parts/snippets/electron-browser/snippets.contribution';
import { values } from 'vs/base/common/map';
import { IQuickPickItem, IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
const id = 'workbench.action.openSnippets';
@ -27,7 +27,7 @@ namespace ISnippetPick {
}
}
interface ISnippetPick extends IPickOpenEntry {
interface ISnippetPick extends IQuickPickItem {
filepath: string;
hint?: true;
}
@ -179,22 +179,23 @@ async function createLanguageSnippetFile(pick: ISnippetPick) {
CommandsRegistry.registerCommand(id, async accessor => {
const snippetService = accessor.get(ISnippetsService);
const quickOpenService = accessor.get(IQuickOpenService);
const quickInputService = accessor.get(IQuickInputService);
const opener = accessor.get(IOpenerService);
const windowService = accessor.get(IWindowService);
const modeService = accessor.get(IModeService);
const envService = accessor.get(IEnvironmentService);
const { existing, future } = await computePicks(snippetService, envService, modeService);
const newGlobalPick = <IPickOpenEntry>{ label: nls.localize('new.global', "New Global Snippets file...") };
const picks = await computePicks(snippetService, envService, modeService);
const existing: QuickPickInput[] = picks.existing;
const newGlobalPick = <IQuickPickItem>{ label: nls.localize('new.global', "New Global Snippets file...") };
if (existing.length > 0) {
existing[0].separator = { label: nls.localize('group.global', "Existing Snippets") };
newGlobalPick.separator = { border: true, label: nls.localize('new.global.sep', "New Snippets") };
existing.unshift({ type: 'separator', label: nls.localize('group.global', "Existing Snippets") });
existing.push({ type: 'separator', border: true, label: nls.localize('new.global.sep', "New Snippets") });
} else {
newGlobalPick.separator = { label: nls.localize('new.global.sep', "New Snippets") };
existing.push({ type: 'separator', label: nls.localize('new.global.sep', "New Snippets") });
}
const pick = await quickOpenService.pick(<(IPickOpenEntry | ISnippetPick)[]>[].concat(existing, newGlobalPick, future), {
const pick = await quickInputService.pick(<(IQuickPickItem | ISnippetPick)[]>[].concat(existing, newGlobalPick, picks.future), {
placeHolder: nls.localize('openSnippet.pickLanguage', "Select Snippets File or Create Snippets"),
matchOnDescription: true
});

View file

@ -7,7 +7,6 @@
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { registerEditorAction, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions';
import { IQuickOpenService, IPickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen';
import { IModeService } from 'vs/editor/common/services/modeService';
import { LanguageId } from 'vs/editor/common/modes';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
@ -16,8 +15,9 @@ import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Snippet } from 'vs/workbench/parts/snippets/electron-browser/snippetsFile';
import { IQuickPickItem, IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
interface ISnippetPick extends IPickOpenEntry {
interface ISnippetPick extends IQuickPickItem {
snippet: Snippet;
}
@ -71,7 +71,7 @@ class InsertSnippetAction extends EditorAction {
return undefined;
}
const quickOpenService = accessor.get(IQuickOpenService);
const quickInputService = accessor.get(IQuickInputService);
const { lineNumber, column } = editor.getPosition();
let { snippet, name, langId } = Args.fromUser(arg);
@ -116,7 +116,7 @@ class InsertSnippetAction extends EditorAction {
} else {
// let user pick a snippet
const snippets = (await snippetService.getSnippets(languageId)).sort(Snippet.compare);
const picks: ISnippetPick[] = [];
const picks: QuickPickInput<ISnippetPick>[] = [];
let prevSnippet: Snippet;
for (const snippet of snippets) {
const pick: ISnippetPick = {
@ -125,14 +125,14 @@ class InsertSnippetAction extends EditorAction {
snippet
};
if (!snippet.isFromExtension && !prevSnippet) {
pick.separator = { label: nls.localize('sep.userSnippet', "User Snippets") };
picks.push({ type: 'separator', label: nls.localize('sep.userSnippet', "User Snippets") });
} else if (snippet.isFromExtension && (!prevSnippet || !prevSnippet.isFromExtension)) {
pick.separator = { label: nls.localize('sep.extSnippet', "Extension Snippets") };
picks.push({ type: 'separator', label: nls.localize('sep.extSnippet', "Extension Snippets") });
}
picks.push(pick);
prevSnippet = snippet;
}
return quickOpenService.pick(picks, { matchOnDetail: true }).then(pick => resolve(pick && pick.snippet), reject);
return quickInputService.pick(picks, { matchOnDetail: true }).then(pick => resolve(pick && pick.snippet), reject);
}
}).then(snippet => {
if (snippet) {

View file

@ -57,7 +57,6 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { IStatusbarItem, IStatusbarRegistry, Extensions as StatusbarExtensions, StatusbarItemDescriptor, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { IQuickOpenService, IPickOpenEntry, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import Constants from 'vs/workbench/parts/markers/electron-browser/constants';
import { IPartService } from 'vs/workbench/services/part/common/partService';
@ -90,7 +89,7 @@ import { QuickOpenActionContributor } from '../browser/quickOpen';
import { Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
let tasksCategory = nls.localize('tasksCategory', "Tasks");
@ -425,7 +424,7 @@ class TaskMap {
}
}
interface TaskQuickPickEntry extends IPickOpenEntry {
interface TaskQuickPickEntry extends IQuickPickItem {
task: Task;
}
@ -475,7 +474,6 @@ class TaskService implements ITaskService {
@ILifecycleService lifecycleService: ILifecycleService,
@IModelService private modelService: IModelService,
@IExtensionService private extensionService: IExtensionService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IQuickInputService private quickInputService: IQuickInputService,
@IConfigurationResolverService private configurationResolverService: IConfigurationResolverService,
@ITerminalService private terminalService: ITerminalService,
@ -873,12 +871,12 @@ class TaskService implements ITaskService {
}
private attachProblemMatcher(task: ContributedTask | CustomTask): TPromise<Task> {
interface ProblemMatcherPickEntry extends IPickOpenEntry {
interface ProblemMatcherPickEntry extends IQuickPickItem {
matcher: NamedProblemMatcher;
never?: boolean;
learnMore?: boolean;
}
let entries: ProblemMatcherPickEntry[] = [];
let entries: QuickPickInput<ProblemMatcherPickEntry>[] = [];
for (let key of ProblemMatcherRegistry.keys()) {
let matcher = ProblemMatcherRegistry.get(key);
if (matcher.deprecated) {
@ -896,15 +894,14 @@ class TaskService implements ITaskService {
}
if (entries.length > 0) {
entries = entries.sort((a, b) => a.label.localeCompare(b.label));
entries[0].separator = { border: true, label: nls.localize('TaskService.associate', 'associate') };
entries.unshift({ type: 'separator', border: true, label: nls.localize('TaskService.associate', 'associate') });
entries.unshift(
{ label: nls.localize('TaskService.attachProblemMatcher.continueWithout', 'Continue without scanning the task output'), matcher: undefined },
{ label: nls.localize('TaskService.attachProblemMatcher.never', 'Never scan the task output'), matcher: undefined, never: true },
{ label: nls.localize('TaskService.attachProblemMatcher.learnMoreAbout', 'Learn more about scanning the task output'), matcher: undefined, learnMore: true }
);
return this.quickOpenService.pick(entries, {
return this.quickInputService.pick(entries, {
placeHolder: nls.localize('selectProblemMatcher', 'Select for which kind of errors and warnings to scan the task output'),
autoFocus: { autoFocusFirstEntry: true }
}).then((selected) => {
if (selected) {
if (selected.learnMore) {
@ -1807,32 +1804,13 @@ class TaskService implements ITaskService {
}
return { label: task._label, description, task };
};
let taskService = this;
let action = new class extends Action implements IPickOpenAction {
constructor() {
super('configureAction', 'Configure Task', 'quick-open-task-configure', true);
function fillEntries(entries: QuickPickInput<TaskQuickPickEntry>[], tasks: Task[], groupLabel: string, withBorder: boolean = false): void {
if (tasks.length) {
entries.push({ type: 'separator', label: groupLabel, border: withBorder });
}
public run(item: IPickOpenItem): TPromise<boolean> {
let task: Task = item.getPayload();
taskService.quickOpenService.close();
if (ContributedTask.is(task)) {
taskService.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
taskService.openConfig(task);
}
return TPromise.as(false);
}
};
function fillEntries(entries: TaskQuickPickEntry[], tasks: Task[], groupLabel: string, withBorder: boolean = false): void {
let first = true;
for (let task of tasks) {
let entry: TaskQuickPickEntry = TaskQuickPickEntry(task);
if (first) {
first = false;
entry.separator = { label: groupLabel, border: withBorder };
}
entry.action = action;
entry.payload = task;
entry.buttons = [{ iconClass: 'quick-open-task-configure', tooltip: nls.localize('configureTask', "Configure Task") }];
entries.push(entry);
}
}
@ -1896,12 +1874,24 @@ class TaskService implements ITaskService {
return tasks.then((tasks) => this.createTaskQuickPickEntries(tasks, group, sort));
}
};
return this.quickOpenService.pick(_createEntries().then((entries) => {
return this.quickInputService.pick(_createEntries().then((entries) => {
if (entries.length === 0 && defaultEntry) {
entries.push(defaultEntry);
}
return entries;
}), { placeHolder, autoFocus: { autoFocusFirstEntry: true }, matchOnDescription: true }).then(entry => entry ? entry.task : undefined);
}), {
placeHolder,
matchOnDescription: true,
onDidTriggerItemButton: context => {
let task = context.item.task;
this.quickInputService.cancel();
if (ContributedTask.is(task)) {
this.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
this.openConfig(task);
}
}
}).then(entry => entry ? entry.task : undefined);
}
private showIgnoredFoldersMessage(): TPromise<void> {
@ -2254,8 +2244,8 @@ class TaskService implements ITaskService {
}
};
function isTaskEntry(value: IPickOpenEntry): value is IPickOpenEntry & { task: Task } {
let candidate: IPickOpenEntry & { task: Task } = value as any;
function isTaskEntry(value: IQuickPickItem): value is IQuickPickItem & { task: Task } {
let candidate: IQuickPickItem & { task: Task } = value as any;
return candidate && !!candidate.task;
}
@ -2267,8 +2257,8 @@ class TaskService implements ITaskService {
let openLabel = nls.localize('TaskService.openJsonFile', 'Open tasks.json file');
let entries = TPromise.join(stats).then((stats) => {
return taskPromise.then((taskMap) => {
type EntryType = (IPickOpenEntry & { task: Task; }) | (IPickOpenEntry & { folder: IWorkspaceFolder; });
let entries: EntryType[] = [];
type EntryType = (IQuickPickItem & { task: Task; }) | (IQuickPickItem & { folder: IWorkspaceFolder; });
let entries: QuickPickInput<EntryType>[] = [];
if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) {
let tasks = taskMap.all();
let needsCreateOrOpen: boolean = true;
@ -2283,7 +2273,10 @@ class TaskService implements ITaskService {
}
if (needsCreateOrOpen) {
let label = stats[0] !== void 0 ? openLabel : createLabel;
entries.push({ label, folder: this.contextService.getWorkspace().folders[0], separator: entries.length > 0 ? { border: true } : undefined });
if (entries.length) {
entries.push({ type: 'separator', border: true });
}
entries.push({ label, folder: this.contextService.getWorkspace().folders[0] });
}
} else {
let folders = this.contextService.getWorkspace().folders;
@ -2295,14 +2288,14 @@ class TaskService implements ITaskService {
for (let i = 0; i < tasks.length; i++) {
let entry: EntryType = { label: tasks[i]._label, task: tasks[i], description: folder.name };
if (i === 0) {
entry.separator = { label: folder.name, border: index > 0 };
entries.push({ type: 'separator', label: folder.name, border: index > 0 });
}
entries.push(entry);
}
} else {
let label = stats[index] !== void 0 ? openLabel : createLabel;
let entry: EntryType = { label, folder: folder };
entry.separator = { label: folder.name, border: index > 0 };
entries.push({ type: 'separator', label: folder.name, border: index > 0 });
entries.push(entry);
}
index++;
@ -2312,8 +2305,8 @@ class TaskService implements ITaskService {
});
});
this.quickOpenService.pick(entries,
{ placeHolder: nls.localize('TaskService.pickTask', 'Select a task to configure'), autoFocus: { autoFocusFirstEntry: true } }).
this.quickInputService.pick(entries,
{ placeHolder: nls.localize('TaskService.pickTask', 'Select a task to configure') }).
then((selection) => {
if (!selection) {
return;

View file

@ -482,7 +482,7 @@ export class TerminalInstance implements ITerminalInstance {
label: nls.localize('yes', "Yes"),
run: () => {
this._configurationService.updateValue('terminal.integrated.rendererType', 'dom', ConfigurationTarget.USER).then(() => {
this._notificationService.info(nls.localize('terminal.rendererInAllNewTerminals', "The termnial is now using the fallback renderer."));
this._notificationService.info(nls.localize('terminal.rendererInAllNewTerminals', "The terminal is now using the fallback renderer."));
});
}
} as IPromptChoice,

View file

@ -13,7 +13,6 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IQuickOpenService, IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen';
import { ITerminalInstance, ITerminalService, IShellLaunchConfig, ITerminalConfigHelper, NEVER_SUGGEST_SELECT_WINDOWS_SHELL_STORAGE_KEY, TERMINAL_PANEL_ID, ITerminalProcessExtHostProxy } from 'vs/workbench/parts/terminal/common/terminal';
import { TerminalService as AbstractTerminalService } from 'vs/workbench/parts/terminal/common/terminalService';
import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
@ -29,6 +28,7 @@ import { ipcRenderer as ipc } from 'electron';
import { IOpenFileRequest } from 'vs/platform/windows/common/windows';
import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IQuickInputService, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput';
export class TerminalService extends AbstractTerminalService implements ITerminalService {
private _configHelper: TerminalConfigHelper;
@ -47,7 +47,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
@ILifecycleService lifecycleService: ILifecycleService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IQuickOpenService private readonly _quickOpenService: IQuickOpenService,
@IQuickInputService private readonly _quickInputService: IQuickInputService,
@INotificationService private readonly _notificationService: INotificationService,
@IDialogService private readonly _dialogService: IDialogService,
@IExtensionService private readonly _extensionService: IExtensionService
@ -184,10 +184,10 @@ export class TerminalService extends AbstractTerminalService implements ITermina
public selectDefaultWindowsShell(): TPromise<string> {
return this._detectWindowsShells().then(shells => {
const options: IPickOptions = {
const options: IPickOptions<IQuickPickItem> = {
placeHolder: nls.localize('terminal.integrated.chooseWindowsShell', "Select your preferred terminal shell, you can change this later in your settings")
};
return this._quickOpenService.pick(shells, options).then(value => {
return this._quickInputService.pick(shells, options).then(value => {
if (!value) {
return null;
}
@ -197,7 +197,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
});
}
private _detectWindowsShells(): TPromise<IPickOpenEntry[]> {
private _detectWindowsShells(): TPromise<IQuickPickItem[]> {
// Determine the correct System32 path. We want to point to Sysnative
// when the 32-bit version of VS Code is running on a 64-bit machine.
// The reason for this is because PowerShell's important PSReadline
@ -231,7 +231,7 @@ export class TerminalService extends AbstractTerminalService implements ITermina
Object.keys(expectedLocations).forEach(key => promises.push(this._validateShellPaths(key, expectedLocations[key])));
return TPromise.join(promises).then(results => {
return results.filter(result => !!result).map(result => {
return <IPickOpenEntry>{
return <IQuickPickItem>{
label: result[0],
description: result[1]
};

View file

@ -9,7 +9,7 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } fr
import { Registry } from 'vs/platform/registry/common/platform';
import { WelcomePageContribution, WelcomePageAction, WelcomeInputFactory } from 'vs/workbench/parts/welcome/page/electron-browser/welcomePage';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
@ -41,3 +41,12 @@ Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions)
.registerWorkbenchAction(new SyncActionDescriptor(WelcomePageAction, WelcomePageAction.ID, WelcomePageAction.LABEL), 'Help: Welcome', localize('help', "Help"));
Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).registerEditorInputFactory(WelcomeInputFactory.ID, WelcomeInputFactory);
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.showWelcomePage',
title: localize({ key: 'miWelcome', comment: ['&& denotes a mnemonic'] }, "&&Welcome")
},
order: 1
});

View file

@ -14,7 +14,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IEditorRegistry, Extensions as EditorExtensions, EditorDescriptor } from 'vs/workbench/browser/editor';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
@ -48,3 +48,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule(WalkThroughArrowDown);
KeybindingsRegistry.registerCommandAndKeybindingRule(WalkThroughPageUp);
KeybindingsRegistry.registerCommandAndKeybindingRule(WalkThroughPageDown);
MenuRegistry.appendMenuItem(MenuId.MenubarHelpMenu, {
group: '1_welcome',
command: {
id: 'workbench.action.showInteractivePlayground',
title: localize({ key: 'miInteractivePlayground', comment: ['&& denotes a mnemonic'] }, "&&Interactive Playground")
},
order: 2
});

View file

@ -37,46 +37,44 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
showContextMenu(delegate: IContextMenuDelegate): void {
delegate.getActions().then(actions => {
if (!actions.length) {
return TPromise.as(null);
}
if (actions.length) {
setTimeout(() => {
const onHide = once(() => {
if (delegate.onHide) {
delegate.onHide(undefined);
}
return TPromise.timeout(0).then(() => { // https://github.com/Microsoft/vscode/issues/3638
const onHide = once(() => {
if (delegate.onHide) {
delegate.onHide(undefined);
this._onDidContextMenu.fire();
});
const menu = this.createMenu(delegate, actions, onHide);
const anchor = delegate.getAnchor();
let x: number, y: number;
if (dom.isHTMLElement(anchor)) {
let elementPosition = dom.getDomNodePagePosition(anchor);
x = elementPosition.left;
y = elementPosition.top + elementPosition.height;
} else {
const pos = <{ x: number; y: number; }>anchor;
x = pos.x + 1; /* prevent first item from being selected automatically under mouse */
y = pos.y;
}
this._onDidContextMenu.fire();
});
let zoom = webFrame.getZoomFactor();
x *= zoom;
y *= zoom;
const menu = this.createMenu(delegate, actions, onHide);
const anchor = delegate.getAnchor();
let x: number, y: number;
if (dom.isHTMLElement(anchor)) {
let elementPosition = dom.getDomNodePagePosition(anchor);
x = elementPosition.left;
y = elementPosition.top + elementPosition.height;
} else {
const pos = <{ x: number; y: number; }>anchor;
x = pos.x + 1; /* prevent first item from being selected automatically under mouse */
y = pos.y;
}
let zoom = webFrame.getZoomFactor();
x *= zoom;
y *= zoom;
menu.popup({
window: remote.getCurrentWindow(),
x: Math.floor(x),
y: Math.floor(y),
positioningItem: delegate.autoSelectFirstItem ? 0 : void 0,
callback: () => onHide()
});
});
menu.popup({
window: remote.getCurrentWindow(),
x: Math.floor(x),
y: Math.floor(y),
positioningItem: delegate.autoSelectFirstItem ? 0 : void 0,
callback: () => onHide()
});
}, 0); // https://github.com/Microsoft/vscode/issues/3638
}
});
}

View file

@ -36,6 +36,7 @@ import { getScopes } from 'vs/platform/configuration/common/configurationRegistr
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { timeout } from 'vs/base/common/async';
export class ExtensionHostProcessWorker {
@ -505,7 +506,7 @@ export class ExtensionHostProcessWorker {
}
});
event.veto(TPromise.timeout(100 /* wait a bit for IPC to get delivered */).then(() => false));
event.veto(timeout(100 /* wait a bit for IPC to get delivered */).then(() => false));
}
}
}

View file

@ -33,6 +33,7 @@ import { ResourceGlobMatcher } from 'vs/workbench/electron-browser/resources';
import { Schemas } from 'vs/base/common/network';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
/**
* Stores the selection & view state of an editor and allows to compare it to other selection states.
@ -123,6 +124,9 @@ export class HistoryService extends Disposable implements IHistoryService {
private fileInputFactory: IFileInputFactory;
private canNavigateBackContextKey: IContextKey<boolean>;
private canNavigateForwardContextKey: IContextKey<boolean>;
constructor(
@IEditorService private editorService: EditorServiceImpl,
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
@ -133,12 +137,16 @@ export class HistoryService extends Disposable implements IHistoryService {
@IFileService private fileService: IFileService,
@IWindowsService private windowService: IWindowsService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService
@IPartService private partService: IPartService,
@IContextKeyService private contextKeyService: IContextKeyService
) {
super();
this.activeEditorListeners = [];
this.canNavigateBackContextKey = (new RawContextKey<boolean>('canNavigateBack', false)).bindTo(this.contextKeyService);
this.canNavigateForwardContextKey = (new RawContextKey<boolean>('canNavigateForward', false)).bindTo(this.contextKeyService);
this.fileInputFactory = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).getFileInputFactory();
this.index = -1;
@ -268,6 +276,8 @@ export class HistoryService extends Disposable implements IHistoryService {
private setIndex(value: number): void {
this.lastIndex = this.index;
this.index = value;
this.updateContextKeys();
}
private doForwardAcrossEditors(): void {
@ -338,6 +348,13 @@ export class HistoryService extends Disposable implements IHistoryService {
this.stack.splice(0);
this.history = [];
this.recentlyClosedFiles = [];
this.updateContextKeys();
}
private updateContextKeys(): void {
this.canNavigateBackContextKey.set(this.stack.length > 0 && this.index > 0);
this.canNavigateForwardContextKey.set(this.stack.length > 0 && this.index < this.stack.length - 1);
}
private navigate(acrossEditors?: boolean): void {
@ -569,6 +586,9 @@ export class HistoryService extends Disposable implements IHistoryService {
if (stackInput instanceof EditorInput) {
once(stackInput.onDispose)(() => this.removeFromStack(input));
}
// Context
this.updateContextKeys();
}
private preferResourceInput(input: IEditorInput): IEditorInput | IResourceInput {
@ -595,6 +615,8 @@ export class HistoryService extends Disposable implements IHistoryService {
this.stack = this.stack.filter(e => !this.matches(arg1, e.input));
this.index = this.stack.length - 1; // reset index
this.lastIndex = -1;
this.updateContextKeys();
}
private removeFromRecentlyClosedFiles(arg1: IEditorInput | IResourceInput | FileChangesEvent): void {
@ -659,13 +681,15 @@ export class HistoryService extends Disposable implements IHistoryService {
if (arg2 instanceof EditorInput) {
const inputResource = arg2.getResource();
let isSupportedFile = true;
if (this.partService.isCreated() && !this.fileService.canHandleResource(inputResource)) {
isSupportedFile = false; // make sure to only check this when workbench has started (for https://github.com/Microsoft/vscode/issues/48275)
if (!inputResource) {
return false;
}
return inputResource && isSupportedFile && inputResource.toString() === resource.toString();
if (this.partService.isCreated() && !this.fileService.canHandleResource(inputResource)) {
return false; // make sure to only check this when workbench has started (for https://github.com/Microsoft/vscode/issues/48275)
}
return inputResource.toString() === resource.toString();
}
const resourceInput = arg2 as IResourceInput;

View file

@ -21,6 +21,8 @@ import { Engine as TextSearchEngine } from 'vs/workbench/services/search/node/te
import { TextSearchWorkerProvider } from 'vs/workbench/services/search/node/textSearchWorkerProvider';
import { IFileSearchProgressItem, IRawFileMatch, IRawSearch, IRawSearchService, ISearchEngine, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, ITelemetryEvent, ISerializedSearchSuccess } from './search';
import { Event, Emitter } from 'vs/base/common/event';
import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
gracefulFs.gracefulify(fs);
@ -55,12 +57,14 @@ export class SearchService implements IRawSearchService {
}
public textSearch(config: IRawSearch): Event<ISerializedSearchProgressItem | ISerializedSearchComplete> {
let promise: TPromise<ISerializedSearchSuccess>;
let promise: CancelablePromise<void>;
const emitter = new Emitter<ISerializedSearchProgressItem | ISerializedSearchComplete>({
onFirstListenerDidAdd: () => {
promise = (config.useRipgrep ? this.ripgrepTextSearch(config, p => emitter.fire(p)) : this.legacyTextSearch(config, p => emitter.fire(p)))
.then(c => emitter.fire(c), err => emitter.fire({ type: 'error', error: { message: err.message, stack: err.stack } }));
promise = createCancelablePromise(token => {
return (config.useRipgrep ? this.ripgrepTextSearch(config, p => emitter.fire(p), token) : this.legacyTextSearch(config, p => emitter.fire(p), token))
.then(c => emitter.fire(c), err => emitter.fire({ type: 'error', error: { message: err.message, stack: err.stack } }));
});
},
onLastListenerRemove: () => {
promise.cancel();
@ -70,11 +74,13 @@ export class SearchService implements IRawSearchService {
return emitter.event;
}
private ripgrepTextSearch(config: IRawSearch, progressCallback: IProgressCallback): TPromise<ISerializedSearchSuccess> {
private ripgrepTextSearch(config: IRawSearch, progressCallback: IProgressCallback, token: CancellationToken): Promise<ISerializedSearchSuccess> {
config.maxFilesize = MAX_FILE_SIZE;
let engine = new RipgrepEngine(config);
return new TPromise<ISerializedSearchSuccess>((c, e) => {
token.onCancellationRequested(() => engine.cancel());
return new Promise<ISerializedSearchSuccess>((c, e) => {
// Use BatchedCollector to get new results to the frontend every 2s at least, until 50 results have been returned
const collector = new BatchedCollector<ISerializedFileMatch>(SearchService.BATCH_SIZE, progressCallback);
engine.search((match) => {
@ -90,12 +96,10 @@ export class SearchService implements IRawSearchService {
c(stats);
}
});
}, () => {
engine.cancel();
});
}
private legacyTextSearch(config: IRawSearch, progressCallback: IProgressCallback): TPromise<ISerializedSearchComplete> {
private legacyTextSearch(config: IRawSearch, progressCallback: IProgressCallback, token: CancellationToken): Promise<ISerializedSearchComplete> {
if (!this.textSearchWorkerProvider) {
this.textSearchWorkerProvider = new TextSearchWorkerProvider();
}
@ -113,7 +117,7 @@ export class SearchService implements IRawSearchService {
}),
this.textSearchWorkerProvider);
return this.doTextSearch(engine, progressCallback, SearchService.BATCH_SIZE);
return this.doTextSearch(engine, progressCallback, SearchService.BATCH_SIZE, token);
}
doFileSearch(EngineClass: { new(config: IRawSearch): ISearchEngine<IRawFileMatch>; }, config: IRawSearch, progressCallback: IProgressCallback, batchSize?: number): TPromise<ISerializedSearchSuccess> {
@ -241,6 +245,7 @@ export class SearchService implements IRawSearchService {
const cached = this.getResultsFromCache(cache, config.filePattern, progressCallback);
if (cached) {
let chained: TPromise<void>;
return new TPromise<[ISerializedSearchSuccess, IRawFileMatch[]]>((c, e) => {
chained = cached.then(([result, results, cacheStats]) => {
const cacheLookupResultTime = Date.now();
@ -361,8 +366,10 @@ export class SearchService implements IRawSearchService {
});
}
private doTextSearch(engine: TextSearchEngine, progressCallback: IProgressCallback, batchSize: number): TPromise<ISerializedSearchSuccess> {
return new TPromise<ISerializedSearchSuccess>((c, e) => {
private doTextSearch(engine: TextSearchEngine, progressCallback: IProgressCallback, batchSize: number, token: CancellationToken): Promise<ISerializedSearchSuccess> {
token.onCancellationRequested(() => engine.cancel());
return new Promise<ISerializedSearchSuccess>((c, e) => {
// Use BatchedCollector to get new results to the frontend every 2s at least, until 50 results have been returned
const collector = new BatchedCollector<ISerializedFileMatch>(batchSize, progressCallback);
engine.search((matches) => {
@ -379,8 +386,6 @@ export class SearchService implements IRawSearchService {
c(stats);
}
});
}, () => {
engine.cancel();
});
}

View file

@ -25,7 +25,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { RunOnceScheduler } from 'vs/base/common/async';
import { RunOnceScheduler, timeout } from 'vs/base/common/async';
import { ITextBufferFactory } from 'vs/editor/common/model';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { createTextBufferFactory } from 'vs/editor/common/model/textModel';
@ -153,13 +153,13 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
}
if (fileEventImpactsModel && this.inOrphanMode !== newInOrphanModeGuess) {
let checkOrphanedPromise: TPromise<boolean>;
let checkOrphanedPromise: Thenable<boolean>;
if (newInOrphanModeGuess) {
// We have received reports of users seeing delete events even though the file still
// exists (network shares issue: https://github.com/Microsoft/vscode/issues/13665).
// Since we do not want to mark the model as orphaned, we have to check if the
// file is really gone and not just a faulty file event.
checkOrphanedPromise = TPromise.timeout(100).then(() => {
checkOrphanedPromise = timeout(100).then(() => {
if (this.disposed) {
return true;
}
@ -167,10 +167,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
return this.fileService.existsFile(this.resource).then(exists => !exists);
});
} else {
checkOrphanedPromise = TPromise.as(false);
checkOrphanedPromise = Promise.resolve(false);
}
checkOrphanedPromise.done(newInOrphanModeValidated => {
checkOrphanedPromise.then(newInOrphanModeValidated => {
if (this.inOrphanMode !== newInOrphanModeValidated && !this.disposed) {
this.setOrphaned(newInOrphanModeValidated);
}

View file

@ -9,6 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { CharCode } from 'vs/base/common/charCode';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { isThenable } from 'vs/base/common/async';
export function SingleProxyRPCProtocol(thing: any): IExtHostContext {
return {
@ -106,7 +107,7 @@ export class TestRPCProtocol implements IExtHostContext {
let p: Thenable<any>;
try {
let result = (<Function>instance[path]).apply(instance, wireArgs);
p = TPromise.is(result) ? result : TPromise.as(result);
p = isThenable(result) ? result : TPromise.as(result);
} catch (err) {
p = TPromise.wrapError(err);
}

View file

@ -33,7 +33,7 @@
"rimraf": "^2.6.1",
"strip-json-comments": "^2.0.1",
"tmp": "0.0.33",
"typescript": "2.5.2",
"typescript": "2.9.2",
"watch": "^1.0.2"
}
}

View file

@ -1825,9 +1825,9 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34"
typescript@2.9.2:
version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
uid-number@^0.0.6:
version "0.0.6"

View file

@ -7933,9 +7933,9 @@ vscode-textmate@^4.0.1:
dependencies:
oniguruma "^7.0.0"
vscode-xterm@3.7.0-beta3:
version "3.7.0-beta3"
resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.7.0-beta3.tgz#2306f9650ee2f55637ba1804d10c5ffb9ef944f6"
vscode-xterm@3.7.0-beta4:
version "3.7.0-beta4"
resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.7.0-beta4.tgz#f980d66f94f09ae80e100715dae60715dcae1ac6"
vso-node-api@^6.1.2-preview:
version "6.1.2-preview"