simpleServices.ts 14.0 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

J
Johannes Rieken 已提交
7
import { Schemas } from 'vs/base/common/network';
E
Erich Gamma 已提交
8
import Severity from 'vs/base/common/severity';
9
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
10
import { TPromise } from 'vs/base/common/winjs.base';
B
Benjamin Pasero 已提交
11
import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, getConfigurationValue, IConfigurationKeys } from 'vs/platform/configuration/common/configuration';
J
Joao Moreno 已提交
12
import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, Position } from 'vs/platform/editor/common/editor';
13
import { ICommandService, ICommand, ICommandEvent, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
A
Alex Dima 已提交
14
import { USLayoutResolvedKeybinding, AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
15
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
16
import { IKeybindingEvent, IKeybindingItem, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
17
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
J
Johannes Rieken 已提交
18
import { IConfirmation, IMessageService } from 'vs/platform/message/common/message';
A
Alex Dima 已提交
19
import * as editorCommon from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
20 21 22 23 24 25
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { Selection } from 'vs/editor/common/core/selection';
import Event, { Emitter } from 'vs/base/common/event';
import { getDefaultValues as getDefaultConfiguration } from 'vs/platform/configuration/common/model';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress';
J
Joao Moreno 已提交
26
import { ITextModelResolverService, ITextModelContentProvider, ITextEditorModel } from 'vs/editor/common/services/resolverService';
27
import { IDisposable, IReference, ImmortalReference, combinedDisposable } from 'vs/base/common/lifecycle';
28 29
import * as dom from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
30
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
31
import { MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions';
A
Alex Dima 已提交
32
import { Menu } from 'vs/platform/actions/common/menu';
33
import { ITelemetryService, ITelemetryExperiments, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
34
import { ResolvedKeybinding, Keybinding } from 'vs/base/common/keyCodes';
35
import { NormalizedKeybindingItem } from 'vs/platform/keybinding/common/normalizedKeybindingItem';
A
Alex Dima 已提交
36
import { OS } from 'vs/base/common/platform';
E
Erich Gamma 已提交
37 38 39

export class SimpleEditor implements IEditor {

J
Johannes Rieken 已提交
40 41 42
	public input: IEditorInput;
	public options: IEditorOptions;
	public position: Position;
E
Erich Gamma 已提交
43

J
Johannes Rieken 已提交
44
	public _widget: editorCommon.IEditor;
E
Erich Gamma 已提交
45

J
Johannes Rieken 已提交
46
	constructor(editor: editorCommon.IEditor) {
E
Erich Gamma 已提交
47 48 49
		this._widget = editor;
	}

J
Johannes Rieken 已提交
50 51 52 53 54
	public getId(): string { return 'editor'; }
	public getControl(): editorCommon.IEditor { return this._widget; }
	public getSelection(): Selection { return this._widget.getSelection(); }
	public focus(): void { this._widget.focus(); }
	public isVisible(): boolean { return true; }
E
Erich Gamma 已提交
55

J
Johannes Rieken 已提交
56
	public withTypedEditor<T>(codeEditorCallback: (editor: ICodeEditor) => T, diffEditorCallback: (editor: IDiffEditor) => T): T {
A
Alex Dima 已提交
57
		if (this._widget.getEditorType() === editorCommon.EditorType.ICodeEditor) {
E
Erich Gamma 已提交
58
			// Single Editor
A
Alex Dima 已提交
59
			return codeEditorCallback(<ICodeEditor>this._widget);
E
Erich Gamma 已提交
60 61
		} else {
			// Diff Editor
A
Alex Dima 已提交
62
			return diffEditorCallback(<IDiffEditor>this._widget);
E
Erich Gamma 已提交
63 64 65 66
		}
	}
}

J
Johannes Rieken 已提交
67
export class SimpleModel implements ITextEditorModel {
E
Erich Gamma 已提交
68

J
Johannes Rieken 已提交
69
	private model: editorCommon.IModel;
70
	private _onDispose: Emitter<void>;
E
Erich Gamma 已提交
71

J
Johannes Rieken 已提交
72
	constructor(model: editorCommon.IModel) {
E
Erich Gamma 已提交
73
		this.model = model;
74 75 76 77 78
		this._onDispose = new Emitter<void>();
	}

	public get onDispose(): Event<void> {
		return this._onDispose.event;
E
Erich Gamma 已提交
79 80
	}

81 82 83 84
	public load(): TPromise<SimpleModel> {
		return TPromise.as(this);
	}

J
Johannes Rieken 已提交
85
	public get textEditorModel(): editorCommon.IModel {
E
Erich Gamma 已提交
86 87
		return this.model;
	}
88 89 90 91

	public dispose(): void {
		this._onDispose.fire();
	}
E
Erich Gamma 已提交
92 93 94
}

export interface IOpenEditorDelegate {
J
Johannes Rieken 已提交
95
	(url: string): boolean;
E
Erich Gamma 已提交
96 97 98
}

export class SimpleEditorService implements IEditorService {
99
	public _serviceBrand: any;
E
Erich Gamma 已提交
100

J
Johannes Rieken 已提交
101 102
	private editor: SimpleEditor;
	private openEditorDelegate: IOpenEditorDelegate;
E
Erich Gamma 已提交
103 104 105 106 107

	constructor() {
		this.openEditorDelegate = null;
	}

J
Johannes Rieken 已提交
108
	public setEditor(editor: editorCommon.IEditor): void {
E
Erich Gamma 已提交
109 110 111
		this.editor = new SimpleEditor(editor);
	}

J
Johannes Rieken 已提交
112
	public setOpenEditorDelegate(openEditorDelegate: IOpenEditorDelegate): void {
E
Erich Gamma 已提交
113 114 115
		this.openEditorDelegate = openEditorDelegate;
	}

J
Johannes Rieken 已提交
116
	public openEditor(typedData: IResourceInput, sideBySide?: boolean): TPromise<IEditor> {
E
Erich Gamma 已提交
117 118 119 120 121 122 123 124 125
		return TPromise.as(this.editor.withTypedEditor(
			(editor) => this.doOpenEditor(editor, typedData),
			(diffEditor) => (
				this.doOpenEditor(diffEditor.getOriginalEditor(), typedData) ||
				this.doOpenEditor(diffEditor.getModifiedEditor(), typedData)
			)
		));
	}

J
Johannes Rieken 已提交
126
	private doOpenEditor(editor: editorCommon.ICommonCodeEditor, data: IResourceInput): IEditor {
A
Alex Dima 已提交
127
		let model = this.findModel(editor, data);
E
Erich Gamma 已提交
128 129 130 131 132 133
		if (!model) {
			if (data.resource) {
				if (this.openEditorDelegate) {
					this.openEditorDelegate(data.resource.toString());
					return null;
				} else {
A
Alex Dima 已提交
134
					let schema = data.resource.scheme;
A
Alex Dima 已提交
135
					if (schema === Schemas.http || schema === Schemas.https) {
E
Erich Gamma 已提交
136 137 138 139 140 141 142 143 144
						// This is a fully qualified http or https URL
						window.open(data.resource.toString());
						return this.editor;
					}
				}
			}
			return null;
		}

A
Alex Dima 已提交
145
		let selection = <editorCommon.IRange>data.options.selection;
E
Erich Gamma 已提交
146 147 148
		if (selection) {
			if (typeof selection.endLineNumber === 'number' && typeof selection.endColumn === 'number') {
				editor.setSelection(selection);
A
Alex Dima 已提交
149
				editor.revealRangeInCenter(selection);
E
Erich Gamma 已提交
150
			} else {
A
Alex Dima 已提交
151
				let pos = {
E
Erich Gamma 已提交
152 153 154 155 156 157 158 159 160 161 162
					lineNumber: selection.startLineNumber,
					column: selection.startColumn
				};
				editor.setPosition(pos);
				editor.revealPositionInCenter(pos);
			}
		}

		return this.editor;
	}

J
Johannes Rieken 已提交
163
	private findModel(editor: editorCommon.ICommonCodeEditor, data: IResourceInput): editorCommon.IModel {
A
Alex Dima 已提交
164
		let model = editor.getModel();
J
Johannes Rieken 已提交
165
		if (model.uri.toString() !== data.resource.toString()) {
E
Erich Gamma 已提交
166 167 168 169 170 171 172
			return null;
		}

		return model;
	}
}

173 174 175 176 177 178 179 180 181
export class SimpleEditorModelResolverService implements ITextModelResolverService {
	public _serviceBrand: any;

	private editor: SimpleEditor;

	public setEditor(editor: editorCommon.IEditor): void {
		this.editor = new SimpleEditor(editor);
	}

J
Joao Moreno 已提交
182
	public createModelReference(resource: URI): TPromise<IReference<ITextEditorModel>> {
183 184 185 186 187 188 189 190
		let model: editorCommon.IModel;

		model = this.editor.withTypedEditor(
			(editor) => this.findModel(editor, resource),
			(diffEditor) => this.findModel(diffEditor.getOriginalEditor(), resource) || this.findModel(diffEditor.getModifiedEditor(), resource)
		);

		if (!model) {
J
Joao Moreno 已提交
191
			return TPromise.as(new ImmortalReference(null));
192 193
		}

J
Joao Moreno 已提交
194
		return TPromise.as(new ImmortalReference(new SimpleModel(model)));
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
	}

	public registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable {
		return {
			dispose: function () { /* no op */ }
		};
	}

	private findModel(editor: editorCommon.ICommonCodeEditor, resource: URI): editorCommon.IModel {
		let model = editor.getModel();
		if (model.uri.toString() !== resource.toString()) {
			return null;
		}

		return model;
	}
}

213 214 215
export class SimpleProgressService implements IProgressService {
	_serviceBrand: any;

J
Johannes Rieken 已提交
216 217 218 219
	private static NULL_PROGRESS_RUNNER: IProgressRunner = {
		done: () => { },
		total: () => { },
		worked: () => { }
220 221 222 223 224 225 226 227 228 229 230 231 232
	};

	show(infinite: boolean, delay?: number): IProgressRunner;
	show(total: number, delay?: number): IProgressRunner;
	show(): IProgressRunner {
		return SimpleProgressService.NULL_PROGRESS_RUNNER;
	}

	showWhile(promise: TPromise<any>, delay?: number): TPromise<void> {
		return null;
	}
}

E
Erich Gamma 已提交
233
export class SimpleMessageService implements IMessageService {
234
	public _serviceBrand: any;
E
Erich Gamma 已提交
235

J
Johannes Rieken 已提交
236
	private static Empty = function () { /* nothing */ };
E
Erich Gamma 已提交
237

J
Johannes Rieken 已提交
238
	public show(sev: Severity, message: any): () => void {
E
Erich Gamma 已提交
239

J
Johannes Rieken 已提交
240
		switch (sev) {
E
Erich Gamma 已提交
241
			case Severity.Error:
242
				console.error(message);
E
Erich Gamma 已提交
243 244 245 246 247 248 249 250 251 252 253 254
				break;
			case Severity.Warning:
				console.warn(message);
				break;
			default:
				console.log(message);
				break;
		}

		return SimpleMessageService.Empty;
	}

J
Johannes Rieken 已提交
255
	public hideAll(): void {
E
Erich Gamma 已提交
256 257 258
		// No-op
	}

J
Johannes Rieken 已提交
259
	public confirm(confirmation: IConfirmation): boolean {
A
Alex Dima 已提交
260
		let messageText = confirmation.message;
E
Erich Gamma 已提交
261 262 263 264 265 266
		if (confirmation.detail) {
			messageText = messageText + '\n\n' + confirmation.detail;
		}

		return window.confirm(messageText);
	}
A
Alex Dima 已提交
267 268
}

A
Alex Dima 已提交
269 270
export class StandaloneCommandService implements ICommandService {
	_serviceBrand: any;
271

A
Alex Dima 已提交
272
	private readonly _instantiationService: IInstantiationService;
273 274
	private _dynamicCommands: { [id: string]: ICommand; };

275 276 277
	private _onWillExecuteCommand: Emitter<ICommandEvent> = new Emitter<ICommandEvent>();
	public readonly onWillExecuteCommand: Event<ICommandEvent> = this._onWillExecuteCommand.event;

A
Alex Dima 已提交
278 279
	constructor(instantiationService: IInstantiationService) {
		this._instantiationService = instantiationService;
280 281 282
		this._dynamicCommands = Object.create(null);
	}

283
	public addCommand(id: string, command: ICommand): IDisposable {
284
		this._dynamicCommands[id] = command;
285 286 287 288 289
		return {
			dispose: () => {
				delete this._dynamicCommands[id];
			}
		};
290 291
	}

A
Alex Dima 已提交
292 293 294 295 296 297 298
	public executeCommand<T>(id: string, ...args: any[]): TPromise<T> {
		const command = (CommandsRegistry.getCommand(id) || this._dynamicCommands[id]);
		if (!command) {
			return TPromise.wrapError(new Error(`command '${id}' not found`));
		}

		try {
299
			this._onWillExecuteCommand.fire({ commandId: id });
A
Alex Dima 已提交
300 301 302 303 304
			const result = this._instantiationService.invokeFunction.apply(this._instantiationService, [command.handler].concat(args));
			return TPromise.as(result);
		} catch (err) {
			return TPromise.wrapError(err);
		}
305 306 307
	}
}

308 309
export class StandaloneKeybindingService extends AbstractKeybindingService {
	private _cachedResolver: KeybindingResolver;
E
Erich Gamma 已提交
310 311
	private _dynamicKeybindings: IKeybindingItem[];

A
Alex Dima 已提交
312
	constructor(
313
		contextKeyService: IContextKeyService,
A
Alex Dima 已提交
314 315 316 317
		commandService: ICommandService,
		messageService: IMessageService,
		domNode: HTMLElement
	) {
318
		super(contextKeyService, commandService, messageService);
319

320
		this._cachedResolver = null;
E
Erich Gamma 已提交
321
		this._dynamicKeybindings = [];
322

323 324 325 326 327 328 329
		this.toDispose.push(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
			let keyEvent = new StandardKeyboardEvent(e);
			let shouldPreventDefault = this._dispatch(keyEvent.toKeybinding(), keyEvent.target);
			if (shouldPreventDefault) {
				keyEvent.preventDefault();
			}
		}));
E
Erich Gamma 已提交
330 331
	}

332
	public addDynamicKeybinding(commandId: string, keybinding: number, handler: ICommandHandler, when: ContextKeyExpr): IDisposable {
333 334
		let toDispose: IDisposable[] = [];

E
Erich Gamma 已提交
335 336 337
		this._dynamicKeybindings.push({
			keybinding: keybinding,
			command: commandId,
338
			when: when,
E
Erich Gamma 已提交
339 340 341
			weight1: 1000,
			weight2: 0
		});
342

343 344 345 346 347 348 349 350 351 352 353 354 355
		toDispose.push({
			dispose: () => {
				for (let i = 0; i < this._dynamicKeybindings.length; i++) {
					let kb = this._dynamicKeybindings[i];
					if (kb.command === commandId) {
						this._dynamicKeybindings.splice(i, 1);
						this.updateResolver({ source: KeybindingSource.Default });
						return;
					}
				}
			}
		});

356 357
		let commandService = this._commandService;
		if (commandService instanceof StandaloneCommandService) {
358
			toDispose.push(commandService.addCommand(commandId, {
359
				handler: handler
360
			}));
361 362 363
		} else {
			throw new Error('Unknown command service!');
		}
C
Christof Marti 已提交
364
		this.updateResolver({ source: KeybindingSource.Default });
365

366
		return combinedDisposable(toDispose);
E
Erich Gamma 已提交
367 368
	}

369 370 371 372 373 374 375
	private updateResolver(event: IKeybindingEvent): void {
		this._cachedResolver = null;
		this._onDidUpdateKeybindings.fire(event);
	}

	protected _getResolver(): KeybindingResolver {
		if (!this._cachedResolver) {
376 377 378
			const defaults = KeybindingsRegistry.getDefaultKeybindings().map(k => NormalizedKeybindingItem.fromKeybindingItem(k, true));
			const overrides = this._dynamicKeybindings.map(k => NormalizedKeybindingItem.fromKeybindingItem(k, false));
			this._cachedResolver = new KeybindingResolver(defaults, overrides);
379 380 381 382
		}
		return this._cachedResolver;
	}

A
Alex Dima 已提交
383
	protected _createResolvedKeybinding(kb: Keybinding): ResolvedKeybinding {
A
Alex Dima 已提交
384
		return new USLayoutResolvedKeybinding(kb, OS);
A
Alex Dima 已提交
385 386
	}

E
Erich Gamma 已提交
387 388
}

389
export class SimpleConfigurationService implements IConfigurationService {
390

391 392
	_serviceBrand: any;

393 394
	private _onDidUpdateConfiguration = new Emitter<IConfigurationServiceEvent>();
	public onDidUpdateConfiguration: Event<IConfigurationServiceEvent> = this._onDidUpdateConfiguration.event;
395

396
	private _config: any;
397

398 399
	constructor() {
		this._config = getDefaultConfiguration();
400 401
	}

402
	public getConfiguration<T>(section?: any): T {
403
		return this._config;
404 405
	}

406
	public reloadConfiguration<T>(section?: string): TPromise<T> {
407
		return TPromise.as(this.getConfiguration(section));
408
	}
B
Benjamin Pasero 已提交
409 410 411 412 413 414 415 416

	public lookup<C>(key: string): IConfigurationValue<C> {
		return {
			value: getConfigurationValue<C>(this.getConfiguration(), key),
			default: getConfigurationValue<C>(this.getConfiguration(), key),
			user: getConfigurationValue<C>(this.getConfiguration(), key)
		};
	}
B
Benjamin Pasero 已提交
417 418 419 420

	public keys(): IConfigurationKeys {
		return { default: [], user: [] };
	}
421
}
A
Alex Dima 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436

export class SimpleMenuService implements IMenuService {

	_serviceBrand: any;

	private readonly _commandService: ICommandService;

	constructor(commandService: ICommandService) {
		this._commandService = commandService;
	}

	public createMenu(id: MenuId, contextKeyService: IContextKeyService): IMenu {
		return new Menu(id, TPromise.as(true), this._commandService, contextKeyService);
	}
}
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454

export class StandaloneTelemetryService implements ITelemetryService {
	_serviceBrand: void;

	public isOptedIn = false;

	public publicLog(eventName: string, data?: any): TPromise<void> {
		return TPromise.as<void>(null);
	}

	public getTelemetryInfo(): TPromise<ITelemetryInfo> {
		return null;
	}

	public getExperiments(): ITelemetryExperiments {
		return null;
	}
}