mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-07 07:16:41 +01:00
Merge branch 'master' into ben/electron
This commit is contained in:
@@ -30,6 +30,7 @@ var commit = util.getVersion(root);
|
||||
var dependencies = Object.keys(shrinkwrap.dependencies);
|
||||
var baseModules = Object.keys(process.binding('natives')).filter(function (n) { return !/^_|\//.test(n); });
|
||||
var nodeModules = ['electron'].concat(dependencies).concat(baseModules);
|
||||
nodeModules.push('original-fs'); // provided by electron to have original fs functionality without ASAR support
|
||||
|
||||
// Build
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { workspace, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Disposable } from 'vscode';
|
||||
import * as Proto from '../protocol';
|
||||
import { ITypescriptServiceClient } from '../typescriptService';
|
||||
@@ -83,7 +80,6 @@ export default class BufferSyncSupport {
|
||||
private diagnostics: Diagnostics;
|
||||
private disposables: Disposable[] = [];
|
||||
private syncedBuffers: Map<SyncedBuffer>;
|
||||
private closedFiles: Map<boolean>;
|
||||
|
||||
private projectValidationRequested: boolean;
|
||||
|
||||
@@ -104,7 +100,6 @@ export default class BufferSyncSupport {
|
||||
this.diagnosticDelayer = new Delayer<any>(100);
|
||||
|
||||
this.syncedBuffers = Object.create(null);
|
||||
this.closedFiles = Object.create(null);
|
||||
}
|
||||
|
||||
public listen(): void {
|
||||
@@ -112,19 +107,6 @@ export default class BufferSyncSupport {
|
||||
workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, this.disposables);
|
||||
workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, this.disposables);
|
||||
workspace.textDocuments.forEach(this.onDidOpenTextDocument, this);
|
||||
workspace.createFileSystemWatcher('**/*', true, true, false).onDidDelete((resource) => {
|
||||
let filepath = this.client.asAbsolutePath(resource);
|
||||
if (!filepath) {
|
||||
return;
|
||||
}
|
||||
if (!this.syncedBuffers[filepath]) {
|
||||
// The file is not synced (open in an editor) and got
|
||||
// removed from disk. Make sure it is not in the closedFiles
|
||||
// list since we shouldn't revalidate it.
|
||||
delete this.closedFiles[filepath];
|
||||
this.diagnostics.delete(filepath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public get validate(): boolean {
|
||||
@@ -165,7 +147,6 @@ export default class BufferSyncSupport {
|
||||
}
|
||||
let syncedBuffer = new SyncedBuffer(document, filepath, this, this.client);
|
||||
this.syncedBuffers[filepath] = syncedBuffer;
|
||||
delete this.closedFiles[filepath];
|
||||
syncedBuffer.open();
|
||||
this.requestDiagnostic(filepath);
|
||||
}
|
||||
@@ -179,14 +160,7 @@ export default class BufferSyncSupport {
|
||||
if (!syncedBuffer) {
|
||||
return;
|
||||
}
|
||||
// If the file still exists on disk keep on validating the file.
|
||||
if (fs.existsSync(filepath) && this.extensions[path.extname(filepath)]) {
|
||||
this.closedFiles[filepath] = true;
|
||||
} else {
|
||||
// Ensure we don't have the file in the map and clear all errors.
|
||||
delete this.closedFiles[filepath];
|
||||
this.diagnostics.delete(filepath);
|
||||
}
|
||||
this.diagnostics.delete(filepath);
|
||||
delete this.syncedBuffers[filepath];
|
||||
syncedBuffer.close();
|
||||
}
|
||||
@@ -246,13 +220,6 @@ export default class BufferSyncSupport {
|
||||
}
|
||||
});
|
||||
|
||||
// Now add all files that we have requested diagnostics for but are now
|
||||
// closed. Otherwise it might be confusing that interfile dependent markers
|
||||
// don't get fixed.
|
||||
Object.keys(this.closedFiles).forEach((file) => {
|
||||
files.push(file);
|
||||
});
|
||||
|
||||
let args: Proto.GeterrRequestArgs = {
|
||||
delay: 0,
|
||||
files: files
|
||||
|
||||
@@ -41,5 +41,6 @@ export interface ITypescriptServiceClient {
|
||||
execute(command:'occurrences', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.OccurrencesResponse>;
|
||||
execute(command:'projectInfo', args: Proto.ProjectInfoRequestArgs, token?: CancellationToken): Promise<Proto.ProjectInfoResponse>;
|
||||
execute(command:'reloadProjects', args: any, expectedResult:boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command:'reload', args: Proto.ReloadRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command:string, args:any, expectedResult:boolean| CancellationToken, token?: CancellationToken):Promise<any>;
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.3.0",
|
||||
"version": "1.4.0",
|
||||
"electronVersion": "1.2.6",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
|
||||
Vendored
+6
@@ -4999,6 +4999,12 @@ declare module 'electron' {
|
||||
export = electron;
|
||||
}
|
||||
|
||||
declare module 'original-fs' {
|
||||
import * as fs from 'fs';
|
||||
|
||||
export = fs;
|
||||
}
|
||||
|
||||
// interface NodeRequireFunction {
|
||||
// (moduleName: 'electron'): Electron.ElectronMainAndRenderer;
|
||||
// }
|
||||
@@ -42,17 +42,19 @@ export class DelayedDragHandler {
|
||||
}
|
||||
}
|
||||
|
||||
export function extractResources(e: DragEvent): URI[] {
|
||||
export function extractResources(e: DragEvent, externalOnly?: boolean): URI[] {
|
||||
const resources: URI[] = [];
|
||||
if (e.dataTransfer.types.length > 0) {
|
||||
|
||||
// Check for in-app DND
|
||||
const rawData = e.dataTransfer.getData(e.dataTransfer.types[0]);
|
||||
if (rawData) {
|
||||
try {
|
||||
resources.push(URI.parse(rawData));
|
||||
} catch (error) {
|
||||
// Invalid URI
|
||||
if (!externalOnly) {
|
||||
const rawData = e.dataTransfer.getData(e.dataTransfer.types[0]);
|
||||
if (rawData) {
|
||||
try {
|
||||
resources.push(URI.parse(rawData));
|
||||
} catch (error) {
|
||||
// Invalid URI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,31 +141,4 @@
|
||||
flex: 1;
|
||||
max-width: 170px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.monaco-workbench .action-bar-select {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
margin-top: 8px; /* Center the select box */
|
||||
}
|
||||
|
||||
.monaco-workbench .action-bar-select.windows {
|
||||
margin-top: 7px; /* Center the select box */
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .action-bar-select {
|
||||
background-color: #3C3C3C;
|
||||
border-color: #3C3C3C;
|
||||
color: rgb(204, 204, 204);
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .action-bar-select {
|
||||
background-color: #3C3C3C;
|
||||
border-color: #3C3C3C;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .action-bar-select {
|
||||
background-color: white;
|
||||
border-color: #CECECE;
|
||||
}
|
||||
@@ -11,11 +11,11 @@ import lifecycle = require('vs/base/common/lifecycle');
|
||||
import {Promise} from 'vs/base/common/winjs.base';
|
||||
import {Builder, $} from 'vs/base/browser/builder';
|
||||
import platform = require('vs/base/common/platform');
|
||||
import {IAction, IActionRunner, Action, ActionRunner} from 'vs/base/common/actions';
|
||||
import {IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner} from 'vs/base/common/actions';
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import {EventType as CommonEventType} from 'vs/base/common/events';
|
||||
import types = require('vs/base/common/types');
|
||||
import {IEventEmitter, EventEmitter, EmitterEvent} from 'vs/base/common/eventEmitter';
|
||||
import {IEventEmitter, EventEmitter} from 'vs/base/common/eventEmitter';
|
||||
import {Gesture, EventType} from 'vs/base/browser/touch';
|
||||
import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
||||
@@ -48,38 +48,33 @@ export class BaseActionItem extends EventEmitter implements IActionItem {
|
||||
this._action = action;
|
||||
|
||||
if (action instanceof Action) {
|
||||
let l = (<Action>action).addBulkListener2((events: EmitterEvent[]) => {
|
||||
this._callOnDispose.push(action.onDidChange(event => {
|
||||
if (!this.builder) {
|
||||
// we have not been rendered yet, so there
|
||||
// is no point in updating the UI
|
||||
return;
|
||||
}
|
||||
this._handleActionChangeEvent(event);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
events.forEach((event: EmitterEvent) => {
|
||||
switch (event.getType()) {
|
||||
case Action.ENABLED:
|
||||
this._updateEnabled();
|
||||
break;
|
||||
case Action.LABEL:
|
||||
this._updateLabel();
|
||||
this._updateTooltip();
|
||||
break;
|
||||
case Action.TOOLTIP:
|
||||
this._updateTooltip();
|
||||
break;
|
||||
case Action.CLASS:
|
||||
this._updateClass();
|
||||
break;
|
||||
case Action.CHECKED:
|
||||
this._updateChecked();
|
||||
break;
|
||||
default:
|
||||
this._updateUnknown(event);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
this._callOnDispose.push(l);
|
||||
protected _handleActionChangeEvent(event: IActionChangeEvent): void {
|
||||
if (event.enabled !== void 0) {
|
||||
this._updateEnabled();
|
||||
}
|
||||
if (event.checked !== void 0) {
|
||||
this._updateChecked();
|
||||
}
|
||||
if (event.class !== void 0) {
|
||||
this._updateClass();
|
||||
}
|
||||
if (event.label !== void 0) {
|
||||
this._updateLabel();
|
||||
this._updateTooltip();
|
||||
}
|
||||
if (event.tooltip !== void 0) {
|
||||
this._updateTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,30 +156,26 @@ export class BaseActionItem extends EventEmitter implements IActionItem {
|
||||
}
|
||||
}
|
||||
|
||||
public _updateEnabled(): void {
|
||||
protected _updateEnabled(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
public _updateLabel(): void {
|
||||
protected _updateLabel(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
public _updateTooltip(): void {
|
||||
protected _updateTooltip(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
public _updateClass(): void {
|
||||
protected _updateClass(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
public _updateChecked(): void {
|
||||
protected _updateChecked(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
public _updateUnknown(event: EmitterEvent): void {
|
||||
// can implement in subclass
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
@@ -746,7 +737,7 @@ export class SelectActionItem extends BaseActionItem {
|
||||
super(ctx, action);
|
||||
|
||||
this.select = document.createElement('select');
|
||||
this.select.className = `action-bar-select ${platform.isWindows ? 'windows' : ''}`;
|
||||
this.select.className = 'action-bar-select';
|
||||
|
||||
this.options = options;
|
||||
this.selected = selected;
|
||||
|
||||
@@ -52,22 +52,22 @@ export class Button extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
public getElement(): HTMLElement {
|
||||
getElement(): HTMLElement {
|
||||
return this.$el.getHTMLElement();
|
||||
}
|
||||
|
||||
public set label(value: string) {
|
||||
set label(value: string) {
|
||||
if (!this.$el.hasClass('monaco-text-button')) {
|
||||
this.$el.addClass('monaco-text-button');
|
||||
}
|
||||
this.$el.text(value);
|
||||
}
|
||||
|
||||
public set icon(iconClassName: string) {
|
||||
set icon(iconClassName: string) {
|
||||
this.$el.addClass(iconClassName);
|
||||
}
|
||||
|
||||
public set enabled(value: boolean) {
|
||||
set enabled(value: boolean) {
|
||||
if (value) {
|
||||
this.$el.removeClass('disabled');
|
||||
this.$el.attr({
|
||||
@@ -81,11 +81,15 @@ export class Button extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
public get enabled() {
|
||||
get enabled() {
|
||||
return !this.$el.hasClass('disabled');
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
focus(): void {
|
||||
this.$el.domFocus();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.$el) {
|
||||
this.$el.dispose();
|
||||
this.$el = null;
|
||||
|
||||
@@ -136,7 +136,7 @@ export class InputBox extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => this.layout(), 0);
|
||||
setTimeout(() => this.updateMirror(), 0);
|
||||
|
||||
// Support actions
|
||||
if (this.options.actions) {
|
||||
@@ -357,19 +357,25 @@ export class InputBox extends Widget {
|
||||
this._onDidChange.fire(this.value);
|
||||
|
||||
this.validate();
|
||||
|
||||
if (this.mirror) {
|
||||
let lastCharCode = this.value.charCodeAt(this.value.length - 1);
|
||||
let suffix = lastCharCode === 10 ? ' ' : '';
|
||||
this.mirror.textContent = this.value + suffix;
|
||||
this.layout();
|
||||
}
|
||||
this.updateMirror();
|
||||
|
||||
if (this.state === 'open') {
|
||||
this.contextViewProvider.layout();
|
||||
}
|
||||
}
|
||||
|
||||
private updateMirror(): void {
|
||||
if (!this.mirror) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this.value || this.placeholder;
|
||||
let lastCharCode = value.charCodeAt(value.length - 1);
|
||||
let suffix = lastCharCode === 10 ? ' ' : '';
|
||||
this.mirror.textContent = value + suffix;
|
||||
this.layout();
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
if (!this.mirror) {
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@ import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import { IEventEmitter, EventEmitter } from 'vs/base/common/eventEmitter';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import * as Events from 'vs/base/common/events';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
|
||||
export interface IAction extends IDisposable {
|
||||
id: string;
|
||||
@@ -68,26 +69,27 @@ export interface IActionProvider {
|
||||
getAction(id: string): IAction;
|
||||
}
|
||||
|
||||
export class Action extends EventEmitter implements IAction {
|
||||
export interface IActionChangeEvent {
|
||||
label?: string;
|
||||
tooltip?: string;
|
||||
class?: string;
|
||||
enabled?: boolean;
|
||||
checked?: boolean;
|
||||
}
|
||||
|
||||
static LABEL: string = 'label';
|
||||
static TOOLTIP: string = 'tooltip';
|
||||
static CLASS: string = 'class';
|
||||
static ENABLED: string = 'enabled';
|
||||
static CHECKED: string = 'checked';
|
||||
export class Action implements IAction {
|
||||
|
||||
public _id: string;
|
||||
public _label: string;
|
||||
public _tooltip: string;
|
||||
public _cssClass: string;
|
||||
public _enabled: boolean;
|
||||
public _checked: boolean;
|
||||
public _actionCallback: IActionCallback;
|
||||
public _order: number;
|
||||
|
||||
constructor(id: string, label = '', cssClass = '', enabled = true, actionCallback: IActionCallback = null) {
|
||||
super();
|
||||
protected _onDidChange = new Emitter<IActionChangeEvent>();
|
||||
protected _id: string;
|
||||
protected _label: string;
|
||||
protected _tooltip: string;
|
||||
protected _cssClass: string;
|
||||
protected _enabled: boolean;
|
||||
protected _checked: boolean;
|
||||
protected _actionCallback: IActionCallback;
|
||||
protected _order: number;
|
||||
|
||||
constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback: IActionCallback = null) {
|
||||
this._id = id;
|
||||
this._label = label;
|
||||
this._cssClass = cssClass;
|
||||
@@ -95,6 +97,14 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._actionCallback = actionCallback;
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this._onDidChange.dispose();
|
||||
}
|
||||
|
||||
public get onDidChange(): Event<IActionChangeEvent> {
|
||||
return this._onDidChange.event;
|
||||
}
|
||||
|
||||
public get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
@@ -107,10 +117,10 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._setLabel(value);
|
||||
}
|
||||
|
||||
_setLabel(value: string): void {
|
||||
protected _setLabel(value: string): void {
|
||||
if (this._label !== value) {
|
||||
this._label = value;
|
||||
this.emit(Action.LABEL, { source: this });
|
||||
this._onDidChange.fire({ label: value });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,10 +132,10 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._setTooltip(value);
|
||||
}
|
||||
|
||||
_setTooltip(value: string): void {
|
||||
protected _setTooltip(value: string): void {
|
||||
if (this._tooltip !== value) {
|
||||
this._tooltip = value;
|
||||
this.emit(Action.TOOLTIP, { source: this });
|
||||
this._onDidChange.fire({ tooltip: value });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,10 +147,10 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._setClass(value);
|
||||
}
|
||||
|
||||
_setClass(value: string): void {
|
||||
protected _setClass(value: string): void {
|
||||
if (this._cssClass !== value) {
|
||||
this._cssClass = value;
|
||||
this.emit(Action.CLASS, { source: this });
|
||||
this._onDidChange.fire({ class: value });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,10 +162,10 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._setEnabled(value);
|
||||
}
|
||||
|
||||
_setEnabled(value: boolean): void {
|
||||
protected _setEnabled(value: boolean): void {
|
||||
if (this._enabled !== value) {
|
||||
this._enabled = value;
|
||||
this.emit(Action.ENABLED, { source: this });
|
||||
this._onDidChange.fire({ enabled: value });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,10 +177,10 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._setChecked(value);
|
||||
}
|
||||
|
||||
_setChecked(value: boolean): void {
|
||||
protected _setChecked(value: boolean): void {
|
||||
if (this._checked !== value) {
|
||||
this._checked = value;
|
||||
this.emit(Action.CHECKED, { source: this });
|
||||
this._onDidChange.fire({ checked: value });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,14 +192,6 @@ export class Action extends EventEmitter implements IAction {
|
||||
this._order = value;
|
||||
}
|
||||
|
||||
public get actionCallback(): IActionCallback {
|
||||
return this._actionCallback;
|
||||
}
|
||||
|
||||
public set actionCallback(value: IActionCallback) {
|
||||
this._actionCallback = value;
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<any> {
|
||||
if (this._actionCallback !== null) {
|
||||
return this._actionCallback(event);
|
||||
|
||||
@@ -603,7 +603,7 @@ export class QuickOpenWidget implements IModelProvider {
|
||||
this.tree.layout();
|
||||
|
||||
// Handle auto focus
|
||||
if (!this.tree.getFocus() && input && input.entries.some(e => this.isElementVisible(input, e))) {
|
||||
if (input && input.entries.some(e => this.isElementVisible(input, e))) {
|
||||
this.autoFocus(input, autoFocus);
|
||||
}
|
||||
}, errors.onUnexpectedError);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'original-fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { app } from 'electron';
|
||||
@@ -263,7 +263,8 @@ function parsePathArguments(cwd: string, args: string[], gotoLineMode?: boolean)
|
||||
realPath = path.normalize(path.isAbsolute(pathCandidate) ? pathCandidate : path.join(cwd, pathCandidate));
|
||||
}
|
||||
|
||||
if (!paths.isValidBasename(path.basename(realPath))) {
|
||||
const basename = path.basename(realPath);
|
||||
if (basename /* can be empty if code is opened on root */ && !paths.isValidBasename(basename)) {
|
||||
return null; // do not allow invalid file names
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'original-fs';
|
||||
import { app, ipcMain as ipc } from 'electron';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { mkdirp } from 'vs/base/node/pfs';
|
||||
|
||||
@@ -193,7 +193,7 @@ export class VSCodeMenu {
|
||||
|
||||
// Goto
|
||||
let gotoMenu = new Menu();
|
||||
let gotoMenuItem = new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Goto")), submenu: gotoMenu });
|
||||
let gotoMenuItem = new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go")), submenu: gotoMenu });
|
||||
this.setGotoMenu(gotoMenu);
|
||||
|
||||
// Mac: Window
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'original-fs';
|
||||
import { EventEmitter } from 'events';
|
||||
import { IEnvironmentService } from 'vs/code/electron-main/env';
|
||||
import { ServiceIdentifier, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'original-fs';
|
||||
import * as path from 'path';
|
||||
import * as electron from 'electron';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'original-fs';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
|
||||
@@ -32,7 +32,7 @@ import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppen
|
||||
|
||||
const notFound = id => localize('notFound', "Extension '{0}' not found.", id);
|
||||
const notInstalled = id => localize('notInstalled', "Extension '{0}' is not installed.", id);
|
||||
const useId = localize('useId', "Make sure you use the full extension ID, eg: {0}", 'ms-vscode.csharp');
|
||||
const useId = localize('useId', "Make sure you use the full extension ID, including the publisher, eg: {0}", 'ms-vscode.csharp');
|
||||
|
||||
function getId(manifest: IExtensionManifest): string {
|
||||
return `${ manifest.publisher }.${ manifest.name }`;
|
||||
|
||||
@@ -26,7 +26,6 @@ import 'vs/editor/contrib/linesOperations/common/linesOperations';
|
||||
import 'vs/editor/contrib/carretOperations/common/carretOperations';
|
||||
import 'vs/editor/contrib/links/browser/links';
|
||||
import 'vs/editor/contrib/multicursor/common/multicursor';
|
||||
import 'vs/editor/contrib/outlineMarker/browser/outlineMarker';
|
||||
import 'vs/editor/contrib/parameterHints/browser/parameterHints';
|
||||
import 'vs/editor/contrib/quickFix/browser/quickFix';
|
||||
import 'vs/editor/contrib/referenceSearch/browser/referenceSearch';
|
||||
|
||||
@@ -437,6 +437,7 @@ export function createMonacoEditorAPI(): typeof monaco.editor {
|
||||
// consts
|
||||
KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS: editorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS,
|
||||
KEYBINDING_CONTEXT_EDITOR_FOCUS: editorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS,
|
||||
KEYBINDING_CONTEXT_EDITOR_READONLY: editorCommon.KEYBINDING_CONTEXT_EDITOR_READONLY,
|
||||
KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS: editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS,
|
||||
KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION: editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION,
|
||||
KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID: editorCommon.KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID,
|
||||
|
||||
@@ -113,6 +113,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
|
||||
private _editorIdContextKey: IKeybindingContextKey<string>;
|
||||
protected _editorFocusContextKey: IKeybindingContextKey<boolean>;
|
||||
private _editorTabMovesFocusKey: IKeybindingContextKey<boolean>;
|
||||
private _editorReadonly: IKeybindingContextKey<boolean>;
|
||||
private _hasMultipleSelectionsKey: IKeybindingContextKey<boolean>;
|
||||
private _hasNonEmptySelectionKey: IKeybindingContextKey<boolean>;
|
||||
private _langIdKey: IKeybindingContextKey<string>;
|
||||
@@ -141,6 +142,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
|
||||
this._editorIdContextKey = this._keybindingService.createKey('editorId', this.getId());
|
||||
this._editorFocusContextKey = this._keybindingService.createKey(editorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS, undefined);
|
||||
this._editorTabMovesFocusKey = this._keybindingService.createKey(editorCommon.KEYBINDING_CONTEXT_EDITOR_TAB_MOVES_FOCUS, false);
|
||||
this._editorReadonly = this._keybindingService.createKey(editorCommon.KEYBINDING_CONTEXT_EDITOR_READONLY, false);
|
||||
this._hasMultipleSelectionsKey = this._keybindingService.createKey(editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_MULTIPLE_SELECTIONS, false);
|
||||
this._hasNonEmptySelectionKey = this._keybindingService.createKey(editorCommon.KEYBINDING_CONTEXT_EDITOR_HAS_NON_EMPTY_SELECTION, false);
|
||||
this._langIdKey = this._keybindingService.createKey<string>(editorCommon.KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID, undefined);
|
||||
@@ -157,7 +159,15 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
|
||||
if (this._configuration.editor.tabFocusMode) {
|
||||
this._editorTabMovesFocusKey.set(true);
|
||||
}
|
||||
this._lifetimeDispose.push(this._configuration.onDidChange((e) => this.emit(editorCommon.EventType.ConfigurationChanged, e)));
|
||||
this._editorReadonly.set(this._configuration.editor.readOnly);
|
||||
this._lifetimeDispose.push(this._configuration.onDidChange((e) => {
|
||||
if (this._configuration.editor.tabFocusMode) {
|
||||
this._editorTabMovesFocusKey.set(true);
|
||||
} else {
|
||||
this._editorTabMovesFocusKey.reset();
|
||||
}
|
||||
this.emit(editorCommon.EventType.ConfigurationChanged, e);
|
||||
}));
|
||||
|
||||
this._telemetryService = telemetryService;
|
||||
this._instantiationService = instantiationService.createChild(new ServiceCollection([IKeybindingService, this._keybindingService]));
|
||||
@@ -212,11 +222,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
|
||||
|
||||
public updateOptions(newOptions:editorCommon.IEditorOptions): void {
|
||||
this._configuration.updateOptions(newOptions);
|
||||
if (this._configuration.editor.tabFocusMode) {
|
||||
this._editorTabMovesFocusKey.set(true);
|
||||
} else {
|
||||
this._editorTabMovesFocusKey.reset();
|
||||
}
|
||||
this._editorReadonly.set(this._configuration.editor.readOnly);
|
||||
}
|
||||
|
||||
public getConfiguration(): editorCommon.InternalEditorOptions {
|
||||
@@ -708,6 +714,12 @@ export abstract class CommonCodeEditor extends EventEmitter implements IActionPr
|
||||
if (oldDecorationsIds) {
|
||||
this.deltaDecorations(oldDecorationsIds, []);
|
||||
}
|
||||
if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {
|
||||
delete this._decorationTypeKeysToIds[decorationTypeKey];
|
||||
}
|
||||
if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {
|
||||
delete this._decorationTypeSubtypes[decorationTypeKey];
|
||||
}
|
||||
}
|
||||
|
||||
public addTypingListener(character:string, callback: () => void): IDisposable {
|
||||
|
||||
@@ -55,6 +55,38 @@ export const EditorZoom: IEditorZoom = new class {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Control what pressing Tab does.
|
||||
* If it is false, pressing Tab or Shift-Tab will be handled by the editor.
|
||||
* If it is true, pressing Tab or Shift-Tab will move the browser focus.
|
||||
* Defaults to false.
|
||||
*/
|
||||
export interface ITabFocus {
|
||||
onDidChangeTabFocus:Event<boolean>;
|
||||
getTabFocusMode(): boolean;
|
||||
setTabFocusMode(tabFocusMode:boolean): void;
|
||||
}
|
||||
|
||||
export const TabFocus: ITabFocus = new class {
|
||||
private _tabFocus: boolean = false;
|
||||
|
||||
private _onDidChangeTabFocus: Emitter<boolean> = new Emitter<boolean>();
|
||||
public onDidChangeTabFocus:Event<boolean> = this._onDidChangeTabFocus.event;
|
||||
|
||||
public getTabFocusMode(): boolean {
|
||||
return this._tabFocus;
|
||||
}
|
||||
|
||||
public setTabFocusMode(tabFocusMode:boolean): void {
|
||||
if (this._tabFocus === tabFocusMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._tabFocus = tabFocusMode;
|
||||
this._onDidChangeTabFocus.fire(this._tabFocus);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Experimental screen reader support toggle
|
||||
*/
|
||||
@@ -188,7 +220,7 @@ class InternalEditorOptionsHelper {
|
||||
|
||||
let readOnly = toBoolean(opts.readOnly);
|
||||
|
||||
let tabFocusMode = toBoolean(opts.tabFocusMode);
|
||||
let tabFocusMode = TabFocus.getTabFocusMode();
|
||||
if (readOnly) {
|
||||
tabFocusMode = true;
|
||||
}
|
||||
@@ -230,7 +262,6 @@ class InternalEditorOptionsHelper {
|
||||
suggestOnTriggerCharacters: toBoolean(opts.suggestOnTriggerCharacters),
|
||||
acceptSuggestionOnEnter: toBoolean(opts.acceptSuggestionOnEnter),
|
||||
selectionHighlight: toBoolean(opts.selectionHighlight),
|
||||
outlineMarkers: toBoolean(opts.outlineMarkers),
|
||||
referenceInfos: toBoolean(opts.referenceInfos),
|
||||
folding: toBoolean(opts.folding),
|
||||
});
|
||||
@@ -391,6 +422,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed
|
||||
this.editor = this._computeInternalOptions();
|
||||
this.editorClone = this.editor.clone();
|
||||
this._register(EditorZoom.onDidChangeZoomLevel(_ => this._recomputeOptions()));
|
||||
this._register(TabFocus.onDidChangeTabFocus(_ => this._recomputeOptions()));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -663,11 +695,6 @@ let editorConfiguration:IConfigurationNode = {
|
||||
'default': DefaultConfig.editor.selectionHighlight,
|
||||
'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight similar matches to the selection")
|
||||
},
|
||||
// 'editor.outlineMarkers' : {
|
||||
// 'type': 'boolean',
|
||||
// 'default': DefaultConfig.editor.outlineMarkers,
|
||||
// 'description': nls.localize('outlineMarkers', "Controls whether the editor should draw horizontal lines before classes and methods")
|
||||
// },
|
||||
'editor.overviewRulerLanes' : {
|
||||
'type': 'integer',
|
||||
'default': 3,
|
||||
|
||||
@@ -70,7 +70,6 @@ class ConfigClass implements IConfiguration {
|
||||
wordWrapBreakBeforeCharacters: '([{‘“〈《「『【〔([{「£¥$£¥++',
|
||||
wordWrapBreakAfterCharacters: ' \t})]?|&,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー’”〉》」』】〕)]}」',
|
||||
wordWrapBreakObtrusiveCharacters: '.',
|
||||
tabFocusMode: false,
|
||||
|
||||
// Features
|
||||
hover: true,
|
||||
@@ -85,7 +84,6 @@ class ConfigClass implements IConfiguration {
|
||||
suggestOnTriggerCharacters: true,
|
||||
acceptSuggestionOnEnter: true,
|
||||
selectionHighlight: true,
|
||||
outlineMarkers: false,
|
||||
referenceInfos: true,
|
||||
folding: true,
|
||||
renderWhitespace: false,
|
||||
|
||||
@@ -1518,26 +1518,31 @@ export class OneCursorOp {
|
||||
|
||||
ctx.isAutoWhitespaceCommand = true;
|
||||
|
||||
let typeText = '';
|
||||
|
||||
if (cursor.model.getLineMaxColumn(selection.startLineNumber) === 1) {
|
||||
// Line is empty => indent straight to the right place
|
||||
typeText = cursor.model.normalizeIndentation(this._goodIndentForLine(cursor, selection.startLineNumber));
|
||||
} else {
|
||||
let position = cursor.getPosition();
|
||||
let modelOpts = cursor.model.getOptions();
|
||||
if (modelOpts.insertSpaces) {
|
||||
let visibleColumnFromColumn = cursor.getVisibleColumnFromColumn(position.lineNumber, position.column);
|
||||
let tabSize = modelOpts.tabSize;
|
||||
let spacesCnt = tabSize - (visibleColumnFromColumn % tabSize);
|
||||
for (let i = 0; i < spacesCnt; i++) {
|
||||
typeText += ' ';
|
||||
}
|
||||
} else {
|
||||
typeText = '\t';
|
||||
let lineText = cursor.model.getLineContent(selection.startLineNumber);
|
||||
|
||||
if (/^\s*$/.test(lineText)) {
|
||||
let possibleTypeText = cursor.model.normalizeIndentation(this._goodIndentForLine(cursor, selection.startLineNumber));
|
||||
if (!strings.startsWith(lineText, possibleTypeText)) {
|
||||
ctx.executeCommand = new ReplaceCommand(new Range(selection.startLineNumber, 1, selection.startLineNumber, lineText.length + 1), possibleTypeText);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
let typeText = '';
|
||||
let position = cursor.getPosition();
|
||||
let modelOpts = cursor.model.getOptions();
|
||||
if (modelOpts.insertSpaces) {
|
||||
let visibleColumnFromColumn = cursor.getVisibleColumnFromColumn(position.lineNumber, position.column);
|
||||
let tabSize = modelOpts.tabSize;
|
||||
let spacesCnt = tabSize - (visibleColumnFromColumn % tabSize);
|
||||
for (let i = 0; i < spacesCnt; i++) {
|
||||
typeText += ' ';
|
||||
}
|
||||
} else {
|
||||
typeText = '\t';
|
||||
}
|
||||
|
||||
ctx.executeCommand = new ReplaceCommand(selection, typeText);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -328,14 +328,6 @@ export interface IEditorOptions {
|
||||
*/
|
||||
wordWrapBreakObtrusiveCharacters?: string;
|
||||
|
||||
/**
|
||||
* Control what pressing Tab does.
|
||||
* If it is false, pressing Tab or Shift-Tab will be handled by the editor.
|
||||
* If it is true, pressing Tab or Shift-Tab will move the browser focus.
|
||||
* Defaults to false.
|
||||
*/
|
||||
tabFocusMode?:boolean;
|
||||
|
||||
/**
|
||||
* Performance guard: Stop rendering a line after x characters.
|
||||
* Defaults to 10000 if wrappingColumn is -1. Defaults to -1 if wrappingColumn is >= 0.
|
||||
@@ -401,11 +393,6 @@ export interface IEditorOptions {
|
||||
* Defaults to true.
|
||||
*/
|
||||
selectionHighlight?:boolean;
|
||||
/**
|
||||
* Show lines before classes and methods (based on outline info).
|
||||
* Defaults to false.
|
||||
*/
|
||||
outlineMarkers?: boolean;
|
||||
/**
|
||||
* Show reference infos (a.k.a. code lenses) for modes that support it
|
||||
* Defaults to true.
|
||||
@@ -811,7 +798,6 @@ export class EditorContribOptions {
|
||||
suggestOnTriggerCharacters: boolean;
|
||||
acceptSuggestionOnEnter: boolean;
|
||||
selectionHighlight:boolean;
|
||||
outlineMarkers: boolean;
|
||||
referenceInfos: boolean;
|
||||
folding: boolean;
|
||||
|
||||
@@ -830,7 +816,6 @@ export class EditorContribOptions {
|
||||
suggestOnTriggerCharacters: boolean;
|
||||
acceptSuggestionOnEnter: boolean;
|
||||
selectionHighlight:boolean;
|
||||
outlineMarkers: boolean;
|
||||
referenceInfos: boolean;
|
||||
folding: boolean;
|
||||
}) {
|
||||
@@ -845,7 +830,6 @@ export class EditorContribOptions {
|
||||
this.suggestOnTriggerCharacters = Boolean(source.suggestOnTriggerCharacters);
|
||||
this.acceptSuggestionOnEnter = Boolean(source.acceptSuggestionOnEnter);
|
||||
this.selectionHighlight = Boolean(source.selectionHighlight);
|
||||
this.outlineMarkers = Boolean(source.outlineMarkers);
|
||||
this.referenceInfos = Boolean(source.referenceInfos);
|
||||
this.folding = Boolean(source.folding);
|
||||
}
|
||||
@@ -866,7 +850,6 @@ export class EditorContribOptions {
|
||||
&& this.suggestOnTriggerCharacters === other.suggestOnTriggerCharacters
|
||||
&& this.acceptSuggestionOnEnter === other.acceptSuggestionOnEnter
|
||||
&& this.selectionHighlight === other.selectionHighlight
|
||||
&& this.outlineMarkers === other.outlineMarkers
|
||||
&& this.referenceInfos === other.referenceInfos
|
||||
&& this.folding === other.folding
|
||||
);
|
||||
@@ -3052,6 +3035,10 @@ export const KEYBINDING_CONTEXT_EDITOR_FOCUS = 'editorFocus';
|
||||
* @internal
|
||||
*/
|
||||
export const KEYBINDING_CONTEXT_EDITOR_TAB_MOVES_FOCUS = 'editorTabMovesFocus';
|
||||
/**
|
||||
* A context key that is set when the editor's text is readonly.
|
||||
*/
|
||||
export const KEYBINDING_CONTEXT_EDITOR_READONLY = 'editorReadonly';
|
||||
/**
|
||||
* A context key that is set when the editor has multiple selections (multiple cursors).
|
||||
*/
|
||||
|
||||
@@ -34,8 +34,8 @@ export interface CommentRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* The language configuration interfaces defines the contract between extensions
|
||||
* and various editor features, like automatic bracket insertion, automatic indentation etc.
|
||||
* The language configuration interface defines the contract between extensions and
|
||||
* various editor features, like automatic bracket insertion, automatic indentation etc.
|
||||
*/
|
||||
export interface LanguageConfiguration {
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import {IReadOnlyModel} from 'vs/editor/common/editorCommon';
|
||||
import {ISuggestResult, ISuggestSupport} from 'vs/editor/common/modes';
|
||||
import {IFilter, matchesStrictPrefix, fuzzyContiguousFilter} from 'vs/base/common/filters';
|
||||
import {IFilter, matchesPrefix, fuzzyContiguousFilter} from 'vs/base/common/filters';
|
||||
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
|
||||
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
|
||||
import {IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry';
|
||||
@@ -41,7 +41,7 @@ export class TextualSuggestSupport implements ISuggestSupport {
|
||||
}
|
||||
|
||||
public get filter(): IFilter {
|
||||
return matchesStrictPrefix;
|
||||
return matchesPrefix;
|
||||
}
|
||||
|
||||
private _editorWorkerService: IEditorWorkerService;
|
||||
|
||||
@@ -18,6 +18,8 @@ import {EditorAction} from 'vs/editor/common/editorAction';
|
||||
import {Behaviour} from 'vs/editor/common/editorActionEnablement';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {MenuRegistry} from 'vs/platform/actions/browser/menuService';
|
||||
import {MenuId} from 'vs/platform/actions/common/actions';
|
||||
|
||||
class ClipboardWritingAction extends EditorAction {
|
||||
|
||||
@@ -62,7 +64,7 @@ function editorCursorIsInEditableRange(editor:editorCommon.ICommonCodeEditor): b
|
||||
class ExecCommandCutAction extends ClipboardWritingAction {
|
||||
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor, Behaviour.Writeable | Behaviour.WidgetFocus | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange);
|
||||
super(descriptor, editor, Behaviour.Writeable | Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
@@ -83,7 +85,7 @@ class ExecCommandCutAction extends ClipboardWritingAction {
|
||||
class ExecCommandCopyAction extends ClipboardWritingAction {
|
||||
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.ShowInContextMenu);
|
||||
super(descriptor, editor, Behaviour.WidgetFocus);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
@@ -100,7 +102,7 @@ class ExecCommandCopyAction extends ClipboardWritingAction {
|
||||
class ExecCommandPasteAction extends EditorAction {
|
||||
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor, Behaviour.Writeable | Behaviour.WidgetFocus | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange);
|
||||
super(descriptor, editor, Behaviour.Writeable | Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
@@ -123,8 +125,9 @@ interface IClipboardCommand extends IKeybindings {
|
||||
id: string;
|
||||
label: string;
|
||||
execCommand: string;
|
||||
kbExpr: KbExpr;
|
||||
}
|
||||
function registerClipboardAction(desc:IClipboardCommand, alias:string) {
|
||||
function registerClipboardAction(desc: IClipboardCommand, alias: string, weight: number) {
|
||||
if (!browser.supportsExecCommand(desc.execCommand)) {
|
||||
return;
|
||||
}
|
||||
@@ -139,6 +142,17 @@ function registerClipboardAction(desc:IClipboardCommand, alias:string) {
|
||||
mac: desc.mac,
|
||||
kbExpr: KbExpr.has(editorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS)
|
||||
}, alias));
|
||||
|
||||
MenuRegistry.addCommand({
|
||||
id: desc.id,
|
||||
title: desc.label
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
|
||||
command: MenuRegistry.getCommand(desc.id),
|
||||
group: `cutcopypaste@${weight}`,
|
||||
when: desc.kbExpr
|
||||
});
|
||||
}
|
||||
|
||||
registerClipboardAction({
|
||||
@@ -147,24 +161,29 @@ registerClipboardAction({
|
||||
label: nls.localize('actions.clipboard.cutLabel', "Cut"),
|
||||
execCommand: 'cut',
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_X,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_X, secondary: [KeyMod.Shift | KeyCode.Delete] }
|
||||
}, 'Cut');
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_X, secondary: [KeyMod.Shift | KeyCode.Delete] },
|
||||
kbExpr: KbExpr.and(KbExpr.has(editorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS), KbExpr.not(editorCommon.KEYBINDING_CONTEXT_EDITOR_READONLY))
|
||||
}, 'Cut', 1);
|
||||
|
||||
registerClipboardAction({
|
||||
ctor: ExecCommandCopyAction,
|
||||
id: 'editor.action.clipboardCopyAction',
|
||||
label: nls.localize('actions.clipboard.copyLabel', "Copy"),
|
||||
execCommand: 'copy',
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_C,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_C, secondary: [KeyMod.CtrlCmd | KeyCode.Insert] }
|
||||
}, 'Copy');
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_C, secondary: [KeyMod.CtrlCmd | KeyCode.Insert] },
|
||||
kbExpr: KbExpr.has(editorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS)
|
||||
}, 'Copy', 2);
|
||||
|
||||
registerClipboardAction({
|
||||
ctor: ExecCommandPasteAction,
|
||||
id: 'editor.action.clipboardPasteAction',
|
||||
label: nls.localize('actions.clipboard.pasteLabel', "Paste"),
|
||||
execCommand: 'paste',
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] }
|
||||
}, 'Paste');
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] },
|
||||
kbExpr: KbExpr.and(KbExpr.has(editorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS), KbExpr.not(editorCommon.KEYBINDING_CONTEXT_EDITOR_READONLY))
|
||||
}, 'Paste', 3);
|
||||
|
||||
function execCommandToHandler(actionId: string, browserCommand: string, accessor: ServicesAccessor, args: any): void {
|
||||
let focusedEditor = findFocusedEditor(actionId, accessor, false);
|
||||
|
||||
@@ -343,14 +343,14 @@ export interface IMultiCursorFindResult {
|
||||
matchCase:boolean;
|
||||
wholeWord:boolean;
|
||||
|
||||
nextMatch: Selection;
|
||||
currentMatch: Selection;
|
||||
}
|
||||
|
||||
function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearchString:boolean): IMultiCursorFindResult {
|
||||
let controller = CommonFindController.getFindController(editor);
|
||||
let state = controller.getState();
|
||||
let searchText: string,
|
||||
nextMatch: Selection;
|
||||
let searchText: string;
|
||||
let currentMatch: Selection;
|
||||
|
||||
// In any case, if the find widget was ever opened, the options are taken from it
|
||||
let wholeWord = state.wholeWord;
|
||||
@@ -379,7 +379,7 @@ function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearch
|
||||
return null;
|
||||
}
|
||||
searchText = word.word;
|
||||
nextMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn);
|
||||
currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn);
|
||||
} else {
|
||||
searchText = editor.getModel().getValueInRange(s);
|
||||
}
|
||||
@@ -392,7 +392,7 @@ function multiCursorFind(editor:editorCommon.ICommonCodeEditor, changeFindSearch
|
||||
searchText: searchText,
|
||||
matchCase: matchCase,
|
||||
wholeWord: wholeWord,
|
||||
nextMatch: nextMatch
|
||||
currentMatch: currentMatch
|
||||
};
|
||||
}
|
||||
|
||||
@@ -406,8 +406,8 @@ export class SelectNextFindMatchAction extends EditorAction {
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
if (r.nextMatch) {
|
||||
return r.nextMatch;
|
||||
if (r.currentMatch) {
|
||||
return r.currentMatch;
|
||||
}
|
||||
|
||||
let allSelections = this.editor.getSelections();
|
||||
@@ -423,6 +423,33 @@ export class SelectNextFindMatchAction extends EditorAction {
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectPreviousFindMatchAction extends EditorAction {
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor, Behaviour.WidgetFocus);
|
||||
}
|
||||
|
||||
protected _getPreviousMatch(): Selection {
|
||||
let r = multiCursorFind(this.editor, true);
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
if (r.currentMatch) {
|
||||
return r.currentMatch;
|
||||
}
|
||||
|
||||
let allSelections = this.editor.getSelections();
|
||||
let lastAddedSelection = allSelections[allSelections.length - 1];
|
||||
|
||||
let previousMatch = this.editor.getModel().findPreviousMatch(r.searchText, lastAddedSelection.getStartPosition(), false, r.matchCase, r.wholeWord);
|
||||
|
||||
if (!previousMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Selection(previousMatch.startLineNumber, previousMatch.startColumn, previousMatch.endLineNumber, previousMatch.endColumn);
|
||||
}
|
||||
}
|
||||
|
||||
export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction {
|
||||
static ID = FIND_IDS.AddSelectionToNextFindMatchAction;
|
||||
|
||||
@@ -445,6 +472,28 @@ export class AddSelectionToNextFindMatchAction extends SelectNextFindMatchAction
|
||||
}
|
||||
}
|
||||
|
||||
export class AddSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction {
|
||||
static ID = FIND_IDS.AddSelectionToPreviousFindMatchAction;
|
||||
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor);
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
let previousMatch = this._getPreviousMatch();
|
||||
|
||||
if (!previousMatch) {
|
||||
return TPromise.as(false);
|
||||
}
|
||||
|
||||
let allSelections = this.editor.getSelections();
|
||||
this.editor.setSelections(allSelections.concat(previousMatch));
|
||||
this.editor.revealRangeInCenterIfOutsideViewport(previousMatch);
|
||||
|
||||
return TPromise.as(true);
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchAction {
|
||||
static ID = FIND_IDS.MoveSelectionToNextFindMatchAction;
|
||||
|
||||
@@ -467,6 +516,28 @@ export class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchActio
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveSelectionToPreviousFindMatchAction extends SelectPreviousFindMatchAction {
|
||||
static ID = FIND_IDS.MoveSelectionToPreviousFindMatchAction;
|
||||
|
||||
constructor(descriptor:editorCommon.IEditorActionDescriptorData, editor:editorCommon.ICommonCodeEditor) {
|
||||
super(descriptor, editor);
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
let previousMatch = this._getPreviousMatch();
|
||||
|
||||
if (!previousMatch) {
|
||||
return TPromise.as(false);
|
||||
}
|
||||
|
||||
let allSelections = this.editor.getSelections();
|
||||
this.editor.setSelections(allSelections.slice(0, allSelections.length - 1).concat(previousMatch));
|
||||
this.editor.revealRangeInCenterIfOutsideViewport(previousMatch);
|
||||
|
||||
return TPromise.as(true);
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectHighlightsAction extends EditorAction {
|
||||
static ID = 'editor.action.selectHighlights';
|
||||
static COMPAT_ID = 'editor.action.changeAll';
|
||||
@@ -566,7 +637,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd
|
||||
}
|
||||
|
||||
let hasFindOccurences = DocumentHighlightProviderRegistry.has(model);
|
||||
if (r.nextMatch) {
|
||||
if (r.currentMatch) {
|
||||
// This is an empty selection
|
||||
if (hasFindOccurences) {
|
||||
// Do not interfere with semantic word highlighting in the no selection case
|
||||
@@ -574,7 +645,7 @@ export class SelectionHighlighter extends Disposable implements editorCommon.IEd
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastWordUnderCursor = r.nextMatch;
|
||||
this.lastWordUnderCursor = r.currentMatch;
|
||||
}
|
||||
if (/^[ \t]+$/.test(r.searchText)) {
|
||||
// whitespace only selection
|
||||
@@ -697,10 +768,19 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveSelecti
|
||||
context: ContextKey.EditorFocus,
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)
|
||||
}, 'Move Last Selection To Next Find Match'));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveSelectionToPreviousFindMatchAction, MoveSelectionToPreviousFindMatchAction.ID, nls.localize('moveSelectionToPreviousFindMatch', "Move Last Selection To Previous Find Match"), {
|
||||
context: ContextKey.EditorFocus,
|
||||
primary: 0
|
||||
}, 'Move Last Selection To Previous Find Match'));
|
||||
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(AddSelectionToNextFindMatchAction, AddSelectionToNextFindMatchAction.ID, nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"), {
|
||||
context: ContextKey.EditorFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_D
|
||||
}, 'Add Selection To Next Find Match'));
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(AddSelectionToPreviousFindMatchAction, AddSelectionToPreviousFindMatchAction.ID, nls.localize('addSelectionToPreviousFindMatch', "Add Selection To Previous Find Match"), {
|
||||
context: ContextKey.EditorFocus,
|
||||
primary: 0
|
||||
}, 'Add Selection To Previous Find Match'));
|
||||
|
||||
function registerFindCommand(id:string, callback:(controller:CommonFindController)=>void, keybindings:IKeybindings, needsKey:string = null): void {
|
||||
CommonEditorRegistry.registerEditorCommand(id, CommonEditorRegistry.commandWeight(5), keybindings, false, needsKey, (ctx, editor, args) => {
|
||||
|
||||
@@ -14,6 +14,7 @@ export class FindDecorations implements IDisposable {
|
||||
private _editor:editorCommon.ICommonCodeEditor;
|
||||
private _decorations:string[];
|
||||
private _findScopeDecorationId:string;
|
||||
private _lineHighlightDecorationId:string;
|
||||
private _highlightedDecorationId:string;
|
||||
private _startPosition:Position;
|
||||
|
||||
@@ -21,6 +22,7 @@ export class FindDecorations implements IDisposable {
|
||||
this._editor = editor;
|
||||
this._decorations = [];
|
||||
this._findScopeDecorationId = null;
|
||||
this._lineHighlightDecorationId = null;
|
||||
this._highlightedDecorationId = null;
|
||||
this._startPosition = this._editor.getPosition();
|
||||
}
|
||||
@@ -31,6 +33,7 @@ export class FindDecorations implements IDisposable {
|
||||
this._editor = null;
|
||||
this._decorations = [];
|
||||
this._findScopeDecorationId = null;
|
||||
this._lineHighlightDecorationId = null;
|
||||
this._highlightedDecorationId = null;
|
||||
this._startPosition = null;
|
||||
}
|
||||
@@ -38,6 +41,7 @@ export class FindDecorations implements IDisposable {
|
||||
public reset(): void {
|
||||
this._decorations = [];
|
||||
this._findScopeDecorationId = null;
|
||||
this._lineHighlightDecorationId = null;
|
||||
this._highlightedDecorationId = null;
|
||||
}
|
||||
|
||||
@@ -95,6 +99,14 @@ export class FindDecorations implements IDisposable {
|
||||
this._highlightedDecorationId = newCurrentDecorationId;
|
||||
changeAccessor.changeDecorationOptions(this._highlightedDecorationId, FindDecorations.createFindMatchDecorationOptions(true));
|
||||
}
|
||||
if (this._lineHighlightDecorationId !== null) {
|
||||
changeAccessor.removeDecoration(this._lineHighlightDecorationId);
|
||||
this._lineHighlightDecorationId = null;
|
||||
}
|
||||
if (newCurrentDecorationId !== null) {
|
||||
let rng = this._editor.getModel().getDecorationRange(newCurrentDecorationId);
|
||||
this._lineHighlightDecorationId = changeAccessor.addDecoration(rng, FindDecorations.createLineHighlightDecoration());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -122,6 +134,7 @@ export class FindDecorations implements IDisposable {
|
||||
this._findScopeDecorationId = null;
|
||||
}
|
||||
this._decorations = tmpDecorations;
|
||||
this._lineHighlightDecorationId = null;
|
||||
this._highlightedDecorationId = null;
|
||||
}
|
||||
|
||||
@@ -131,6 +144,9 @@ export class FindDecorations implements IDisposable {
|
||||
if (this._findScopeDecorationId) {
|
||||
result.push(this._findScopeDecorationId);
|
||||
}
|
||||
if (this._lineHighlightDecorationId) {
|
||||
result.push(this._lineHighlightDecorationId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -146,6 +162,14 @@ export class FindDecorations implements IDisposable {
|
||||
};
|
||||
}
|
||||
|
||||
private static createLineHighlightDecoration(): editorCommon.IModelDecorationOptions {
|
||||
return {
|
||||
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
className: 'lineHighlight',
|
||||
isWholeLine: true
|
||||
};
|
||||
}
|
||||
|
||||
private static createFindScopeDecorationOptions(): editorCommon.IModelDecorationOptions {
|
||||
return {
|
||||
className: 'findScope',
|
||||
|
||||
@@ -23,7 +23,9 @@ export const FIND_IDS = {
|
||||
NextSelectionMatchFindAction: 'editor.action.nextSelectionMatchFindAction',
|
||||
PreviousSelectionMatchFindAction: 'editor.action.previousSelectionMatchFindAction',
|
||||
AddSelectionToNextFindMatchAction: 'editor.action.addSelectionToNextFindMatch',
|
||||
AddSelectionToPreviousFindMatchAction: 'editor.action.addSelectionToPreviousFindMatch',
|
||||
MoveSelectionToNextFindMatchAction: 'editor.action.moveSelectionToNextFindMatch',
|
||||
MoveSelectionToPreviousFindMatchAction: 'editor.action.moveSelectionToPreviousFindMatch',
|
||||
StartFindReplaceAction: 'editor.action.startFindReplaceAction',
|
||||
CloseFindWidgetCommand: 'closeFindWidget',
|
||||
ToggleCaseSensitiveCommand: 'toggleFindCaseSensitive',
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
hr.outlineRule.class {
|
||||
border: 0;
|
||||
border-bottom: 2px solid gray;
|
||||
width: 98%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
hr.outlineRule.method, hr.outlineRule.function {
|
||||
border: 0;
|
||||
border-bottom: 1px dotted gray;
|
||||
width: 98%;
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,271 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./outlineMarker';
|
||||
import {RunOnceScheduler} from 'vs/base/common/async';
|
||||
import {onUnexpectedError} from 'vs/base/common/errors';
|
||||
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import {SymbolInformation, SymbolKind, DocumentSymbolProviderRegistry} from 'vs/editor/common/modes';
|
||||
import {ICodeEditor, IViewZone, IViewZoneChangeAccessor} from 'vs/editor/browser/editorBrowser';
|
||||
import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import {getDocumentSymbols, IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
|
||||
class OutlineViewZone implements IViewZone {
|
||||
|
||||
public afterLineNumber:number;
|
||||
public heightInPx:number;
|
||||
public suppressMouseDown:boolean;
|
||||
|
||||
public domNode:HTMLElement;
|
||||
|
||||
constructor(range:editorCommon.IRange, outlineType:SymbolKind) {
|
||||
this.afterLineNumber = range.startLineNumber-1;
|
||||
this.heightInPx = 4;
|
||||
this.suppressMouseDown = true;
|
||||
|
||||
this.domNode = document.createElement('div');
|
||||
var hr = document.createElement('hr');
|
||||
hr.className = 'outlineRule ' + SymbolKind.from(outlineType);
|
||||
this.domNode.appendChild(hr);
|
||||
}
|
||||
}
|
||||
|
||||
interface IDecorationIdCallback {
|
||||
(decorationId:string):void;
|
||||
}
|
||||
|
||||
class OutlineMarkerHelper {
|
||||
private _removeDecorations:string[];
|
||||
private _addDecorations:editorCommon.IModelDeltaDecoration[];
|
||||
private _addDecorationsCallbacks:IDecorationIdCallback[];
|
||||
|
||||
constructor() {
|
||||
this._removeDecorations = [];
|
||||
this._addDecorations = [];
|
||||
this._addDecorationsCallbacks = [];
|
||||
}
|
||||
|
||||
public addDecoration(decoration:editorCommon.IModelDeltaDecoration, callback:IDecorationIdCallback): void {
|
||||
this._addDecorations.push(decoration);
|
||||
this._addDecorationsCallbacks.push(callback);
|
||||
}
|
||||
|
||||
public removeDecoration(decorationId:string): void {
|
||||
this._removeDecorations.push(decorationId);
|
||||
}
|
||||
|
||||
public commit(changeAccessor:editorCommon.IModelDecorationsChangeAccessor): void {
|
||||
var resultingDecorations = changeAccessor.deltaDecorations(this._removeDecorations, this._addDecorations);
|
||||
for (let i = 0, len = resultingDecorations.length; i < len; i++) {
|
||||
this._addDecorationsCallbacks[i](resultingDecorations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OutlineMarker {
|
||||
private _viewZone:OutlineViewZone;
|
||||
private _viewZoneId:number;
|
||||
private _decorationId:string;
|
||||
|
||||
private _editor:ICodeEditor;
|
||||
|
||||
|
||||
public constructor(range:editorCommon.IRange, outlineType:SymbolKind, _editor:ICodeEditor, helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor) {
|
||||
this._editor = _editor;
|
||||
this._viewZone = new OutlineViewZone(range, outlineType);
|
||||
this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone);
|
||||
helper.addDecoration({
|
||||
range: range,
|
||||
options: {}
|
||||
}, (decorationId) => {
|
||||
this._decorationId = decorationId;
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor): void {
|
||||
helper.removeDecoration(this._decorationId);
|
||||
viewZoneChangeAccessor.removeZone(this._viewZoneId);
|
||||
}
|
||||
|
||||
public getLine(): number {
|
||||
return this._viewZone.afterLineNumber;
|
||||
}
|
||||
|
||||
public update(viewZoneChangeAccessor:IViewZoneChangeAccessor): void {
|
||||
var range = this._editor.getModel().getDecorationRange(this._decorationId);
|
||||
|
||||
this._viewZone.afterLineNumber = range.startLineNumber - 1;
|
||||
viewZoneChangeAccessor.layoutZone(this._viewZoneId);
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineMarkerContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
public static ID = 'editor.outlineMarker';
|
||||
|
||||
private _editor:ICodeEditor;
|
||||
private _isEnabled: boolean;
|
||||
|
||||
private _globalToDispose:IDisposable[];
|
||||
|
||||
private _localToDispose:IDisposable[];
|
||||
private _currentOutlinePromise:TPromise<IOutline>;
|
||||
|
||||
private _markers:OutlineMarker[];
|
||||
|
||||
constructor(editor:ICodeEditor) {
|
||||
this._editor = editor;
|
||||
this._isEnabled = this._editor.getConfiguration().contribInfo.outlineMarkers;
|
||||
|
||||
this._globalToDispose = [];
|
||||
this._localToDispose = [];
|
||||
this._markers = [];
|
||||
this._currentOutlinePromise = null;
|
||||
|
||||
this._globalToDispose.push(this._editor.onDidChangeModel(() => this.onChange(true)));
|
||||
this._globalToDispose.push(this._editor.onDidChangeModelMode(() => this.onChange(false)));
|
||||
this._globalToDispose.push(this._editor.onDidChangeConfiguration((e: editorCommon.IConfigurationChangedEvent) => {
|
||||
let oldIsEnabled = this._isEnabled;
|
||||
this._isEnabled = this._editor.getConfiguration().contribInfo.outlineMarkers;
|
||||
if (oldIsEnabled !== this._isEnabled) {
|
||||
this.onChange(false);
|
||||
}
|
||||
}));
|
||||
|
||||
this.onChange(false);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.localDispose();
|
||||
this._globalToDispose = dispose(this._globalToDispose);
|
||||
}
|
||||
|
||||
private localDispose(): void {
|
||||
if (this._currentOutlinePromise) {
|
||||
this._currentOutlinePromise.cancel();
|
||||
}
|
||||
this._localToDispose = dispose(this._localToDispose);
|
||||
}
|
||||
|
||||
public getId():string {
|
||||
return OutlineMarkerContribution.ID;
|
||||
}
|
||||
|
||||
private onChange( markersAlreadyDisposed : boolean): void {
|
||||
|
||||
if (markersAlreadyDisposed) {
|
||||
this._markers = [];
|
||||
}
|
||||
|
||||
this.localDispose();
|
||||
|
||||
if (!this._isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var model = this._editor.getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DocumentSymbolProviderRegistry.has(model)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scheduler = new RunOnceScheduler(() => {
|
||||
if (this._currentOutlinePromise) {
|
||||
this._currentOutlinePromise.cancel();
|
||||
}
|
||||
|
||||
this._currentOutlinePromise = getDocumentSymbols(model);
|
||||
|
||||
this._currentOutlinePromise.then((result) => {
|
||||
this.renderOutlines(result.entries);
|
||||
}, (error) => {
|
||||
onUnexpectedError(error);
|
||||
});
|
||||
}, 250);
|
||||
this._localToDispose.push(scheduler);
|
||||
this._localToDispose.push(this._editor.onDidChangeModelContent(() => {
|
||||
|
||||
// Synchronously move markers
|
||||
this._editor.changeViewZones((viewAccessor) => {
|
||||
this._markers.forEach((marker) => {
|
||||
marker.update(viewAccessor);
|
||||
});
|
||||
});
|
||||
|
||||
scheduler.schedule();
|
||||
}));
|
||||
this._localToDispose.push({
|
||||
dispose: () => {
|
||||
if (this._markers.length > 0) {
|
||||
var helper = new OutlineMarkerHelper();
|
||||
this._editor.changeViewZones((accessor) => {
|
||||
this._markers.forEach((marker) => marker.dispose(helper, accessor));
|
||||
this._markers = [];
|
||||
});
|
||||
this._editor.changeDecorations((accessor) => {
|
||||
helper.commit(accessor);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.schedule();
|
||||
}
|
||||
|
||||
private renderOutlines(entries: SymbolInformation[]): void {
|
||||
var centeredRange = this._editor.getCenteredRangeInViewport();
|
||||
var oldMarkersCount = this._markers.length;
|
||||
this._editor.changeDecorations((decorationsAccessor) => {
|
||||
var helper = new OutlineMarkerHelper();
|
||||
this._editor.changeViewZones((viewzonesAccessor) => {
|
||||
this._markers.forEach((marker) => marker.dispose(helper, viewzonesAccessor));
|
||||
this._markers = [];
|
||||
|
||||
this.renderOutlinesRecursive(entries, helper, viewzonesAccessor);
|
||||
});
|
||||
helper.commit(decorationsAccessor);
|
||||
});
|
||||
var newMarkersCount = this._markers.length;
|
||||
if (Math.abs(oldMarkersCount - newMarkersCount) > 1) {
|
||||
// Reveal only if the delta is more than 1 marker
|
||||
this._editor.revealRangeInCenter(centeredRange);
|
||||
}
|
||||
}
|
||||
|
||||
private renderOutlinesRecursive(entries: SymbolInformation[], helper:OutlineMarkerHelper, viewZoneChangeAccessor:IViewZoneChangeAccessor): void {
|
||||
if (entries) {
|
||||
entries.forEach((outline) => {
|
||||
if (outline.kind === SymbolKind.Class || outline.kind === SymbolKind.Method || outline.kind === SymbolKind.Function) {
|
||||
var range = Range.lift(outline.location.range);
|
||||
if (!this.alreadyHasMarkerAtRange(range)) {
|
||||
var marker = new OutlineMarker(range, outline.kind, this._editor, helper, viewZoneChangeAccessor);
|
||||
this._markers.push(marker);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private alreadyHasMarkerAtRange(range: editorCommon.IRange): boolean {
|
||||
for (var i = 0; i < this._markers.length; ++i) {
|
||||
if (this._markers[i].getLine() === range.startLineNumber-1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
EditorBrowserRegistry.registerEditorContribution(OutlineMarkerContribution);
|
||||
@@ -1,208 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {IEditorService} from 'vs/platform/editor/common/editor';
|
||||
import {EditOperation} from 'vs/editor/common/core/editOperation';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {Selection} from 'vs/editor/common/core/selection';
|
||||
import {IIdentifiedSingleEditOperation, IModel, IRange} from 'vs/editor/common/editorCommon';
|
||||
import {IResourceEdit} from 'vs/editor/common/modes';
|
||||
|
||||
class EditTask {
|
||||
private _initialSelections: Selection[];
|
||||
private _endCursorSelection: Selection;
|
||||
private _model: IModel;
|
||||
private _edits: IIdentifiedSingleEditOperation[];
|
||||
|
||||
constructor(model: IModel) {
|
||||
this._endCursorSelection = null;
|
||||
this._model = model;
|
||||
this._edits = [];
|
||||
}
|
||||
|
||||
public addEdit(edit: IResourceEdit): void {
|
||||
var range: IRange;
|
||||
if (!edit.range) {
|
||||
range = this._model.getFullModelRange();
|
||||
} else {
|
||||
range = edit.range;
|
||||
}
|
||||
this._edits.push(EditOperation.replace(Range.lift(range), edit.newText));
|
||||
}
|
||||
|
||||
public apply(): void {
|
||||
if (this._edits.length === 0) {
|
||||
return;
|
||||
}
|
||||
this._edits.sort(EditTask._editCompare);
|
||||
|
||||
this._initialSelections = this._getInitialSelections();
|
||||
this._model.pushEditOperations(this._initialSelections, this._edits, (edits) => this._getEndCursorSelections(edits));
|
||||
}
|
||||
|
||||
protected _getInitialSelections(): Selection[] {
|
||||
var firstRange = this._edits[0].range;
|
||||
var initialSelection = new Selection(
|
||||
firstRange.startLineNumber,
|
||||
firstRange.startColumn,
|
||||
firstRange.endLineNumber,
|
||||
firstRange.endColumn
|
||||
);
|
||||
return [initialSelection];
|
||||
}
|
||||
|
||||
private _getEndCursorSelections(inverseEditOperations:IIdentifiedSingleEditOperation[]): Selection[] {
|
||||
var relevantEditIndex = 0;
|
||||
for (var i = 0; i < inverseEditOperations.length; i++) {
|
||||
var editRange = inverseEditOperations[i].range;
|
||||
for (var j = 0; j < this._initialSelections.length; j++) {
|
||||
var selectionRange = this._initialSelections[j];
|
||||
if (Range.areIntersectingOrTouching(editRange, selectionRange)) {
|
||||
relevantEditIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var srcRange = inverseEditOperations[relevantEditIndex].range;
|
||||
this._endCursorSelection = new Selection(
|
||||
srcRange.endLineNumber,
|
||||
srcRange.endColumn,
|
||||
srcRange.endLineNumber,
|
||||
srcRange.endColumn
|
||||
);
|
||||
return [this._endCursorSelection];
|
||||
}
|
||||
|
||||
public getEndCursorSelection(): Selection {
|
||||
return this._endCursorSelection;
|
||||
}
|
||||
|
||||
private static _editCompare(a: IIdentifiedSingleEditOperation, b: IIdentifiedSingleEditOperation): number {
|
||||
return Range.compareRangesUsingStarts(a.range, b.range);
|
||||
}
|
||||
}
|
||||
|
||||
class SourceModelEditTask extends EditTask {
|
||||
|
||||
private _knownInitialSelections:Selection[];
|
||||
|
||||
constructor(model: IModel, initialSelections:Selection[]) {
|
||||
super(model);
|
||||
this._knownInitialSelections = initialSelections;
|
||||
}
|
||||
|
||||
protected _getInitialSelections(): Selection[] {
|
||||
return this._knownInitialSelections;
|
||||
}
|
||||
}
|
||||
|
||||
export default class RenameModel {
|
||||
|
||||
private _editorService: IEditorService;
|
||||
private _numberOfResourcesToModify: number = 0;
|
||||
private _numberOfChanges: number = 0;
|
||||
private _edits: collections.IStringDictionary<IResourceEdit[]> = Object.create(null);
|
||||
private _rejectReasons: string[];
|
||||
private _tasks: EditTask[];
|
||||
private _sourceModel: URI;
|
||||
private _sourceSelections: Selection[];
|
||||
private _sourceModelTask: SourceModelEditTask;
|
||||
|
||||
constructor(editorService: IEditorService, sourceModel: URI, sourceSelections: Selection[], editsOrReject: string|IResourceEdit[]) {
|
||||
this._editorService = editorService;
|
||||
this._sourceModel = sourceModel;
|
||||
this._sourceSelections = sourceSelections;
|
||||
this._sourceModelTask = null;
|
||||
|
||||
if (typeof editsOrReject === 'string') {
|
||||
this.reject(editsOrReject);
|
||||
} else {
|
||||
editsOrReject.forEach(this._addEdit, this);
|
||||
}
|
||||
}
|
||||
|
||||
public reject(value: string): void {
|
||||
if (!this._rejectReasons) {
|
||||
this._rejectReasons = [];
|
||||
}
|
||||
this._rejectReasons.push(value);
|
||||
}
|
||||
|
||||
public isRejected(): boolean {
|
||||
return !arrays.isFalsyOrEmpty(this._rejectReasons);
|
||||
}
|
||||
|
||||
public rejectReasons(): string[]{
|
||||
return this._rejectReasons;
|
||||
}
|
||||
|
||||
public resourcesCount(): number {
|
||||
return this._numberOfResourcesToModify;
|
||||
}
|
||||
|
||||
public changeCount(): number {
|
||||
return this._numberOfChanges;
|
||||
}
|
||||
|
||||
private _addEdit(edit: IResourceEdit): void {
|
||||
var array = this._edits[edit.resource.toString()];
|
||||
if (!array) {
|
||||
this._edits[edit.resource.toString()] = array = [];
|
||||
this._numberOfResourcesToModify += 1;
|
||||
}
|
||||
this._numberOfChanges += 1;
|
||||
array.push(edit);
|
||||
}
|
||||
|
||||
public prepare(): TPromise<RenameModel> {
|
||||
|
||||
if (this._tasks) {
|
||||
throw new Error('illegal state - already prepared');
|
||||
}
|
||||
|
||||
this._tasks = [];
|
||||
var promises: TPromise<any>[] = [];
|
||||
|
||||
collections.forEach(this._edits, entry => {
|
||||
var promise = this._editorService.resolveEditorModel({ resource: URI.parse(entry.key) }).then(model => {
|
||||
if (!model || !model.textEditorModel) {
|
||||
this.reject(nls.localize('cannotLoadFile', "Cannot load file {0}", entry.key));
|
||||
} else {
|
||||
var textEditorModel = <IModel>model.textEditorModel,
|
||||
task: EditTask;
|
||||
|
||||
if (textEditorModel.uri.toString() === this._sourceModel.toString()) {
|
||||
this._sourceModelTask = new SourceModelEditTask(textEditorModel, this._sourceSelections);
|
||||
task = this._sourceModelTask;
|
||||
} else {
|
||||
task = new EditTask(textEditorModel);
|
||||
}
|
||||
|
||||
entry.value.forEach(edit => task.addEdit(edit));
|
||||
this._tasks.push(task);
|
||||
}
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
|
||||
return TPromise.join(promises).then(_ => this);
|
||||
}
|
||||
|
||||
public apply(): Selection {
|
||||
this._tasks.forEach(task => task.apply());
|
||||
var r: Selection = null;
|
||||
if (this._sourceModelTask) {
|
||||
r = this._sourceModelTask.getEndCursorSelection();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,11 @@ export class CompletionModel {
|
||||
item.highlights = filter(word, suggestion.label);
|
||||
match = item.highlights !== null;
|
||||
|
||||
// no match on label -> check on codeSnippet
|
||||
if (!match && suggestion.codeSnippet !== suggestion.label) {
|
||||
match = !isFalsyOrEmpty((filter(word, suggestion.codeSnippet.replace(/{{.+?}}/g, '')))); // filters {{text}}-snippet syntax
|
||||
}
|
||||
|
||||
// no match on label nor codeSnippet -> check on filterText
|
||||
if(!match && typeof suggestion.filterText === 'string') {
|
||||
match = !isFalsyOrEmpty(filter(word, suggestion.filterText));
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import 'vs/css!./suggest';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as timer from 'vs/base/common/timer';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -19,7 +18,6 @@ import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingContextKey, IKeybindingService } from 'vs/platform/keybinding/common/keybindingService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IConfigurationChangedEvent } from 'vs/editor/common/editorCommon';
|
||||
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { Context as SuggestContext } from '../common/suggest';
|
||||
@@ -179,15 +177,6 @@ function computeScore(suggestion: string, currentWord: string, currentWordLowerC
|
||||
return score;
|
||||
}
|
||||
|
||||
interface ITelemetryData {
|
||||
suggestionCount?: number;
|
||||
suggestedIndex?: number;
|
||||
selectedIndex?: number;
|
||||
hintLength?: number;
|
||||
wasCancelled?: boolean;
|
||||
wasAutomaticallyTriggered?: boolean;
|
||||
}
|
||||
|
||||
enum State {
|
||||
Hidden,
|
||||
Loading,
|
||||
@@ -321,10 +310,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
private focusedItem: CompletionItem;
|
||||
private completionModel: CompletionModel;
|
||||
|
||||
private telemetryData: ITelemetryData;
|
||||
private telemetryService: ITelemetryService;
|
||||
private telemetryTimer: timer.ITimerEvent;
|
||||
|
||||
private element: HTMLElement;
|
||||
private messageElement: HTMLElement;
|
||||
private listElement: HTMLElement;
|
||||
@@ -344,15 +329,11 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
private editor: ICodeEditor,
|
||||
private model: SuggestModel,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
this.isAuto = false;
|
||||
this.focusedItem = null;
|
||||
|
||||
this.telemetryData = null;
|
||||
this.telemetryService = telemetryService;
|
||||
|
||||
this.element = $('.editor-widget.suggest-widget.monaco-editor-background');
|
||||
this.element.style.width = SuggestWidget.WIDTH + 'px';
|
||||
this.element.style.top = '0';
|
||||
@@ -426,11 +407,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
this.telemetryData.selectedIndex = 0;
|
||||
this.telemetryData.wasCancelled = false;
|
||||
this.telemetryData.selectedIndex = e.indexes[0];
|
||||
this.submitTelemetryData();
|
||||
|
||||
const item = e.elements[0];
|
||||
const container = item.container;
|
||||
const overwriteBefore = (typeof item.suggestion.overwriteBefore === 'undefined') ? container.currentWord.length : item.suggestion.overwriteBefore;
|
||||
@@ -570,7 +546,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
this.telemetryTimer = this.telemetryService.timedPublicLog('suggestWidgetLoadingTime');
|
||||
this.isAuto = !!e.auto;
|
||||
|
||||
if (!this.isAuto) {
|
||||
@@ -579,12 +554,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
this.setState(State.Loading);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
if (!e.retrigger) {
|
||||
this.telemetryData = {
|
||||
wasAutomaticallyTriggered: e.characterTriggered
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private onDidSuggest(e: ISuggestEvent): void {
|
||||
@@ -629,23 +598,12 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
}
|
||||
});
|
||||
|
||||
this.telemetryData = this.telemetryData || {};
|
||||
this.telemetryData.suggestionCount = this.completionModel.items.length;
|
||||
this.telemetryData.suggestedIndex = bestSuggestionIndex;
|
||||
this.telemetryData.hintLength = currentWord.length;
|
||||
|
||||
this.list.splice(0, this.list.length, ...this.completionModel.items);
|
||||
this.list.setFocus(bestSuggestionIndex);
|
||||
this.list.reveal(bestSuggestionIndex, 0);
|
||||
|
||||
this.setState(State.Open);
|
||||
}
|
||||
|
||||
if (this.telemetryTimer) {
|
||||
this.telemetryTimer.data = { reason: isEmpty ? 'empty' : 'results' };
|
||||
this.telemetryTimer.stop();
|
||||
this.telemetryTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private onDidCancel(e: ICancelEvent) {
|
||||
@@ -656,18 +614,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
|
||||
if (!e.retrigger) {
|
||||
this.setState(State.Hidden);
|
||||
|
||||
if (this.telemetryData) {
|
||||
this.telemetryData.selectedIndex = -1;
|
||||
this.telemetryData.wasCancelled = true;
|
||||
this.submitTelemetryData();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.telemetryTimer) {
|
||||
this.telemetryTimer.data = { reason: 'cancel' };
|
||||
this.telemetryTimer.stop();
|
||||
this.telemetryTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,11 +758,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
return SuggestWidget.ID;
|
||||
}
|
||||
|
||||
private submitTelemetryData(): void {
|
||||
this.telemetryService.publicLog('suggestWidget', this.telemetryData);
|
||||
this.telemetryData = null;
|
||||
}
|
||||
|
||||
private updateWidgetHeight(): number {
|
||||
let height = 0;
|
||||
|
||||
@@ -853,9 +794,6 @@ export class SuggestWidget implements IContentWidget, IDisposable {
|
||||
this.suggestionSupportsAutoAccept = null;
|
||||
this.currentSuggestionDetails = null;
|
||||
this.focusedItem = null;
|
||||
this.telemetryData = null;
|
||||
this.telemetryService = null;
|
||||
this.telemetryTimer = null;
|
||||
this.element = null;
|
||||
this.messageElement = null;
|
||||
this.listElement = null;
|
||||
|
||||
@@ -10,7 +10,9 @@ import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {EditorAction} from 'vs/editor/common/editorAction';
|
||||
import {Behaviour} from 'vs/editor/common/editorActionEnablement';
|
||||
import {ICommonCodeEditor, IEditorActionDescriptorData} from 'vs/editor/common/editorCommon';
|
||||
import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {TabFocus} from 'vs/editor/common/config/commonEditorConfig';
|
||||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
|
||||
export class ToggleTabFocusModeAction extends EditorAction {
|
||||
|
||||
@@ -22,11 +24,8 @@ export class ToggleTabFocusModeAction extends EditorAction {
|
||||
|
||||
public run():TPromise<boolean> {
|
||||
|
||||
if(this.editor.getConfiguration().tabFocusMode) {
|
||||
this.editor.updateOptions({tabFocusMode: false});
|
||||
} else {
|
||||
this.editor.updateOptions({tabFocusMode: true});
|
||||
}
|
||||
let oldValue = TabFocus.getTabFocusMode();
|
||||
TabFocus.setTabFocusMode(!oldValue);
|
||||
|
||||
return TPromise.as(true);
|
||||
}
|
||||
@@ -34,7 +33,14 @@ export class ToggleTabFocusModeAction extends EditorAction {
|
||||
|
||||
// register actions
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ToggleTabFocusModeAction, ToggleTabFocusModeAction.ID, nls.localize('toggle.tabfocusmode', "Toggle Use of Tab Key for Setting Focus"), {
|
||||
context: ContextKey.EditorTextFocus,
|
||||
primary: null,
|
||||
context: null
|
||||
}, 'Toggle Use of Tab Key for Setting Focus'));
|
||||
|
||||
KeybindingsRegistry.registerCommandRule({
|
||||
id: ToggleTabFocusModeAction.ID,
|
||||
weight: KeybindingsRegistry.WEIGHT.editorContrib(),
|
||||
when: null,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_M,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_M }
|
||||
}, 'Toggle Use of Tab Key for Setting Focus'));
|
||||
});
|
||||
|
||||
@@ -1197,6 +1197,115 @@ suite('Editor Controller - Regression tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('bug #2938 (1): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
mode: new OnEnterMode(IndentAction.Indent),
|
||||
}, (model, cursor) => {
|
||||
moveTo(cursor, 4, 2, false);
|
||||
cursorEqual(cursor, 4, 2, 4, 2);
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(4), '\t\t\t');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('bug #2938 (2): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
' ',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
mode: new OnEnterMode(IndentAction.Indent),
|
||||
}, (model, cursor) => {
|
||||
moveTo(cursor, 4, 1, false);
|
||||
cursorEqual(cursor, 4, 1, 4, 1);
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(4), '\t\t\t');
|
||||
});
|
||||
});
|
||||
|
||||
test('bug #2938 (3): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t\t\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
mode: new OnEnterMode(IndentAction.Indent),
|
||||
}, (model, cursor) => {
|
||||
moveTo(cursor, 4, 3, false);
|
||||
cursorEqual(cursor, 4, 3, 4, 3);
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(4), '\t\t\t\t');
|
||||
});
|
||||
});
|
||||
|
||||
test('bug #2938 (4): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t\t\t\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
mode: new OnEnterMode(IndentAction.Indent),
|
||||
}, (model, cursor) => {
|
||||
moveTo(cursor, 4, 4, false);
|
||||
cursorEqual(cursor, 4, 4, 4, 4);
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(4), '\t\t\t\t\t');
|
||||
});
|
||||
});
|
||||
|
||||
test('Bug 18276:[editor] Indentation broken when selection is empty', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
|
||||
Vendored
+7
-15
@@ -1181,13 +1181,6 @@ declare module monaco.editor {
|
||||
* Defaults to '.'.
|
||||
*/
|
||||
wordWrapBreakObtrusiveCharacters?: string;
|
||||
/**
|
||||
* Control what pressing Tab does.
|
||||
* If it is false, pressing Tab or Shift-Tab will be handled by the editor.
|
||||
* If it is true, pressing Tab or Shift-Tab will move the browser focus.
|
||||
* Defaults to false.
|
||||
*/
|
||||
tabFocusMode?: boolean;
|
||||
/**
|
||||
* Performance guard: Stop rendering a line after x characters.
|
||||
* Defaults to 10000 if wrappingColumn is -1. Defaults to -1 if wrappingColumn is >= 0.
|
||||
@@ -1253,11 +1246,6 @@ declare module monaco.editor {
|
||||
* Defaults to true.
|
||||
*/
|
||||
selectionHighlight?: boolean;
|
||||
/**
|
||||
* Show lines before classes and methods (based on outline info).
|
||||
* Defaults to false.
|
||||
*/
|
||||
outlineMarkers?: boolean;
|
||||
/**
|
||||
* Show reference infos (a.k.a. code lenses) for modes that support it
|
||||
* Defaults to true.
|
||||
@@ -1416,7 +1404,6 @@ declare module monaco.editor {
|
||||
suggestOnTriggerCharacters: boolean;
|
||||
acceptSuggestionOnEnter: boolean;
|
||||
selectionHighlight: boolean;
|
||||
outlineMarkers: boolean;
|
||||
referenceInfos: boolean;
|
||||
folding: boolean;
|
||||
}
|
||||
@@ -2744,6 +2731,11 @@ declare module monaco.editor {
|
||||
*/
|
||||
export const KEYBINDING_CONTEXT_EDITOR_FOCUS: string;
|
||||
|
||||
/**
|
||||
* A context key that is set when the editor's text is readonly.
|
||||
*/
|
||||
export const KEYBINDING_CONTEXT_EDITOR_READONLY: string;
|
||||
|
||||
/**
|
||||
* A context key that is set when the editor has multiple selections (multiple cursors).
|
||||
*/
|
||||
@@ -3909,8 +3901,8 @@ declare module monaco.languages {
|
||||
}
|
||||
|
||||
/**
|
||||
* The language configuration interfaces defines the contract between extensions
|
||||
* and various editor features, like automatic bracket insertion, automatic indentation etc.
|
||||
* The language configuration interface defines the contract between extensions and
|
||||
* various editor features, like automatic bracket insertion, automatic indentation etc.
|
||||
*/
|
||||
export interface LanguageConfiguration {
|
||||
/**
|
||||
|
||||
@@ -11,64 +11,43 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import {IAction} from 'vs/base/common/actions';
|
||||
import {values} from 'vs/base/common/collections';
|
||||
import {KbExpr, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {MenuId, CommandAction, MenuItemAction, IMenu, IMenuItem, IMenuService} from 'vs/platform/actions/common/actions';
|
||||
import {MenuId, ICommandAction, MenuItemAction, IMenu, IMenuItem, IMenuService} from 'vs/platform/actions/common/actions';
|
||||
import {IExtensionService} from 'vs/platform/extensions/common/extensions';
|
||||
import {ResourceContextKey} from 'vs/platform/actions/common/resourceContextKey';
|
||||
|
||||
|
||||
export interface IDeclaredMenuItem {
|
||||
command: string;
|
||||
alt?: string;
|
||||
when?: string;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export interface IMenuRegistry {
|
||||
addCommand(userCommand: CommandAction): boolean;
|
||||
hasCommand(id: string): boolean;
|
||||
addMenuItems(location: MenuId, items: IDeclaredMenuItem[]): void;
|
||||
addCommand(userCommand: ICommandAction): boolean;
|
||||
getCommand(id: string): ICommandAction;
|
||||
appendMenuItem(menu: MenuId, item: IMenuItem): void;
|
||||
}
|
||||
|
||||
const _registry = new class {
|
||||
|
||||
commands: { [id: string]: CommandAction } = Object.create(null);
|
||||
commands: { [id: string]: ICommandAction } = Object.create(null);
|
||||
|
||||
menuItems: { [loc: number]: IDeclaredMenuItem[] } = Object.create(null);
|
||||
menuItems: { [loc: number]: IMenuItem[] } = Object.create(null);
|
||||
|
||||
addCommand(command: CommandAction): boolean {
|
||||
addCommand(command: ICommandAction): boolean {
|
||||
const old = this.commands[command.id];
|
||||
this.commands[command.id] = command;
|
||||
return old !== void 0;
|
||||
}
|
||||
|
||||
hasCommand(id: string): boolean {
|
||||
return this.commands[id] !== void 0;
|
||||
getCommand(id: string): ICommandAction {
|
||||
return this.commands[id];
|
||||
}
|
||||
|
||||
addMenuItems(loc: MenuId, items: IDeclaredMenuItem[]): void {
|
||||
appendMenuItem(loc: MenuId, items: IMenuItem): void {
|
||||
let array = this.menuItems[loc];
|
||||
if (!array) {
|
||||
this.menuItems[loc] = items;
|
||||
this.menuItems[loc] = [items];
|
||||
} else {
|
||||
array.push(...items);
|
||||
array.push(items);
|
||||
}
|
||||
}
|
||||
getMenuItems(loc: MenuId): IMenuItem[] {
|
||||
const result: IMenuItem[] = [];
|
||||
const menuItems = this.menuItems[loc];
|
||||
if (menuItems) {
|
||||
for (let item of menuItems) {
|
||||
const command = this.commands[item.command];
|
||||
if (!command) {
|
||||
// warn?
|
||||
continue;
|
||||
}
|
||||
const when = KbExpr.deserialize(item.when);
|
||||
const alt = this.commands[item.alt];
|
||||
result.push({ when, command, alt, group: item.group });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return this.menuItems[loc] || [];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,7 +67,7 @@ export class MenuService implements IMenuService {
|
||||
return new Menu(id, keybindingService, this._extensionService);
|
||||
}
|
||||
|
||||
getCommandActions(): CommandAction[] {
|
||||
getCommandActions(): ICommandAction[] {
|
||||
return values(_registry.commands);
|
||||
}
|
||||
}
|
||||
@@ -181,14 +160,15 @@ class Menu implements IMenu {
|
||||
}
|
||||
|
||||
private static _compareMenuItems(a: IMenuItem, b: IMenuItem): number {
|
||||
let ret: number;
|
||||
if (a.group && b.group) {
|
||||
ret = Menu._compareGroupId(a.group, b.group);
|
||||
if (a.group === b.group) {
|
||||
return a.command.title.localeCompare(b.command.title);
|
||||
} else if (!a.group) {
|
||||
return 1;
|
||||
} else if (!b.group) {
|
||||
return -1;
|
||||
} else {
|
||||
return Menu._compareGroupId(a.group, b.group);
|
||||
}
|
||||
if (!ret) {
|
||||
ret = a.command.title.localeCompare(b.command.title);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static _compareGroupId(a: string, b: string): number {
|
||||
|
||||
@@ -11,13 +11,21 @@ import {IdGenerator} from 'vs/base/common/idGenerator';
|
||||
import {IJSONSchema} from 'vs/base/common/jsonSchema';
|
||||
import {forEach} from 'vs/base/common/collections';
|
||||
import {IExtensionPointUser, IExtensionMessageCollector, ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry';
|
||||
import {IDeclaredMenuItem, MenuRegistry} from './menuService';
|
||||
import {MenuRegistry} from './menuService';
|
||||
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {MenuId} from 'vs/platform/actions/common/actions';
|
||||
|
||||
namespace schema {
|
||||
|
||||
// --- menus contribution point
|
||||
|
||||
export interface IUserFriendlyMenuItem {
|
||||
command: string;
|
||||
alt?: string;
|
||||
when?: string;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export function parseMenuId(value: string): MenuId {
|
||||
switch (value) {
|
||||
case 'editor/title': return MenuId.EditorTitle;
|
||||
@@ -26,7 +34,7 @@ namespace schema {
|
||||
}
|
||||
}
|
||||
|
||||
export function isValidMenuItems(menu: IDeclaredMenuItem[], collector: IExtensionMessageCollector): boolean {
|
||||
export function isValidMenuItems(menu: IUserFriendlyMenuItem[], collector: IExtensionMessageCollector): boolean {
|
||||
if (!Array.isArray(menu)) {
|
||||
collector.error(localize('requirearry', "menu items must be an arry"));
|
||||
return false;
|
||||
@@ -237,7 +245,7 @@ ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.I
|
||||
});
|
||||
|
||||
|
||||
ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IDeclaredMenuItem[] }>('menus', schema.menusContribtion).setHandler(extensions => {
|
||||
ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyMenuItem[] }>('menus', schema.menusContribtion).setHandler(extensions => {
|
||||
for (let extension of extensions) {
|
||||
const {value, collector} = extension;
|
||||
|
||||
@@ -253,10 +261,13 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IDeclaredMenuItem[] }
|
||||
}
|
||||
|
||||
for (let item of entry.value) {
|
||||
if (!MenuRegistry.hasCommand(item.command)) {
|
||||
let command = MenuRegistry.getCommand(item.command);
|
||||
let alt = item.alt && MenuRegistry.getCommand(item.alt);
|
||||
|
||||
if (!command) {
|
||||
collector.warn(localize('missing.command', "Menu item references a command `{0}` which is not defined in the 'commands' section.", item.command));
|
||||
}
|
||||
if (item.alt && !MenuRegistry.hasCommand(item.alt)) {
|
||||
if (item.alt && !alt) {
|
||||
collector.warn(localize('missing.altCommand', "Menu item references an alt-command `{0}` which is not defined in the 'commands' section.", item.alt));
|
||||
}
|
||||
if (item.command === item.alt) {
|
||||
@@ -266,9 +277,14 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IDeclaredMenuItem[] }
|
||||
if (item.alt && menu !== MenuId.EditorTitle && item.group !== 'navigation') {
|
||||
collector.info(localize('nosupport.altCommand', "Sorry, but currently only the 'navigation' group of the 'editor/title' menu supports alt-commands"));
|
||||
}
|
||||
}
|
||||
|
||||
MenuRegistry.addMenuItems(menu, entry.value);
|
||||
MenuRegistry.appendMenuItem(menu, {
|
||||
command,
|
||||
alt,
|
||||
group: item.group || undefined,
|
||||
when: KbExpr.deserialize(item.when)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Actions = require('vs/base/common/actions');
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import Assert = require('vs/base/common/assert');
|
||||
import Descriptors = require('vs/platform/instantiation/common/descriptors');
|
||||
import Instantiation = require('vs/platform/instantiation/common/instantiation');
|
||||
import {KbExpr, IKeybindings, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
@@ -15,7 +14,7 @@ import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {createDecorator} from 'vs/platform/instantiation/common/instantiation';
|
||||
import Event from 'vs/base/common/event';
|
||||
|
||||
export interface CommandAction {
|
||||
export interface ICommandAction {
|
||||
id: string;
|
||||
title: string;
|
||||
category?: string;
|
||||
@@ -28,8 +27,8 @@ export interface IMenu extends IDisposable {
|
||||
}
|
||||
|
||||
export interface IMenuItem {
|
||||
command: CommandAction;
|
||||
alt?: CommandAction;
|
||||
command: ICommandAction;
|
||||
alt?: ICommandAction;
|
||||
when?: KbExpr;
|
||||
group?: string;
|
||||
}
|
||||
@@ -48,7 +47,7 @@ export interface IMenuService {
|
||||
|
||||
createMenu(id: MenuId, scopedKeybindingService: IKeybindingService): IMenu;
|
||||
|
||||
getCommandActions(): CommandAction[];
|
||||
getCommandActions(): ICommandAction[];
|
||||
}
|
||||
|
||||
export class MenuItemAction extends Actions.Action {
|
||||
@@ -168,7 +167,8 @@ export class DeferredAction extends Actions.Action {
|
||||
private _cachedAction: Actions.IAction;
|
||||
private _emitterUnbind: IDisposable;
|
||||
|
||||
constructor(private _instantiationService: Instantiation.IInstantiationService, private _descriptor: Descriptors.AsyncDescriptor0<Actions.Action>,
|
||||
constructor(private _instantiationService: Instantiation.IInstantiationService,
|
||||
private _descriptor: Descriptors.AsyncDescriptor0<Actions.Action>,
|
||||
id: string, label = '', cssClass = '', enabled = true) {
|
||||
|
||||
super(id, label, cssClass, enabled);
|
||||
@@ -265,13 +265,15 @@ export class DeferredAction extends Actions.Action {
|
||||
let promise = WinJS.TPromise.as(undefined);
|
||||
return promise.then(() => {
|
||||
return this._instantiationService.createInstance(this._descriptor);
|
||||
}).then(action => {
|
||||
if (action instanceof Actions.Action) {
|
||||
this._cachedAction = action;
|
||||
// Pipe events from the instantated action through this deferred action
|
||||
this._emitterUnbind = action.onDidChange(e => this._onDidChange.fire(e));
|
||||
|
||||
}).then((action) => {
|
||||
Assert.ok(action instanceof Actions.Action, 'Action must be an instanceof Base Action');
|
||||
this._cachedAction = action;
|
||||
|
||||
// Pipe events from the instantated action through this deferred action
|
||||
this._emitterUnbind = this.addEmitter2(<Actions.Action>this._cachedAction);
|
||||
} else {
|
||||
throw new Error('Action must be an instanceof Base Action');
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
@@ -93,17 +93,6 @@ export class ExtensionManagementService implements IExtensionManagementService {
|
||||
this.extensionsPath = environmentService.extensionsPath;
|
||||
this.obsoletePath = path.join(this.extensionsPath, '.obsolete');
|
||||
this.obsoleteFileLimiter = new Limiter(1);
|
||||
|
||||
// this.disposables = [
|
||||
// this.onDidInstallExtension(({ extension, isUpdate, error }) => telemetryService.publicLog(
|
||||
// isUpdate ? 'extensionGallery2:update' : 'extensionGallery2:install',
|
||||
// assign(getTelemetryData(extension), { success: !error })
|
||||
// )),
|
||||
// this.onDidUninstallExtension(extension => telemetryService.publicLog(
|
||||
// 'extensionGallery2:uninstall',
|
||||
// assign(getTelemetryData(extension), { success: true })
|
||||
// ))
|
||||
// ];
|
||||
}
|
||||
|
||||
install(extension: IGalleryExtension): TPromise<void>;
|
||||
|
||||
@@ -181,7 +181,7 @@ export class ExtHostAPIImplementation {
|
||||
return;
|
||||
}
|
||||
|
||||
activeTextEditor.edit((edit: vscode.TextEditorEdit) => {
|
||||
return activeTextEditor.edit((edit: vscode.TextEditorEdit) => {
|
||||
args.unshift(activeTextEditor, edit);
|
||||
callback.apply(thisArg, args);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import labels = require('vs/base/common/labels');
|
||||
import {Registry} from 'vs/platform/platform';
|
||||
import {Action} from 'vs/base/common/actions';
|
||||
import strings = require('vs/base/common/strings');
|
||||
import {EditorOptions} from 'vs/workbench/common/editor';
|
||||
import {IWorkbenchActionRegistry, Extensions} from 'vs/workbench/common/actionRegistry';
|
||||
import {StringEditorInput} from 'vs/workbench/common/editor/stringEditorInput';
|
||||
import {getDefaultValuesContent} from 'vs/platform/configuration/common/model';
|
||||
@@ -65,8 +66,8 @@ export class BaseTwoEditorsAction extends Action {
|
||||
return this.createIfNotExists(editableResource, defaultEditableContents).then(() => {
|
||||
return this.editorService.createInput({ resource: editableResource }).then((typedRightHandEditableInput) => {
|
||||
const editors = [
|
||||
{ input: leftHandDefaultInput, position: Position.LEFT },
|
||||
{ input: typedRightHandEditableInput, position: Position.CENTER }
|
||||
{ input: leftHandDefaultInput, position: Position.LEFT, options: { pinned: true } },
|
||||
{ input: typedRightHandEditableInput, position: Position.CENTER, options: { pinned: true } }
|
||||
];
|
||||
|
||||
return this.editorService.openEditors(editors).then(() => {
|
||||
@@ -139,7 +140,7 @@ export class OpenGlobalSettingsAction extends BaseOpenSettingsAction {
|
||||
let editorCount = this.editorService.getVisibleEditors().length;
|
||||
|
||||
return this.editorService.createInput({ resource: this.contextService.toResource('.vscode/settings.json') }).then((typedInput) => {
|
||||
return this.editorService.openEditor(typedInput, null, editorCount === 2 ? Position.RIGHT : editorCount === 1 ? Position.CENTER : void 0);
|
||||
return this.editorService.openEditor(typedInput, EditorOptions.create({ pinned: true }), editorCount === 2 ? Position.RIGHT : editorCount === 1 ? Position.CENTER : void 0);
|
||||
});
|
||||
})
|
||||
]
|
||||
|
||||
@@ -30,6 +30,39 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .action-bar-select {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
margin-top: 8px; /* Center the select box */
|
||||
}
|
||||
|
||||
.monaco-workbench.windows .action-bar-select {
|
||||
margin-top: 7px; /* Center the select box */
|
||||
}
|
||||
|
||||
#monaco-workbench-drop-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 3000000;
|
||||
}
|
||||
|
||||
.vs #monaco-workbench-drop-overlay {
|
||||
background-color: rgba(51,153,255, 0.18);
|
||||
}
|
||||
|
||||
.vs-dark #monaco-workbench-drop-overlay {
|
||||
background-color: rgba(83, 89, 93, 0.5);
|
||||
}
|
||||
|
||||
.hc-black #monaco-workbench-drop-overlay {
|
||||
background: none !important;
|
||||
outline: 2px dashed #f38518;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* ---------- Light Theme ---------- */
|
||||
|
||||
.vs .monaco-workbench { background-color: #F3F3F3; }
|
||||
@@ -44,6 +77,11 @@
|
||||
background-color: #E1E1E1;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .action-bar-select {
|
||||
background-color: white;
|
||||
border-color: #CECECE;
|
||||
}
|
||||
|
||||
/* ---------- Dark Theme ---------- */
|
||||
|
||||
.vs-dark .monaco-workbench {
|
||||
@@ -74,6 +112,12 @@
|
||||
.vs-dark .monaco-workbench .stacked-view .action-label { color: inherit; }
|
||||
.vs-dark .monaco-workbench .stacked-view .action-label:hover { color: #3399FF; }
|
||||
|
||||
.vs-dark .monaco-workbench .action-bar-select {
|
||||
background-color: #3C3C3C;
|
||||
border-color: #3C3C3C;
|
||||
color: rgb(204, 204, 204);
|
||||
}
|
||||
|
||||
/* ---------- HC Theme ---------- */
|
||||
|
||||
.hc-black .monaco-workbench { color: #FFF; background-color: #000; }
|
||||
@@ -92,4 +136,10 @@
|
||||
|
||||
.hc-black .monaco-workbench .monaco-action-bar .action-item.disabled .action-label.disabled {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .action-bar-select {
|
||||
background-color: #3C3C3C;
|
||||
border-color: #3C3C3C;
|
||||
color: white;
|
||||
}
|
||||
@@ -11,14 +11,13 @@ import {Builder, $} from 'vs/base/browser/builder';
|
||||
import {DelayedDragHandler} from 'vs/base/browser/dnd';
|
||||
import {Action} from 'vs/base/common/actions';
|
||||
import {BaseActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import {EmitterEvent} from 'vs/base/common/eventEmitter';
|
||||
import {ProgressBadge, TextBadge, NumberBadge, IconBadge, IBadge} from 'vs/workbench/services/activity/common/activityService';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
|
||||
export class ActivityAction extends Action {
|
||||
|
||||
static BADGE = 'badge';
|
||||
|
||||
private badge: IBadge;
|
||||
private _onDidChangeBadge = new Emitter<this>();
|
||||
|
||||
constructor(id: string, name: string, clazz: string) {
|
||||
super(id, name, clazz);
|
||||
@@ -26,17 +25,19 @@ export class ActivityAction extends Action {
|
||||
this.badge = null;
|
||||
}
|
||||
|
||||
public get onDidChangeBadge(): Event<this> {
|
||||
return this._onDidChangeBadge.event;
|
||||
}
|
||||
|
||||
public activate(): void {
|
||||
if (!this.checked) {
|
||||
this.checked = true;
|
||||
this.emit('checked', { source: this });
|
||||
this._setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
public deactivate(): void {
|
||||
if (this.checked) {
|
||||
this.checked = false;
|
||||
this.emit('checked', { source: this });
|
||||
this._setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +47,7 @@ export class ActivityAction extends Action {
|
||||
|
||||
public setBadge(badge: IBadge): void {
|
||||
this.badge = badge;
|
||||
this.emit(ActivityAction.BADGE, { source: this });
|
||||
this._onDidChangeBadge.fire(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,12 +60,13 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
private $badge: Builder;
|
||||
private $badgeContent: Builder;
|
||||
|
||||
constructor(action: Action, activityName: string = action.label, keybinding: string = null) {
|
||||
constructor(action: ActivityAction, activityName: string = action.label, keybinding: string = null) {
|
||||
super(null, action);
|
||||
|
||||
this.cssClass = action.class;
|
||||
this.name = activityName;
|
||||
this._keybinding = keybinding;
|
||||
action.onDidChangeBadge(this._handleBadgeChangeEvenet, this, this._callOnDispose);
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
@@ -158,7 +160,7 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
}
|
||||
}
|
||||
|
||||
public _updateClass(): void {
|
||||
protected _updateClass(): void {
|
||||
if (this.cssClass) {
|
||||
this.$badge.removeClass(this.cssClass);
|
||||
}
|
||||
@@ -167,7 +169,7 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
this.$badge.addClass(this.cssClass);
|
||||
}
|
||||
|
||||
public _updateChecked(): void {
|
||||
protected _updateChecked(): void {
|
||||
if (this.getAction().checked) {
|
||||
this.$e.addClass('active');
|
||||
} else {
|
||||
@@ -175,16 +177,14 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
}
|
||||
}
|
||||
|
||||
public _updateUnknown(event: EmitterEvent): void {
|
||||
if (event.getType() === ActivityAction.BADGE) {
|
||||
let action = this.getAction();
|
||||
if (action instanceof ActivityAction) {
|
||||
this.updateBadge((<ActivityAction> action).getBadge());
|
||||
}
|
||||
private _handleBadgeChangeEvenet(): void {
|
||||
let action = this.getAction();
|
||||
if (action instanceof ActivityAction) {
|
||||
this.updateBadge((<ActivityAction>action).getBadge());
|
||||
}
|
||||
}
|
||||
|
||||
public _updateEnabled(): void {
|
||||
protected _updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
this.builder.removeClass('disabled');
|
||||
} else {
|
||||
|
||||
@@ -17,10 +17,9 @@ import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInpu
|
||||
import {ResourceEditorInput} from 'vs/workbench/common/editor/resourceEditorInput';
|
||||
import {IInstantiationService, ServicesAccessor} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {KbExpr, IKeybindings, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KbExpr, IKeybindings} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
import {IMessageService, Severity, CloseAction} from 'vs/platform/message/common/message';
|
||||
import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
|
||||
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
|
||||
import {IConfigurationRegistry, Extensions as ConfigurationExtensions} from 'vs/platform/configuration/common/configurationRegistry';
|
||||
@@ -403,52 +402,4 @@ configurationRegistry.registerConfiguration({
|
||||
'description': nls.localize('editorOpenPositioning', "Controls where editors open. Select 'left' or 'right' to open editors to the left or right of the current active one. Select 'first' or 'last' to open editors independently from the currently active one.")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// TODO@Ben remove me next version
|
||||
|
||||
const mapDeprecatedCommands = {
|
||||
'workbench.action.focusFirstEditor': 'workbench.action.focusFirstEditorGroup',
|
||||
'workbench.action.focusSecondEditor': 'workbench.action.focusSecondEditorGroup',
|
||||
'workbench.action.focusThirdEditor': 'workbench.action.focusThirdEditorGroup',
|
||||
'workbench.action.focusLeftEditor': 'workbench.action.focusPreviousGroup',
|
||||
'workbench.action.focusRightEditor': 'workbench.action.focusNextGroup',
|
||||
'workbench.action.moveActiveEditorLeft': 'workbench.action.moveActiveEditorGroupLeft',
|
||||
'workbench.action.moveActiveEditorRight': 'workbench.action.moveActiveEditorGroupRight',
|
||||
'workbench.action.openPreviousEditor': 'workbench.action.openPreviousEditorFromHistory',
|
||||
'workbench.files.action.addToWorkingFiles': 'workbench.action.keepEditor',
|
||||
'workbench.files.action.closeAllFiles': 'workbench.action.closeAllEditors',
|
||||
'workbench.files.action.closeFile': 'workbench.action.closeActiveEditor',
|
||||
'workbench.files.action.closeOtherFiles': 'workbench.action.closeOtherEditors',
|
||||
'workbench.files.action.focusWorkingFiles': 'workbench.files.action.focusOpenEditorsView',
|
||||
'workbench.files.action.openNextWorkingFile': 'workbench.action.nextEditor',
|
||||
'workbench.files.action.openPreviousWorkingFile': 'workbench.action.previousEditor',
|
||||
'workbench.files.action.reopenClosedFile': 'workbench.action.reopenClosedEditor',
|
||||
'workbench.files.action.workingFilesPicker': 'workbench.action.showAllEditors',
|
||||
'workbench.action.cycleEditor': 'workbench.action.navigateEditorGroups'
|
||||
};
|
||||
|
||||
Object.keys(mapDeprecatedCommands).forEach(deprecatedCommandId => {
|
||||
const newCommandId = mapDeprecatedCommands[deprecatedCommandId];
|
||||
|
||||
KeybindingsRegistry.registerCommandDesc({
|
||||
id: deprecatedCommandId,
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0),
|
||||
handler(accessor: ServicesAccessor) {
|
||||
const messageService = accessor.get(IMessageService);
|
||||
const keybindingService = accessor.get(IKeybindingService);
|
||||
|
||||
messageService.show(Severity.Warning, {
|
||||
message: nls.localize('commandDeprecated', "Command **{0}** is now deprecated. You can use **{1}** instead", deprecatedCommandId, newCommandId),
|
||||
actions: [
|
||||
CloseAction,
|
||||
new Action('openKeybindings', nls.localize('openKeybindings', "Configure Keyboard Shortcuts"), null, true, () => {
|
||||
return keybindingService.executeCommand('workbench.action.openGlobalKeybindings');
|
||||
})
|
||||
]
|
||||
});
|
||||
},
|
||||
when: undefined,
|
||||
primary: undefined
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/editorPicker';
|
||||
import 'vs/css!./media/editorpicker';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import labels = require('vs/base/common/labels');
|
||||
|
||||
@@ -23,7 +23,7 @@ import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInpu
|
||||
import {IFileEditorInput, EncodingMode, IEncodingSupport, asFileEditorInput, getUntitledOrFileResource} from 'vs/workbench/common/editor';
|
||||
import {IDisposable, combinedDisposable, dispose} from 'vs/base/common/lifecycle';
|
||||
import {IMessageService, Severity} from 'vs/platform/message/common/message';
|
||||
import {ICommonCodeEditor, IConfigurationChangedEvent, IModelContentChangedEvent, IModelOptionsChangedEvent, IModelModeChangedEvent, ICursorPositionChangedEvent} from 'vs/editor/common/editorCommon';
|
||||
import {ICommonCodeEditor, IModelContentChangedEvent, IModelOptionsChangedEvent, IModelModeChangedEvent, ICursorPositionChangedEvent} from 'vs/editor/common/editorCommon';
|
||||
import {OpenGlobalSettingsAction} from 'vs/workbench/browser/actions/openSettings';
|
||||
import {ICodeEditor, IDiffEditor} from 'vs/editor/browser/editorBrowser';
|
||||
import {TrimTrailingWhitespaceAction} from 'vs/editor/contrib/linesOperations/common/linesOperations';
|
||||
@@ -42,6 +42,7 @@ import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {StyleMutator} from 'vs/base/browser/styleMutator';
|
||||
import {Selection} from 'vs/editor/common/core/selection';
|
||||
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
|
||||
import {TabFocus} from 'vs/editor/common/config/commonEditorConfig';
|
||||
|
||||
function getCodeEditor(editorWidget: IEditor): ICommonCodeEditor {
|
||||
if (editorWidget) {
|
||||
@@ -295,7 +296,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
},
|
||||
this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged()),
|
||||
this.eventService.addListener2(EventType.RESOURCE_ENCODING_CHANGED, (e: ResourceEvent) => this.onResourceEncodingChange(e.resource))
|
||||
this.eventService.addListener2(EventType.RESOURCE_ENCODING_CHANGED, (e: ResourceEvent) => this.onResourceEncodingChange(e.resource)),
|
||||
TabFocus.onDidChangeTabFocus((e) => this.onTabFocusModeChange())
|
||||
);
|
||||
|
||||
return combinedDisposable(this.toDispose);
|
||||
@@ -428,10 +430,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
|
||||
private onTabFocusModeClick(): void {
|
||||
let activeEditor = this.editorService.getActiveEditor();
|
||||
if (activeEditor instanceof BaseTextEditor && isCodeEditorWithTabFocusMode(activeEditor)) {
|
||||
(<ICodeEditor>activeEditor.getControl()).updateOptions({ tabFocusMode: false });
|
||||
}
|
||||
TabFocus.setTabFocusMode(false);
|
||||
}
|
||||
|
||||
private onEditorsChanged(): void {
|
||||
@@ -446,7 +445,6 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.onModeChange(control);
|
||||
this.onEOLChange(control);
|
||||
this.onEncodingChange(activeEditor);
|
||||
this.onTabFocusModeChange(activeEditor);
|
||||
this.onIndentationChange(control);
|
||||
|
||||
// Dispose old active editor listeners
|
||||
@@ -475,11 +473,6 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.activeEditorListeners.push(control.onDidChangeModelOptions((event: IModelOptionsChangedEvent) => {
|
||||
this.onIndentationChange(control);
|
||||
}));
|
||||
|
||||
// Hook Listener for options changes
|
||||
this.activeEditorListeners.push(control.onDidChangeConfiguration((event: IConfigurationChangedEvent) => {
|
||||
this.onTabFocusModeChange(activeEditor);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,13 +598,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
}
|
||||
|
||||
private onTabFocusModeChange(e: IBaseEditor): void {
|
||||
let info: StateDelta = { tabFocusMode: false };
|
||||
|
||||
// We only support text based editors
|
||||
if (e instanceof BaseTextEditor && isCodeEditorWithTabFocusMode(e)) {
|
||||
info = { tabFocusMode: true };
|
||||
}
|
||||
private onTabFocusModeChange(): void {
|
||||
let info: StateDelta = { tabFocusMode: TabFocus.getTabFocusMode() };
|
||||
|
||||
this.updateState(info);
|
||||
}
|
||||
@@ -623,19 +611,6 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
}
|
||||
|
||||
function isCodeEditorWithTabFocusMode(e: BaseTextEditor): boolean {
|
||||
let editorWidget = e.getControl();
|
||||
if (editorWidget.getEditorType() === EditorType.IDiffEditor) {
|
||||
editorWidget = (<IDiffEditor>editorWidget).getModifiedEditor();
|
||||
}
|
||||
if (editorWidget.getEditorType() !== EditorType.ICodeEditor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let editorConfig = (<ICodeEditor>editorWidget).getConfiguration();
|
||||
return editorConfig.tabFocusMode && !editorConfig.readOnly;
|
||||
}
|
||||
|
||||
function isWritableCodeEditor(e: BaseTextEditor): boolean {
|
||||
let editorWidget = e.getControl();
|
||||
if (editorWidget.getEditorType() === EditorType.IDiffEditor) {
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.vs .monaco-workbench .editor:not(.empty) > .content {
|
||||
.vs .monaco-workbench > .editor:not(.empty) > .content {
|
||||
background-color: #F3F3F3;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .editor:not(.empty) > .content {
|
||||
.vs-dark .monaco-workbench > .editor:not(.empty) > .content {
|
||||
background-color: #252526;
|
||||
}
|
||||
|
||||
@@ -24,95 +24,109 @@
|
||||
}
|
||||
|
||||
.vs #monaco-workbench-editor-drop-overlay,
|
||||
.vs .monaco-workbench .editor.empty > .content.dropfeedback {
|
||||
.vs .monaco-workbench > .editor.empty > .content.dropfeedback {
|
||||
background-color: rgba(51,153,255, 0.18);
|
||||
}
|
||||
|
||||
.vs-dark #monaco-workbench-editor-drop-overlay,
|
||||
.vs-dark .monaco-workbench .editor.empty > .content.dropfeedback {
|
||||
.vs-dark .monaco-workbench > .editor.empty > .content.dropfeedback {
|
||||
background-color: rgba(83, 89, 93, 0.5);
|
||||
}
|
||||
|
||||
.hc-black #monaco-workbench-editor-drop-overlay,
|
||||
.hc-black .monaco-workbench .editor.empty > .content.dropfeedback {
|
||||
.hc-black #monaco-workbench-editor-drop-overlay,
|
||||
.hc-black .monaco-workbench > .editor.empty > .content.dropfeedback {
|
||||
background: none !important;
|
||||
outline: 2px dashed #f38518;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .editor > .content.dragging {
|
||||
.vs .monaco-workbench > .editor > .content.dragging {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
border-right: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .editor > .content.dragging {
|
||||
.vs-dark .monaco-workbench > .editor > .content.dragging {
|
||||
border-left: 1px solid #444;
|
||||
border-right: 1px solid #444;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .one-editor-container {
|
||||
.monaco-workbench > .editor > .content > .one-editor-container {
|
||||
position: absolute;
|
||||
box-sizing: border-box; /* use border box to be able to draw a border as separator between editors */
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .editor-left {
|
||||
.monaco-workbench > .editor > .content > .one-editor-container.editor-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .editor-right {
|
||||
.monaco-workbench > .editor > .content > .one-editor-container.editor-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .one-editor-container.drag {
|
||||
.monaco-workbench > .editor > .content > .one-editor-container.dragging {
|
||||
z-index: 2000000;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .one-editor-container.dragging {
|
||||
.monaco-workbench > .editor > .content.dragging > .one-editor-container {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .editor > .content > .one-editor-container.dragging {
|
||||
.vs .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-left,
|
||||
.vs .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-center {
|
||||
border-right: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .editor > .content > .one-editor-container.dragging {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
border-right: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .editor > .content > .one-editor-container.dragging {
|
||||
.vs .monaco-workbench > .editor > .content > .one-editor-container.editor-center,
|
||||
.vs .monaco-workbench > .editor > .content > .one-editor-container.editor-right,
|
||||
.vs .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-right {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-left,
|
||||
.vs-dark .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-center {
|
||||
border-right: 1px solid #444;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .editor > .content > .one-editor-container.dragging {
|
||||
border-left: 1px solid #444;
|
||||
border-right: 1px solid #444;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .one-editor-container.draggedunder {
|
||||
.vs-dark .monaco-workbench > .editor > .content > .one-editor-container.editor-center,
|
||||
.vs-dark .monaco-workbench > .editor > .content > .one-editor-container.editor-right,
|
||||
.vs-dark .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-right {
|
||||
border-left: 1px solid #444;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-left,
|
||||
.hc-black .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-center {
|
||||
border-right: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench > .editor > .content > .one-editor-container.dragging {
|
||||
border-left: 1px solid #6FC3DF;
|
||||
border-right: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench > .editor > .content > .one-editor-container.editor-center,
|
||||
.hc-black .monaco-workbench > .editor > .content > .one-editor-container.editor-right,
|
||||
.hc-black .monaco-workbench > .editor > .content.dragging > .one-editor-container.editor-right {
|
||||
border-left: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.monaco-workbench > .editor > .content > .one-editor-container.draggedunder {
|
||||
transition: left 200ms ease-out;
|
||||
}
|
||||
|
||||
.monaco-workbench .editor > .content > .editor-right.draggedunder {
|
||||
.monaco-workbench > .editor > .content > .editor-right.draggedunder {
|
||||
transition-property: right;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .editor > .content > .editor-center {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .editor > .content > .editor-center {
|
||||
border-left: 1px solid #444;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .editor > .content > .editor-center {
|
||||
border-left: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .editor > .content > .editor-right {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .editor > .content > .editor-right {
|
||||
border-left: 1px solid #444;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .editor > .content > .editor-right {
|
||||
border-left: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.monaco-workbench > .editor > .content .editor-container {
|
||||
height: calc(100% - 35px); /* Editor is below editor title */
|
||||
}
|
||||
@@ -41,6 +41,10 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-container > .title.tabs > .monaco-scrollable-element .scrollbar {
|
||||
z-index: 3; /* on top of tabs */
|
||||
}
|
||||
|
||||
/* Tabs Container */
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container {
|
||||
@@ -126,12 +130,9 @@
|
||||
border: 1px solid #f38518;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback {
|
||||
background-color: rgba(51,153,255, 0.18);
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback,
|
||||
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dropfeedback {
|
||||
background-color: rgba(187, 230, 255, 0.5);
|
||||
background-color: rgba(51,153,255, 0.18);
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback,
|
||||
|
||||
@@ -984,20 +984,27 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
|
||||
if (e.target === node) {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
onDrop(e, Position.LEFT);
|
||||
} else {
|
||||
DOM.removeClass(node, 'dropfeedback');
|
||||
}
|
||||
}));
|
||||
|
||||
// Drag over
|
||||
this.toDispose.push(DOM.addDisposableListener(node, DOM.EventType.DRAG_OVER, (e: DragEvent) => {
|
||||
DOM.addClass(node, 'dropfeedback');
|
||||
if (e.target === node) {
|
||||
DOM.addClass(node, 'dropfeedback');
|
||||
}
|
||||
|
||||
const target = <HTMLElement>e.target;
|
||||
if (target) {
|
||||
if (overlay && target.id !== overlayId) {
|
||||
destroyOverlay(); // somehow we managed to move the mouse quickly out of the current overlay, so destroy it
|
||||
}
|
||||
|
||||
createOverlay(target);
|
||||
|
||||
if (overlay) {
|
||||
DOM.removeClass(node, 'dropfeedback'); // if we show an overlay, we can remove the drop feedback from the editor background
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -1655,4 +1662,4 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
|
||||
|
||||
this._onGroupFocusChanged.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import {Position} from 'vs/platform/editor/common/editor';
|
||||
import {IEditorGroup, IEditorIdentifier, asFileEditorInput, EditorOptions} from 'vs/workbench/common/editor';
|
||||
import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
|
||||
import {CommonKeybindings as Kb} from 'vs/base/common/keyCodes';
|
||||
import {CommonKeybindings as Kb, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import {ActionBar, Separator} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -292,11 +292,14 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Add a tab for each opened editor
|
||||
this.context.getEditors().forEach(editor => {
|
||||
const description = editor.getDescription(true) || '';
|
||||
|
||||
const tabContainer = document.createElement('div');
|
||||
tabContainer.title = description;
|
||||
tabContainer.draggable = true;
|
||||
tabContainer.tabIndex = 0;
|
||||
tabContainer.setAttribute('role', 'tab');
|
||||
tabContainer.setAttribute('aria-label', editor.getName());
|
||||
tabContainer.setAttribute('role', 'presentation'); // cannot use role "tab" here due to https://github.com/Microsoft/vscode/issues/8659
|
||||
tabContainer.setAttribute('aria-label', `tab, ${editor.getName()}`);
|
||||
DOM.addClass(tabContainer, 'tab monaco-editor-background');
|
||||
tabContainers.push(tabContainer);
|
||||
|
||||
@@ -308,7 +311,6 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Tab Label
|
||||
const tabLabel = document.createElement('a');
|
||||
tabLabel.innerText = editor.getName();
|
||||
tabLabel.title = editor.getDescription(true) || '';
|
||||
tabLabelContainer.appendChild(tabLabel);
|
||||
|
||||
// Tab Close
|
||||
@@ -392,6 +394,16 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
}));
|
||||
|
||||
// Context menu on Shift+F10
|
||||
this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
if (event.shiftKey && event.keyCode === KeyCode.F10) {
|
||||
DOM.EventHelper.stop(e);
|
||||
|
||||
this.onContextMenu(identifier, e, tab);
|
||||
}
|
||||
}));
|
||||
|
||||
// Keyboard accessibility
|
||||
this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
@@ -429,6 +441,11 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (handled) {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
}
|
||||
|
||||
// moving in the tabs container can have an impact on scrolling position, so we need to update the custom scrollbar
|
||||
this.scrollbar.updateState({
|
||||
scrollLeft: this.tabsContainer.scrollLeft
|
||||
});
|
||||
}));
|
||||
|
||||
// Pin on double click
|
||||
|
||||
@@ -47,7 +47,7 @@ import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage'
|
||||
import {ContextMenuService} from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
|
||||
import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
|
||||
import {IWorkspace, IConfiguration} from 'vs/platform/workspace/common/workspace';
|
||||
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {IActivityService} from 'vs/workbench/services/activity/common/activityService';
|
||||
import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService';
|
||||
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
|
||||
@@ -118,6 +118,8 @@ export class Workbench implements IPartService {
|
||||
private sideBarPosition: Position;
|
||||
private panelHidden: boolean;
|
||||
private editorBackgroundDelayer: Delayer<void>;
|
||||
private messagesVisibleContext: IKeybindingContextKey<boolean>;
|
||||
private editorsVisibleContext: IKeybindingContextKey<boolean>;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
@@ -196,6 +198,10 @@ export class Workbench implements IPartService {
|
||||
this.callbacks.onServicesCreated();
|
||||
}
|
||||
|
||||
// Contexts
|
||||
this.messagesVisibleContext = this.keybindingService.createKey('globalMessageVisible', false);
|
||||
this.editorsVisibleContext = this.keybindingService.createKey('editorIsOpen', false);
|
||||
|
||||
// Register Listeners
|
||||
this.registerListeners();
|
||||
|
||||
@@ -651,10 +657,8 @@ export class Workbench implements IPartService {
|
||||
|
||||
// Handle message service and quick open events
|
||||
if (this.messageService instanceof WorkbenchMessageService) {
|
||||
const messagesShowingContextKey = this.keybindingService.createKey('globalMessageVisible', false);
|
||||
|
||||
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesShowing(() => messagesShowingContextKey.set(true)));
|
||||
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesCleared(() => messagesShowingContextKey.reset()));
|
||||
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesShowing(() => this.messagesVisibleContext.set(true)));
|
||||
this.toDispose.push((<WorkbenchMessageService>this.messageService).onMessagesCleared(() => this.messagesVisibleContext.reset()));
|
||||
|
||||
this.toDispose.push(this.quickOpen.onShow(() => (<WorkbenchMessageService>this.messageService).suspend())); // when quick open is open, don't show messages behind
|
||||
this.toDispose.push(this.quickOpen.onHide(() => (<WorkbenchMessageService>this.messageService).resume())); // resume messages once quick open is closed again
|
||||
@@ -669,8 +673,10 @@ export class Workbench implements IPartService {
|
||||
|
||||
const editorContainer = this.editorPart.getContainer();
|
||||
if (visibleEditors === 0) {
|
||||
this.editorsVisibleContext.reset();
|
||||
this.editorBackgroundDelayer.trigger(() => editorContainer.addClass('empty'));
|
||||
} else {
|
||||
this.editorsVisibleContext.set(true);
|
||||
this.editorBackgroundDelayer.trigger(() => editorContainer.removeClass('empty'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -992,7 +992,6 @@ export class EditorStacksModel implements IEditorStacksModel {
|
||||
if (modelRaw) {
|
||||
const serialized: ISerializedEditorStacksModel = JSON.parse(modelRaw);
|
||||
|
||||
// TODO@Ben remove this once stacks are stable; prevent bad stored state
|
||||
const invalidId = this.doValidate(serialized);
|
||||
if (invalidId) {
|
||||
console.warn(`Ignoring invalid stacks model (Error code: ${invalidId}): ${JSON.stringify(serialized)}`);
|
||||
@@ -1002,55 +1001,6 @@ export class EditorStacksModel implements IEditorStacksModel {
|
||||
|
||||
this._groups = serialized.groups.map(s => this.doCreateGroup(s));
|
||||
this._activeGroup = this._groups[serialized.active];
|
||||
} else {
|
||||
this.migrate();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO@Ben migration
|
||||
private migrate(): void {
|
||||
const LEGACY_EDITOR_STATE_STORAGE_KEY = 'memento/workbench.parts.editor';
|
||||
const legacyModelRaw = this.storageService.get(LEGACY_EDITOR_STATE_STORAGE_KEY, StorageScope.WORKSPACE);
|
||||
if (legacyModelRaw) {
|
||||
try {
|
||||
const legacyModel = JSON.parse(legacyModelRaw);
|
||||
const state = legacyModel['editorpart.editorState'];
|
||||
const editorsRaw: { inputId: string; inputValue: string }[] = state.editors;
|
||||
|
||||
const registry = Registry.as<IEditorRegistry>(Extensions.Editors);
|
||||
const editors = editorsRaw.map(editorRaw => {
|
||||
const factory = registry.getEditorInputFactory(editorRaw.inputId);
|
||||
if (factory) {
|
||||
return factory.deserialize(this.instantiationService, editorRaw.inputValue);
|
||||
}
|
||||
|
||||
return null;
|
||||
}).filter(editor => !!editor);
|
||||
|
||||
if (editors.length > 0) {
|
||||
const leftGroup = this.openGroup('', true);
|
||||
leftGroup.openEditor(editors[0], { active: true, pinned: true });
|
||||
}
|
||||
|
||||
if (editors.length > 1) {
|
||||
const centerGroup = this.openGroup('', true);
|
||||
centerGroup.openEditor(editors[1], { active: true, pinned: true });
|
||||
}
|
||||
|
||||
if (editors.length > 2) {
|
||||
const rightGroup = this.openGroup('', true);
|
||||
rightGroup.openEditor(editors[2], { active: true, pinned: true });
|
||||
}
|
||||
|
||||
this.storageService.remove(LEGACY_EDITOR_STATE_STORAGE_KEY, StorageScope.WORKSPACE);
|
||||
} catch (error) {
|
||||
console.warn('Unable to migrate previous editor state', error, legacyModelRaw);
|
||||
|
||||
// Reset
|
||||
this._groups = [];
|
||||
this._activeGroup = void 0;
|
||||
this.groupToIdentifier = Object.create(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ export class CloseEditorAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IWindowService private windowService: IWindowService
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
@@ -50,8 +49,6 @@ export class CloseEditorAction extends Action {
|
||||
return this.editorService.closeEditor(activeEditor.position, activeEditor.input);
|
||||
}
|
||||
|
||||
this.windowService.getWindow().close();
|
||||
|
||||
return TPromise.as(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,13 @@ import {IConfigurationRegistry, Extensions as ConfigurationExtensions} from 'vs/
|
||||
import {IWorkbenchActionRegistry, Extensions} from 'vs/workbench/common/actionRegistry';
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import platform = require('vs/base/common/platform');
|
||||
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KbExpr, IKeybindings} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
|
||||
import {CloseEditorAction, ReloadWindowAction, ShowStartupPerformance, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleDevToolsAction, ToggleFullScreenAction, ToggleMenuBarAction, OpenRecentAction, CloseFolderAction, CloseWindowAction, NewWindowAction, CloseMessagesAction} from 'vs/workbench/electron-browser/actions';
|
||||
|
||||
const closeEditorOrWindowKeybindings: IKeybindings = { primary: KeyMod.CtrlCmd | KeyCode.KEY_W, win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] }};
|
||||
|
||||
// Contribute Global Actions
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
const developerCategory = nls.localize('developer', "Developer");
|
||||
@@ -31,12 +35,24 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ZoomRe
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowStartupPerformance, ShowStartupPerformance.ID, ShowStartupPerformance.LABEL), 'Developer: Startup Performance', developerCategory);
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL), 'Reload Window');
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseMessagesAction, CloseMessagesAction.ID, CloseMessagesAction.LABEL, { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] }, KbExpr.has('globalMessageVisible')), 'Close Notification Messages');
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorAction, CloseEditorAction.ID, CloseEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_W, win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] } }), 'View: Close Editor', viewCategory);
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorAction, CloseEditorAction.ID, CloseEditorAction.LABEL, closeEditorOrWindowKeybindings), 'View: Close Editor', viewCategory);
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
|
||||
if (platform.isWindows || platform.isLinux) {
|
||||
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory);
|
||||
}
|
||||
|
||||
// close the window when the last editor is closed by reusing the same keybinding
|
||||
KeybindingsRegistry.registerCommandDesc({
|
||||
id: 'workbench.action.closeWindow',
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
|
||||
when: KbExpr.not('editorIsOpen'),
|
||||
primary: closeEditorOrWindowKeybindings.primary,
|
||||
handler: accessor => {
|
||||
const windowService = accessor.get(IWindowService);
|
||||
windowService.getWindow().close();
|
||||
}
|
||||
});
|
||||
|
||||
// Configuration: Window
|
||||
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
import platform = require('vs/base/common/platform');
|
||||
import URI from 'vs/base/common/uri';
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import workbenchEditorCommon = require('vs/workbench/common/editor');
|
||||
import DND = require('vs/base/browser/dnd');
|
||||
import {Builder, $} from 'vs/base/browser/builder';
|
||||
import {Identifiers} from 'vs/workbench/common/constants';
|
||||
import {asFileEditorInput} from 'vs/workbench/common/editor';
|
||||
import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
import {IStorageService} from 'vs/platform/storage/common/storage';
|
||||
@@ -17,6 +20,8 @@ import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
|
||||
|
||||
import {ipcRenderer as ipc, shell, remote} from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const dialog = remote.dialog;
|
||||
|
||||
@@ -29,6 +34,13 @@ export interface IWindowConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
enum DraggedFileType {
|
||||
UNKNOWN,
|
||||
FILE,
|
||||
EXTENSION,
|
||||
FOLDER
|
||||
}
|
||||
|
||||
export class ElectronWindow {
|
||||
private win: Electron.BrowserWindow;
|
||||
private windowId: number;
|
||||
@@ -53,7 +65,7 @@ export class ElectronWindow {
|
||||
// React to editor input changes (Mac only)
|
||||
if (platform.platform === platform.Platform.Mac) {
|
||||
this.editorGroupService.onEditorsChanged(() => {
|
||||
let fileInput = workbenchEditorCommon.asFileEditorInput(this.editorService.getActiveEditorInput(), true);
|
||||
let fileInput = asFileEditorInput(this.editorService.getActiveEditorInput(), true);
|
||||
let representedFilename = '';
|
||||
if (fileInput) {
|
||||
representedFilename = fileInput.getResource().fsPath;
|
||||
@@ -63,11 +75,59 @@ export class ElectronWindow {
|
||||
});
|
||||
}
|
||||
|
||||
// Prevent a dropped link from opening within
|
||||
[DOM.EventType.DRAG_OVER, DOM.EventType.DROP].forEach(event => {
|
||||
let draggedExternalResources: URI[];
|
||||
let dropOverlay: Builder;
|
||||
|
||||
function cleanUp(): void {
|
||||
draggedExternalResources = void 0;
|
||||
if (dropOverlay) {
|
||||
dropOverlay.destroy();
|
||||
dropOverlay = void 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect resources dropped into Code from outside
|
||||
window.document.body.addEventListener(DOM.EventType.DRAG_OVER, (e: DragEvent) => {
|
||||
DOM.EventHelper.stop(e);
|
||||
|
||||
if (!draggedExternalResources) {
|
||||
draggedExternalResources = DND.extractResources(e, true /* external only */);
|
||||
|
||||
// Show Code wide overlay if we detect a Folder or Extension to be dragged
|
||||
if (draggedExternalResources.some(r => {
|
||||
const kind = this.getFileKind(r);
|
||||
|
||||
return kind === DraggedFileType.FOLDER || kind === DraggedFileType.EXTENSION;
|
||||
})) {
|
||||
dropOverlay = $(window.document.getElementById(Identifiers.WORKBENCH_CONTAINER))
|
||||
.div({ id: 'monaco-workbench-drop-overlay' })
|
||||
.on(DOM.EventType.DROP, (e: DragEvent) => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
|
||||
this.focus(); // make sure this window has focus so that the open call reaches the right window!
|
||||
ipc.send('vscode:windowOpen', draggedExternalResources.map(r => r.fsPath)); // handled from browser process
|
||||
|
||||
cleanUp();
|
||||
})
|
||||
.on([DOM.EventType.DRAG_LEAVE, DOM.EventType.DRAG_END], () => {
|
||||
cleanUp();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Clear our map and overlay on any finish of DND outside the overlay
|
||||
[DOM.EventType.DROP, DOM.EventType.DRAG_END].forEach(event => {
|
||||
window.document.body.addEventListener(event, (e: DragEvent) => {
|
||||
DOM.EventHelper.stop(e);
|
||||
});
|
||||
if (!dropOverlay || e.target !== dropOverlay.getHTMLElement()) {
|
||||
cleanUp(); // only run cleanUp() if we are not over the overlay (because we are being called in capture phase)
|
||||
}
|
||||
}, true /* use capture because components within may preventDefault() when they accept the drop */);
|
||||
});
|
||||
|
||||
// prevent opening a real URL inside the shell
|
||||
window.document.body.addEventListener(DOM.EventType.DROP, (e: DragEvent) => {
|
||||
DOM.EventHelper.stop(e);
|
||||
});
|
||||
|
||||
// Handle window.open() calls
|
||||
@@ -86,20 +146,19 @@ export class ElectronWindow {
|
||||
};
|
||||
}
|
||||
|
||||
public open(pathsToOpen: string[]): void;
|
||||
public open(fileResource: URI): void;
|
||||
public open(pathToOpen: string): void;
|
||||
public open(arg1: any): void {
|
||||
let pathsToOpen: string[];
|
||||
if (Array.isArray(arg1)) {
|
||||
pathsToOpen = arg1;
|
||||
} else if (typeof arg1 === 'string') {
|
||||
pathsToOpen = [arg1];
|
||||
} else {
|
||||
pathsToOpen = [(<URI>arg1).fsPath];
|
||||
private getFileKind(resource: URI): DraggedFileType {
|
||||
if (path.extname(resource.fsPath) === '.vsix') {
|
||||
return DraggedFileType.EXTENSION;
|
||||
}
|
||||
|
||||
ipc.send('vscode:windowOpen', pathsToOpen); // handled from browser process
|
||||
let kind = DraggedFileType.UNKNOWN;
|
||||
try {
|
||||
kind = fs.statSync(resource.fsPath).isDirectory() ? DraggedFileType.FOLDER : DraggedFileType.FILE;
|
||||
} catch (error) {
|
||||
// Do not fail in DND handler
|
||||
}
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
public openNew(): void {
|
||||
|
||||
@@ -8,7 +8,6 @@ import lifecycle = require('vs/base/common/lifecycle');
|
||||
import errors = require('vs/base/common/errors');
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import dom = require('vs/base/browser/dom');
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IDebugService, State } from 'vs/workbench/parts/debug/common/debug';
|
||||
@@ -27,7 +26,7 @@ export class SelectConfigActionItem extends BaseActionItem {
|
||||
super(null, action);
|
||||
|
||||
this.select = document.createElement('select');
|
||||
this.select.className = `debug-select action-bar-select ${isWindows ? 'windows' : ''}`;
|
||||
this.select.className = 'debug-select action-bar-select';
|
||||
|
||||
this.toDispose = [];
|
||||
this.registerListeners(configurationService);
|
||||
|
||||
@@ -83,7 +83,15 @@ export class DebugActionsWidget implements wbext.IWorkbenchContribution {
|
||||
}));
|
||||
$(window).on(dom.EventType.RESIZE, () => this.setXCoordinate(), this.toDispose);
|
||||
|
||||
this.dragArea.on(dom.EventType.MOUSE_DOWN, event => {
|
||||
this.dragArea.on(dom.EventType.MOUSE_UP, (event: MouseEvent) => {
|
||||
const mouseClickEvent = new StandardMouseEvent(event);
|
||||
if (mouseClickEvent.detail === 2) {
|
||||
// double click on debug bar centers it again #8250
|
||||
this.setXCoordinate(0.5 * window.innerWidth);
|
||||
}
|
||||
});
|
||||
|
||||
this.dragArea.on(dom.EventType.MOUSE_DOWN, (event: MouseEvent) => {
|
||||
const $window = $(window);
|
||||
this.dragArea.addClass('dragged');
|
||||
|
||||
|
||||
@@ -632,7 +632,7 @@ export class VariablesRenderer implements tree.IRenderer {
|
||||
}
|
||||
|
||||
let data: IVariableTemplateData = Object.create(null);
|
||||
data.expression = dom.append(container, $(isMacintosh ? '.expression.mac' : '.expression.win-linux'));
|
||||
data.expression = dom.append(container, $('.expression'));
|
||||
data.name = dom.append(data.expression, $('span.name'));
|
||||
data.value = dom.append(data.expression, $('span.value'));
|
||||
|
||||
@@ -843,7 +843,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer {
|
||||
data.actionBar.push(this.actionProvider.getExpressionActions(), { icon: true, label: false });
|
||||
}
|
||||
|
||||
data.expression = dom.append(container, $(isMacintosh ? '.expression.mac' : '.expression.win-linux'));
|
||||
data.expression = dom.append(container, $('.expression'));
|
||||
data.name = dom.append(data.expression, $('span.name'));
|
||||
data.value = dom.append(data.expression, $('span.value'));
|
||||
|
||||
@@ -990,7 +990,7 @@ export class BreakpointsActionProvider implements renderer.IActionProvider {
|
||||
actions.push(this.instantiationService.createInstance(debugactions.RemoveAllBreakpointsAction, debugactions.RemoveAllBreakpointsAction.ID, debugactions.RemoveAllBreakpointsAction.LABEL));
|
||||
actions.push(new actionbar.Separator());
|
||||
|
||||
actions.push(this.instantiationService.createInstance(debugactions.ToggleBreakpointsActivatedAction, debugactions.ToggleBreakpointsActivatedAction.ID, debugactions.ToggleBreakpointsActivatedAction.LABEL));
|
||||
actions.push(this.instantiationService.createInstance(debugactions.ToggleBreakpointsActivatedAction, debugactions.ToggleBreakpointsActivatedAction.ID, debugactions.ToggleBreakpointsActivatedAction.ACTIVATE_LABEL));
|
||||
actions.push(new actionbar.Separator());
|
||||
|
||||
actions.push(this.instantiationService.createInstance(debugactions.EnableAllBreakpointsAction, debugactions.EnableAllBreakpointsAction.ID, debugactions.EnableAllBreakpointsAction.LABEL));
|
||||
@@ -1099,9 +1099,6 @@ export class BreakpointsRenderer implements tree.IRenderer {
|
||||
|
||||
data.checkbox = <HTMLInputElement>$('input');
|
||||
data.checkbox.type = 'checkbox';
|
||||
if (!isMacintosh) {
|
||||
data.checkbox.className = 'checkbox-win-linux';
|
||||
}
|
||||
|
||||
dom.append(data.breakpoint, data.checkbox);
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ export class BreakpointsView extends viewlet.AdaptiveCollapsibleViewletView {
|
||||
public getActions(): actions.IAction[] {
|
||||
return [
|
||||
this.instantiationService.createInstance(debugactions.AddFunctionBreakpointAction, debugactions.AddFunctionBreakpointAction.ID, debugactions.AddFunctionBreakpointAction.LABEL),
|
||||
this.instantiationService.createInstance(debugactions.ToggleBreakpointsActivatedAction, debugactions.ToggleBreakpointsActivatedAction.ID, debugactions.ToggleBreakpointsActivatedAction.LABEL),
|
||||
this.instantiationService.createInstance(debugactions.ToggleBreakpointsActivatedAction, debugactions.ToggleBreakpointsActivatedAction.ID, debugactions.ToggleBreakpointsActivatedAction.ACTIVATE_LABEL),
|
||||
this.instantiationService.createInstance(debugactions.RemoveAllBreakpointsAction, debugactions.RemoveAllBreakpointsAction.ID, debugactions.RemoveAllBreakpointsAction.LABEL)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -18,14 +18,11 @@
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.monaco-editor .breakpoint-widget .input.mac {
|
||||
.monaco-workbench.mac .monaco-editor .breakpoint-widget .input {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.monaco-editor .breakpoint-widget .input.win {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.monaco-editor .breakpoint-widget .input.linux {
|
||||
.monaco-workbench.windows .monaco-editor .breakpoint-widget .input,
|
||||
.monaco-workbench.linux .monaco-editor .breakpoint-widget .input {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@@ -162,11 +162,12 @@
|
||||
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-tree-row .expression.mac {
|
||||
.monaco-workbench.mac .monaco-tree-row .expression {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-tree-row .expression.win-linux {
|
||||
.monaco-workbench.windows .monaco-tree-row .expression,
|
||||
.monaco-workbench.linux .monaco-tree-row .expression {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
font-size: 11px;
|
||||
word-break: normal;
|
||||
text-overflow: ellipsis;
|
||||
height: 18px;
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid rgba(128, 128, 128, 0.35);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.monaco-workbench .debug-select.windows {
|
||||
.monaco-workbench.windows .debug-select {
|
||||
margin-top: 7px; /* Center the select box */
|
||||
}
|
||||
|
||||
@@ -290,7 +290,8 @@
|
||||
margin-left: 0.8em;
|
||||
}
|
||||
|
||||
.debug-viewlet .debug-breakpoints .breakpoint > .checkbox-win-linux {
|
||||
.monaco-workbench.windows debug-viewlet .debug-breakpoints .breakpoint > .checkbox,
|
||||
.monaco-workbench.linux debug-viewlet .debug-breakpoints .breakpoint > .checkbox {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,13 +35,15 @@
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-tree .monaco-tree-row .input.expression.mac,
|
||||
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression.mac {
|
||||
.monaco-workbench.mac .repl .repl-tree .monaco-tree-row .input.expression,
|
||||
.monaco-workbench.mac .repl .repl-tree .monaco-tree-row .output.expression {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-tree .monaco-tree-row .input.expression.win-linux,
|
||||
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression.win-linux {
|
||||
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .input.expression,
|
||||
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .output.expression,
|
||||
.monaco-workbench.linux .repl .repl-tree .monaco-tree-row .input.expression,
|
||||
.monaco-workbench.linux .repl .repl-tree .monaco-tree-row .output.expression {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -143,30 +145,30 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.windows:before {
|
||||
.monaco-workbench.windows .repl .repl-input-wrapper:before {
|
||||
content: '\203A'; /* character does not exist on windows */
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.mac {
|
||||
.monaco-workbench.mac .repl .repl-input-wrapper {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.win {
|
||||
.monaco-workbench.windows .repl .repl-input-wrapper {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.linux {
|
||||
.monaco-workbench.linux .repl .repl-input-wrapper {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.linux:before {
|
||||
.monaco-workbench.linux .repl .repl-input-wrapper:before {
|
||||
content: '\276f';
|
||||
font-size: 9px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.monaco-workbench .repl .repl-input-wrapper.mac:before {
|
||||
.monaco-workbench.mac .repl .repl-input-wrapper:before {
|
||||
content: '\276f';
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export class Repl extends Panel {
|
||||
super.create(parent);
|
||||
const container = dom.append(parent.getHTMLElement(), $('.repl'));
|
||||
this.treeContainer = dom.append(container, $('.repl-tree'));
|
||||
const replInputContainer = dom.append(container, $(platform.isWindows ? '.repl-input-wrapper.windows' : platform.isMacintosh ? '.repl-input-wrapper.mac' : '.repl-input-wrapper.linux'));
|
||||
const replInputContainer = dom.append(container, $('.repl-input-wrapper'));
|
||||
this.replInput = <HTMLInputElement>dom.append(replInputContainer, $('input.repl-input'));
|
||||
this.replInput.type = 'text';
|
||||
|
||||
|
||||
@@ -29,10 +29,6 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
|
||||
|
||||
const $ = dom.emmet;
|
||||
|
||||
function getExpressionClassName(): string {
|
||||
return isMacintosh ? '.expression.mac' : '.expression.win-linux';
|
||||
}
|
||||
|
||||
export class ReplExpressionsDataSource implements tree.IDataSource {
|
||||
|
||||
constructor(private debugService: debug.IDebugService) {
|
||||
@@ -155,7 +151,7 @@ export class ReplExpressionsRenderer implements tree.IRenderer {
|
||||
public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): any {
|
||||
if (templateId === ReplExpressionsRenderer.VARIABLE_TEMPLATE_ID) {
|
||||
let data: debugviewer.IVariableTemplateData = Object.create(null);
|
||||
data.expression = dom.append(container, $(getExpressionClassName()));
|
||||
data.expression = dom.append(container, $('.expression'));
|
||||
data.name = dom.append(data.expression, $('span.name'));
|
||||
data.value = dom.append(data.expression, $('span.value'));
|
||||
|
||||
@@ -165,8 +161,8 @@ export class ReplExpressionsRenderer implements tree.IRenderer {
|
||||
if (templateId === ReplExpressionsRenderer.INPUT_OUTPUT_PAIR_TEMPLATE_ID) {
|
||||
let data: IInputOutputPairTemplateData = Object.create(null);
|
||||
dom.addClass(container, 'input-output-pair');
|
||||
data.input = dom.append(container, $('.input' + getExpressionClassName()));
|
||||
data.output = dom.append(container, $('.output' + getExpressionClassName()));
|
||||
data.input = dom.append(container, $('.input.expression'));
|
||||
data.output = dom.append(container, $('.output.expression'));
|
||||
data.value = dom.append(data.output, $('span.value'));
|
||||
data.annotation = dom.append(data.output, $('span'));
|
||||
|
||||
@@ -176,7 +172,7 @@ export class ReplExpressionsRenderer implements tree.IRenderer {
|
||||
if (templateId === ReplExpressionsRenderer.VALUE_OUTPUT_TEMPLATE_ID) {
|
||||
let data: IValueOutputTemplateData = Object.create(null);
|
||||
dom.addClass(container, 'output');
|
||||
let expression = dom.append(container, $('.output' + getExpressionClassName()));
|
||||
let expression = dom.append(container, $('.output.expression'));
|
||||
|
||||
data.container = container;
|
||||
data.counter = dom.append(expression, $('div.counter'));
|
||||
@@ -190,7 +186,7 @@ export class ReplExpressionsRenderer implements tree.IRenderer {
|
||||
dom.addClass(container, 'output');
|
||||
|
||||
data.container = container;
|
||||
data.expression = dom.append(container, $('.output' + getExpressionClassName()));
|
||||
data.expression = dom.append(container, $('.output.expression'));
|
||||
data.key = dom.append(data.expression, $('span.name'));
|
||||
data.value = dom.append(data.expression, $('span.value'));
|
||||
data.annotation = dom.append(data.expression, $('span'));
|
||||
|
||||
@@ -198,25 +198,19 @@ export interface IEnvConfig {
|
||||
name?: string;
|
||||
type: string;
|
||||
request: string;
|
||||
program?: string;
|
||||
stopOnEntry?: boolean;
|
||||
args?: string[];
|
||||
cwd?: string;
|
||||
runtimeExecutable?: string;
|
||||
runtimeArgs?: string[];
|
||||
env?: { [key: string]: string; };
|
||||
sourceMaps?: boolean;
|
||||
outDir?: string;
|
||||
address?: string;
|
||||
internalConsoleOptions?: string;
|
||||
port?: number;
|
||||
preLaunchTask?: string;
|
||||
externalConsole?: boolean;
|
||||
debugServer?: number;
|
||||
noDebug?: boolean;
|
||||
silentlyAbort?: boolean;
|
||||
}
|
||||
|
||||
export interface IExtHostConfig extends IEnvConfig {
|
||||
port?: number;
|
||||
sourceMaps?: boolean;
|
||||
outDir?: string;
|
||||
}
|
||||
|
||||
export interface IConfig extends IEnvConfig {
|
||||
windows?: IEnvConfig;
|
||||
osx?: IEnvConfig;
|
||||
|
||||
@@ -337,47 +337,48 @@ export class DebugService implements debug.IDebugService {
|
||||
}
|
||||
|
||||
private loadBreakpoints(): debug.IBreakpoint[] {
|
||||
let result: debug.IBreakpoint[];
|
||||
try {
|
||||
return JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => {
|
||||
result = JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => {
|
||||
return new model.Breakpoint(new Source(breakpoint.source.raw ? breakpoint.source.raw : { path: uri.parse(breakpoint.source.uri).fsPath, name: breakpoint.source.name }),
|
||||
breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition);
|
||||
});
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
return result || [];
|
||||
}
|
||||
|
||||
private loadFunctionBreakpoints(): debug.IFunctionBreakpoint[] {
|
||||
let result: debug.IFunctionBreakpoint[];
|
||||
try {
|
||||
return JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => {
|
||||
result = JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => {
|
||||
return new model.FunctionBreakpoint(fb.name, fb.enabled);
|
||||
});
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
return result || [];
|
||||
}
|
||||
|
||||
private loadExceptionBreakpoints(): debug.IExceptionBreakpoint[] {
|
||||
let result: debug.IExceptionBreakpoint[] = null;
|
||||
let result: debug.IExceptionBreakpoint[];
|
||||
try {
|
||||
result = JSON.parse(this.storageService.get(DEBUG_EXCEPTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((exBreakpoint: any) => {
|
||||
return new model.ExceptionBreakpoint(exBreakpoint.filter || exBreakpoint.name, exBreakpoint.label, exBreakpoint.enabled);
|
||||
});
|
||||
} catch (e) {
|
||||
result = [];
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
return result;
|
||||
return result || [];
|
||||
}
|
||||
|
||||
private loadWatchExpressions(): model.Expression[] {
|
||||
let result: model.Expression[];
|
||||
try {
|
||||
return JSON.parse(this.storageService.get(DEBUG_WATCH_EXPRESSIONS_KEY, StorageScope.WORKSPACE, '[]')).map((watch: any) => {
|
||||
result = JSON.parse(this.storageService.get(DEBUG_WATCH_EXPRESSIONS_KEY, StorageScope.WORKSPACE, '[]')).map((watch: any) => {
|
||||
return new model.Expression(watch.name, false, watch.id);
|
||||
});
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
} catch (e) { }
|
||||
|
||||
return result || [];
|
||||
}
|
||||
|
||||
public get state(): debug.State {
|
||||
@@ -565,7 +566,7 @@ export class DebugService implements debug.IDebugService {
|
||||
}))));
|
||||
}
|
||||
|
||||
private doCreateSession(configuration: debug.IConfig): TPromise<any> {
|
||||
private doCreateSession(configuration: debug.IExtHostConfig): TPromise<any> {
|
||||
this.setStateAndEmit(debug.State.Initializing);
|
||||
|
||||
return this.telemetryService.getTelemetryInfo().then(info => {
|
||||
@@ -722,7 +723,7 @@ export class DebugService implements debug.IDebugService {
|
||||
}
|
||||
|
||||
this.setStateAndEmit(debug.State.Initializing);
|
||||
const configuration = this.configurationManager.configuration;
|
||||
const configuration = <debug.IExtHostConfig>this.configurationManager.configuration;
|
||||
return this.doCreateSession({
|
||||
type: configuration.type,
|
||||
request: 'attach',
|
||||
|
||||
@@ -280,7 +280,7 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
||||
if (!result) {
|
||||
this.configuration.silentlyAbort = true;
|
||||
}
|
||||
interactiveVariablesToKeys[interactiveVariable].forEach(key => this.configuration[key] = result);
|
||||
interactiveVariablesToKeys[interactiveVariable].forEach(key => this.configuration[key] = this.configuration[key].replace(`\${command.${ interactiveVariable }}`, result));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -337,6 +337,7 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
||||
|
||||
public openConfigFile(sideBySide: boolean): TPromise<boolean> {
|
||||
const resource = uri.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '/.vscode/launch.json'));
|
||||
let configFileCreated = false;
|
||||
|
||||
return this.fileService.resolveContent(resource).then(content => true, err =>
|
||||
this.getInitialConfigFileContent().then(content => {
|
||||
@@ -344,10 +345,11 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
configFileCreated = true;
|
||||
return this.fileService.updateContent(resource, content).then(() => true);
|
||||
}
|
||||
)).then(configFileCreated => {
|
||||
if (!configFileCreated) {
|
||||
)).then(errorFree => {
|
||||
if (!errorFree) {
|
||||
return false;
|
||||
}
|
||||
this.telemetryService.publicLog('debugConfigure');
|
||||
@@ -355,8 +357,9 @@ export class ConfigurationManager implements debug.IConfigurationManager {
|
||||
return this.editorService.openEditor({
|
||||
resource: resource,
|
||||
options: {
|
||||
forceOpen: true
|
||||
}
|
||||
forceOpen: true,
|
||||
pinned: configFileCreated // pin only if config file is created #8727
|
||||
},
|
||||
}, sideBySide).then(() => true);
|
||||
}, (error) => {
|
||||
throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error));
|
||||
|
||||
@@ -104,9 +104,7 @@ export class CombinedInstallAction extends Action {
|
||||
this.uninstallAction = instantiationService.createInstance(UninstallAction, extension);
|
||||
this.disposables.push(this.installAction, this.uninstallAction);
|
||||
|
||||
this.disposables.push(this.installAction.addListener2(Action.ENABLED, () => this.update()));
|
||||
this.disposables.push(this.installAction.addListener2(Action.LABEL, () => this.update()));
|
||||
this.disposables.push(this.uninstallAction.addListener2(Action.ENABLED, () => this.update()));
|
||||
this.installAction.onDidChange(this.update, this, this.disposables);
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,4 +41,8 @@ export class ExtensionsInput extends EditorInput {
|
||||
resolve(refresh?: boolean): TPromise<any> {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
supportsSplitEditor(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ export class RatingsWidget implements IDisposable {
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
const rating = this.extension.rating;
|
||||
const rating = Math.round(this.extension.rating * 2) / 2;
|
||||
this.container.innerHTML = '';
|
||||
|
||||
if (rating === null) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
.extension-editor > .header {
|
||||
display: flex;
|
||||
height: 130px;
|
||||
height: 128px;
|
||||
background: rgba(128, 128, 128, 0.15);
|
||||
padding: 20px;
|
||||
overflow: hidden;
|
||||
@@ -46,7 +46,6 @@
|
||||
font-size: 26px;
|
||||
line-height: 30px;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -102,7 +101,7 @@
|
||||
}
|
||||
|
||||
.extension-editor > .body {
|
||||
height: calc(100% - 170px);
|
||||
height: calc(100% - 168px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 9px 0 16px;
|
||||
padding: 0 11px 0 16px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
}
|
||||
@@ -80,9 +80,8 @@
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header > .install-count:not(:empty) {
|
||||
opacity: 0.6;
|
||||
font-size: 80%;
|
||||
margin-right: 6px;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header > .install-count > .octicon {
|
||||
|
||||
@@ -35,7 +35,6 @@ import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/edito
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
|
||||
|
||||
const LEGACY_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'editorViewState'; // TODO@Ben migration
|
||||
const TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'textEditorViewState';
|
||||
|
||||
interface ITextEditorViewState {
|
||||
@@ -297,12 +296,6 @@ export class TextFileEditor extends BaseTextEditor {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO@Ben migration
|
||||
const legacyEditorViewStateMemento = memento[LEGACY_EDITOR_VIEW_STATE_PREFERENCE_KEY];
|
||||
if (legacyEditorViewStateMemento) {
|
||||
return legacyEditorViewStateMemento[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ export class FileTracker implements IWorkbenchContribution {
|
||||
|
||||
private handleDelete(resource: URI): void {
|
||||
if (this.textFileService.isDirty(resource)) {
|
||||
return; // never dispose dirty resources
|
||||
return; // never dispose dirty resources from a delete
|
||||
}
|
||||
|
||||
// Add existing clients matching resource
|
||||
@@ -394,6 +394,9 @@ export class FileTracker implements IWorkbenchContribution {
|
||||
});
|
||||
|
||||
inputsContainingPath.forEach((input) => {
|
||||
if (input.isDirty()) {
|
||||
return; // never dispose dirty resources from a delete
|
||||
}
|
||||
|
||||
// Editor History
|
||||
this.historyService.remove(input);
|
||||
|
||||
@@ -252,6 +252,11 @@ configurationRegistry.registerConfiguration({
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('autoReveal', "Controls if the explorer should automatically reveal files when opening them."),
|
||||
'default': true
|
||||
},
|
||||
'explorer.enableDragAndDrop': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enableDragAndDrop', "Controls if the explorer should allow to move files and folders via drag and drop."),
|
||||
'default': true
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -21,6 +21,7 @@ import {InputBox} from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import {$} from 'vs/base/browser/builder';
|
||||
import platform = require('vs/base/common/platform');
|
||||
import glob = require('vs/base/common/glob');
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {ContributableActionProvider} from 'vs/workbench/browser/actionBarRegistry';
|
||||
import {LocalFileChangeEvent, IFilesConfiguration, ITextFileService} from 'vs/workbench/parts/files/common/files';
|
||||
import {IFileOperationResult, FileOperationResult, IFileStat, IFileService} from 'vs/platform/files/common/files';
|
||||
@@ -38,6 +39,7 @@ import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/edito
|
||||
import {IPartService} from 'vs/workbench/services/part/common/partService';
|
||||
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
|
||||
import {IWorkspace} from 'vs/platform/workspace/common/workspace';
|
||||
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
|
||||
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {IContextViewService, IContextMenuService} from 'vs/platform/contextview/browser/contextView';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
@@ -696,6 +698,8 @@ export class FileFilter implements IFilter {
|
||||
|
||||
// Explorer Drag And Drop Controller
|
||||
export class FileDragAndDrop implements IDragAndDrop {
|
||||
private toDispose: IDisposable[];
|
||||
private dropEnabled: boolean;
|
||||
|
||||
constructor(
|
||||
@IMessageService private messageService: IMessageService,
|
||||
@@ -703,9 +707,23 @@ export class FileDragAndDrop implements IDragAndDrop {
|
||||
@IEventService private eventService: IEventService,
|
||||
@IProgressService private progressService: IProgressService,
|
||||
@IFileService private fileService: IFileService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@ITextFileService private textFileService: ITextFileService
|
||||
) {
|
||||
this.toDispose = [];
|
||||
|
||||
this.onConfigurationUpdated(configurationService.getConfiguration<IFilesConfiguration>());
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(e.config)));
|
||||
}
|
||||
|
||||
private onConfigurationUpdated(config: IFilesConfiguration): void {
|
||||
this.dropEnabled = config && config.explorer && config.explorer.enableDragAndDrop;
|
||||
}
|
||||
|
||||
public getDragURI(tree: ITree, stat: FileStat): string {
|
||||
@@ -734,6 +752,10 @@ export class FileDragAndDrop implements IDragAndDrop {
|
||||
}
|
||||
|
||||
public onDragOver(tree: ITree, data: IDragAndDropData, target: FileStat, originalEvent: DragMouseEvent): IDragOverReaction {
|
||||
if (!this.dropEnabled) {
|
||||
return DRAG_OVER_REJECT;
|
||||
}
|
||||
|
||||
let isCopy = originalEvent && ((originalEvent.ctrlKey && !platform.isMacintosh) || (originalEvent.altKey && platform.isMacintosh));
|
||||
let fromDesktop = data instanceof DesktopDragAndDropData;
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ export interface IFilesConfiguration extends IFilesConfiguration, IWorkbenchEdit
|
||||
dynamicHeight: boolean;
|
||||
};
|
||||
autoReveal: boolean;
|
||||
enableDragAndDrop: boolean;
|
||||
};
|
||||
editor: IEditorOptions;
|
||||
}
|
||||
@@ -247,7 +248,7 @@ export enum AutoSaveMode {
|
||||
export var ITextFileService = createDecorator<ITextFileService>(TEXT_FILE_SERVICE_ID);
|
||||
|
||||
export interface IRawTextContent extends IBaseStat {
|
||||
|
||||
|
||||
/**
|
||||
* The line grouped content of a text file.
|
||||
*/
|
||||
|
||||
@@ -137,7 +137,7 @@ export class EmptyView extends EventEmitter.EventEmitter implements GitView.IVie
|
||||
}
|
||||
|
||||
public focus():void {
|
||||
// no-op
|
||||
this.initButton.focus();
|
||||
}
|
||||
|
||||
public layout(dimension:Builder.Dimension):void {
|
||||
|
||||
@@ -6,16 +6,19 @@
|
||||
import 'vs/css!../browser/media/output.contribution';
|
||||
import nls = require('vs/nls');
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import {CommonEditorRegistry, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry';
|
||||
import platform = require('vs/platform/platform');
|
||||
import {SyncActionDescriptor} from 'vs/platform/actions/common/actions';
|
||||
import {MenuId, SyncActionDescriptor} from 'vs/platform/actions/common/actions';
|
||||
import {registerSingleton} from 'vs/platform/instantiation/common/extensions';
|
||||
import {IWorkbenchActionRegistry, Extensions as ActionExtensions} from 'vs/workbench/common/actionRegistry';
|
||||
import {OutputService} from 'vs/workbench/parts/output/common/outputServices';
|
||||
import {ClearOutputEditorAction, ToggleOutputAction} from 'vs/workbench/parts/output/browser/outputActions';
|
||||
import {ToggleOutputAction} from 'vs/workbench/parts/output/browser/outputActions';
|
||||
import {OUTPUT_MIME, OUTPUT_MODE_ID, OUTPUT_PANEL_ID, IOutputService} from 'vs/workbench/parts/output/common/output';
|
||||
import panel = require('vs/workbench/browser/panel');
|
||||
import {KEYBINDING_CONTEXT_EDITOR_FOCUS, KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID} from 'vs/editor/common/editorCommon';
|
||||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {KbExpr} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {MenuRegistry} from 'vs/platform/actions/browser/menuService';
|
||||
|
||||
// Register Service
|
||||
registerSingleton(IOutputService, OutputService);
|
||||
@@ -44,9 +47,32 @@ let actionRegistry = <IWorkbenchActionRegistry>platform.Registry.as(ActionExtens
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleOutputAction, ToggleOutputAction.ID, ToggleOutputAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_U,
|
||||
linux: {
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H // On Ubuntu Ctrl+Shift+U is taken by some global OS command
|
||||
primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_H) // On Ubuntu Ctrl+Shift+U is taken by some global OS command
|
||||
}
|
||||
}), 'View: Toggle Output', nls.localize('viewCategory', "View"));
|
||||
|
||||
// Contribute to Context Menu of Output Window
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ClearOutputEditorAction, ClearOutputEditorAction.ID, nls.localize('clearOutput.label', "Clear Output"), void 0, 'Clear Output'));
|
||||
|
||||
// Define clear command, contribute to editor context menu
|
||||
{
|
||||
const id = 'editor.action.clearoutput';
|
||||
|
||||
KeybindingsRegistry.registerCommandDesc({
|
||||
id,
|
||||
primary: null,
|
||||
weight: KeybindingsRegistry.WEIGHT.editorContrib(),
|
||||
when: KbExpr.has(KEYBINDING_CONTEXT_EDITOR_FOCUS),
|
||||
handler(accessor) {
|
||||
accessor.get(IOutputService).getActiveChannel().clear();
|
||||
}
|
||||
});
|
||||
|
||||
MenuRegistry.addCommand({
|
||||
id,
|
||||
title: nls.localize('clearOutput.label', "Clear Output")
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
|
||||
command: MenuRegistry.getCommand(id),
|
||||
when: KbExpr.equals(KEYBINDING_CONTEXT_EDITOR_LANGUAGE_ID, OUTPUT_MODE_ID)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@ import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import {Registry} from 'vs/platform/platform';
|
||||
import {IAction, Action} from 'vs/base/common/actions';
|
||||
import {EditorAction} from 'vs/editor/common/editorAction';
|
||||
import {Behaviour} from 'vs/editor/common/editorActionEnablement';
|
||||
import {ICommonCodeEditor, IEditorActionDescriptorData} from 'vs/editor/common/editorCommon';
|
||||
import {IOutputChannelRegistry, Extensions, IOutputService, OUTPUT_MODE_ID, OUTPUT_PANEL_ID} from 'vs/workbench/parts/output/common/output';
|
||||
import {IOutputChannelRegistry, Extensions, IOutputService, OUTPUT_PANEL_ID} from 'vs/workbench/parts/output/common/output';
|
||||
import {SelectActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import {IPartService} from 'vs/workbench/services/part/common/partService';
|
||||
import {IPanelService} from 'vs/workbench/services/panel/common/panelService';
|
||||
@@ -59,35 +56,6 @@ export class ClearOutputAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class ClearOutputEditorAction extends EditorAction {
|
||||
|
||||
public static ID = 'editor.action.clearoutput';
|
||||
|
||||
constructor(
|
||||
descriptor: IEditorActionDescriptorData,
|
||||
editor: ICommonCodeEditor,
|
||||
@IOutputService private outputService: IOutputService
|
||||
) {
|
||||
super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.ShowInContextMenu);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
return 'clear';
|
||||
}
|
||||
|
||||
public isSupported(): boolean {
|
||||
let model = this.editor.getModel();
|
||||
let mode = model && model.getMode();
|
||||
|
||||
return mode && mode.getId() === OUTPUT_MODE_ID && super.isSupported();
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
this.outputService.getActiveChannel().clear();
|
||||
return TPromise.as(false);
|
||||
}
|
||||
}
|
||||
|
||||
export class SwitchOutputAction extends Action {
|
||||
|
||||
public static ID = 'workbench.output.action.switchBetweenOutputs';
|
||||
|
||||
@@ -67,7 +67,13 @@ class BaseCommandEntry extends QuickOpenEntryGroup {
|
||||
this.keyLabel = keyLabel;
|
||||
this.keyAriaLabel = keyAriaLabel;
|
||||
this.label = label;
|
||||
this.alias = alias;
|
||||
|
||||
if (label !== alias) {
|
||||
this.alias = alias;
|
||||
} else {
|
||||
aliasHighlights = null;
|
||||
}
|
||||
|
||||
this.setHighlights(labelHighlights, null, aliasHighlights);
|
||||
}
|
||||
|
||||
|
||||
@@ -202,6 +202,7 @@ class ConfigureTaskRunnerAction extends Action {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
let sideBySide = !!(event && (event.ctrlKey || event.metaKey));
|
||||
let configFileCreated = false;
|
||||
return this.fileService.resolveFile(this.contextService.toResource('.vscode/tasks.json')).then((success) => {
|
||||
return success;
|
||||
}, (err:any) => {
|
||||
@@ -247,6 +248,7 @@ class ConfigureTaskRunnerAction extends Action {
|
||||
if (editorConfig.editor.insertSpaces) {
|
||||
content = content.replace(/(\n)(\t+)/g, (_, s1, s2) => s1 + strings.repeat(' ', s2.length * editorConfig.editor.tabSize));
|
||||
}
|
||||
configFileCreated = true;
|
||||
return this.fileService.createFile(this.contextService.toResource('.vscode/tasks.json'), content);
|
||||
});
|
||||
});
|
||||
@@ -258,7 +260,8 @@ class ConfigureTaskRunnerAction extends Action {
|
||||
return this.editorService.openEditor({
|
||||
resource: stat.resource,
|
||||
options: {
|
||||
forceOpen: true
|
||||
forceOpen: true,
|
||||
pinned: configFileCreated // pin only if config file is created #8727
|
||||
}
|
||||
}, sideBySide);
|
||||
}, (error) => {
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import lifecycle = require('vs/base/common/lifecycle');
|
||||
import nls = require('vs/nls');
|
||||
import platform = require('vs/base/common/platform');
|
||||
import xterm = require('xterm');
|
||||
import {Dimension} from 'vs/base/browser/builder';
|
||||
import {IMessageService, Severity} from 'vs/platform/message/common/message';
|
||||
import {ITerminalFont} from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper';
|
||||
import {ITerminalProcess, ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/terminal';
|
||||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
@@ -26,6 +28,7 @@ export class TerminalInstance {
|
||||
private parentDomElement: HTMLElement,
|
||||
private contextService: IWorkspaceContextService,
|
||||
private terminalService: ITerminalService,
|
||||
private messageService: IMessageService,
|
||||
private onExitCallback: (TerminalInstance) => void
|
||||
) {
|
||||
this.toDispose = [];
|
||||
@@ -52,7 +55,7 @@ export class TerminalInstance {
|
||||
this.isExiting = true;
|
||||
this.dispose();
|
||||
if (exitCode) {
|
||||
console.error('Integrated terminal exited with code ' + exitCode);
|
||||
this.messageService.show(Severity.Error, nls.localize('terminal.integrated.exitedWithCode', 'The terminal process terminated with exit code: {0}', exitCode));
|
||||
}
|
||||
this.onExitCallback(this);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {KillTerminalAction, CreateNewTerminalAction, SwitchTerminalInstanceActio
|
||||
import {IActionItem} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IMessageService} from 'vs/platform/message/common/message';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {ITerminalProcess, ITerminalService, TERMINAL_PANEL_ID} from 'vs/workbench/parts/terminal/electron-browser/terminal';
|
||||
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
|
||||
@@ -38,7 +39,8 @@ export class TerminalPanel extends Panel {
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@ITerminalService private terminalService: ITerminalService,
|
||||
@IThemeService private themeService: IThemeService
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IMessageService private messageService: IMessageService
|
||||
) {
|
||||
super(TERMINAL_PANEL_ID, telemetryService);
|
||||
}
|
||||
@@ -128,7 +130,7 @@ export class TerminalPanel extends Panel {
|
||||
|
||||
private createTerminal(terminalProcess: ITerminalProcess): TPromise<TerminalInstance> {
|
||||
return new TPromise<TerminalInstance>(resolve => {
|
||||
var terminalInstance = new TerminalInstance(terminalProcess, this.terminalContainer, this.contextService, this.terminalService, this.onTerminalInstanceExit.bind(this));
|
||||
var terminalInstance = new TerminalInstance(terminalProcess, this.terminalContainer, this.contextService, this.terminalService, this.messageService, this.onTerminalInstanceExit.bind(this));
|
||||
this.terminalInstances.push(terminalInstance);
|
||||
this.setActiveTerminal(this.terminalInstances.length - 1);
|
||||
this.toDispose.push(this.themeService.onDidThemeChange(this.updateTheme.bind(this)));
|
||||
|
||||
@@ -626,21 +626,6 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic
|
||||
let entriesRaw = this.storageService.get(HistoryService.STORAGE_KEY, StorageScope.WORKSPACE);
|
||||
if (entriesRaw) {
|
||||
entries = JSON.parse(entriesRaw);
|
||||
} else {
|
||||
// TODO@Ben migration
|
||||
try {
|
||||
const oldMementoRaw = this.storageService.get('memento/workbench.component.quickopen', StorageScope.WORKSPACE);
|
||||
if (oldMementoRaw) {
|
||||
const oldMemento = JSON.parse(oldMementoRaw);
|
||||
const oldEntries = oldMemento['quickopen.editorhistory'].entries;
|
||||
|
||||
if (oldEntries) {
|
||||
entries = oldEntries;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
this.history = entries.map(entry => {
|
||||
|
||||
Reference in New Issue
Block a user