standaloneEditor.ts 14.3 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';

7
import 'vs/css!./standalone-tokens';
A
Alex Dima 已提交
8
import * as editorCommon from 'vs/editor/common/editorCommon';
A
Alex Dima 已提交
9
import { ICodeEditor, ContentWidgetPositionPreference, OverlayWidgetPositionPreference, MouseTargetType } from 'vs/editor/browser/editorBrowser';
10
import { StandaloneEditor, IStandaloneCodeEditor, StandaloneDiffEditor, IStandaloneDiffEditor, IEditorConstructionOptions, IDiffEditorConstructionOptions } from 'vs/editor/standalone/browser/standaloneCodeEditor';
J
Johannes Rieken 已提交
11
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
12
import { IEditorOverrideServices, DynamicStandaloneServices, StaticServices } from 'vs/editor/standalone/browser/standaloneServices';
J
Johannes Rieken 已提交
13
import { IDisposable } from 'vs/base/common/lifecycle';
14
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
15 16 17
import { TPromise } from 'vs/base/common/winjs.base';
import { OpenerService } from 'vs/platform/opener/browser/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
18 19
import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer';
import { SimpleEditorService, SimpleEditorModelResolverService } from 'vs/editor/standalone/browser/simpleServices';
20
import * as modes from 'vs/editor/common/modes';
J
Johannes Rieken 已提交
21
import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from 'vs/editor/common/services/webWorker';
R
rsafronov 已提交
22
import { IMarkerData, IMarker } from 'vs/platform/markers/common/markers';
23
import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
J
Johannes Rieken 已提交
24 25 26 27 28 29
import { IEditorService } from 'vs/platform/editor/common/editor';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
30
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
J
Johannes Rieken 已提交
31
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
32
import { ITextModelService } from 'vs/editor/common/services/resolverService';
A
Alex Dima 已提交
33
import { NULL_STATE, nullTokenize } from 'vs/editor/common/modes/nullMode';
34
import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
A
Alex Dima 已提交
35
import { Token } from 'vs/editor/common/core/token';
36
import { FontInfo, BareFontInfo } from 'vs/editor/common/config/fontInfo';
37 38
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
A
Alex Dima 已提交
39
import { ITextModel, OverviewRulerLane, EndOfLinePreference, DefaultEndOfLine, EndOfLineSequence, TrackedRangeStickiness, TextModelResolvedOptions, FindMatch } from 'vs/editor/common/model';
40
import { INotificationService } from 'vs/platform/notification/common/notification';
41

J
Johannes Rieken 已提交
42
function withAllStandaloneServices<T extends editorCommon.IEditor>(domElement: HTMLElement, override: IEditorOverrideServices, callback: (services: DynamicStandaloneServices) => T): T {
43 44 45 46 47 48 49
	let services = new DynamicStandaloneServices(domElement, override);

	// The editorService is a lovely beast. It needs to point back to the code editor instance...
	let simpleEditorService: SimpleEditorService = null;
	if (!services.has(IEditorService)) {
		simpleEditorService = new SimpleEditorService();
		services.set(IEditorService, simpleEditorService);
50 51
	}

52
	let simpleEditorModelResolverService: SimpleEditorModelResolverService = null;
53
	if (!services.has(ITextModelService)) {
54
		simpleEditorModelResolverService = new SimpleEditorModelResolverService();
55
		services.set(ITextModelService, simpleEditorModelResolverService);
56 57
	}

58 59
	if (!services.has(IOpenerService)) {
		services.set(IOpenerService, new OpenerService(services.get(IEditorService), services.get(ICommandService)));
60 61
	}

62
	let result = callback(services);
63

64 65
	if (simpleEditorService) {
		simpleEditorService.setEditor(result);
66 67
	}

68 69 70 71
	if (simpleEditorModelResolverService) {
		simpleEditorModelResolverService.setEditor(result);
	}

72 73 74
	return result;
}

A
Alex Dima 已提交
75
/**
76
 * Create a new editor under `domElement`.
A
Alex Dima 已提交
77 78 79
 * `domElement` should be empty (not contain other dom nodes).
 * The editor will read the size of `domElement`.
 */
J
Johannes Rieken 已提交
80
export function create(domElement: HTMLElement, options?: IEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor {
81 82 83 84 85 86 87 88 89 90
	return withAllStandaloneServices(domElement, override, (services) => {
		return new StandaloneEditor(
			domElement,
			options,
			services,
			services.get(IInstantiationService),
			services.get(ICodeEditorService),
			services.get(ICommandService),
			services.get(IContextKeyService),
			services.get(IKeybindingService),
A
Alex Dima 已提交
91
			services.get(IContextViewService),
92
			services.get(IStandaloneThemeService)
93 94 95
		);
	});
}
96

97 98 99 100 101 102 103 104 105 106 107
/**
 * Emitted when an editor is created.
 * Creating a diff editor might cause this listener to be invoked with the two editors.
 * @event
 */
export function onDidCreateEditor(listener: (codeEditor: ICodeEditor) => void): IDisposable {
	return StaticServices.codeEditorService.get().onCodeEditorAdd((editor) => {
		listener(<ICodeEditor>editor);
	});
}

108 109 110 111 112
/**
 * Create a new diff editor under `domElement`.
 * `domElement` should be empty (not contain other dom nodes).
 * The editor will read the size of `domElement`.
 */
J
Johannes Rieken 已提交
113
export function createDiffEditor(domElement: HTMLElement, options?: IDiffEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneDiffEditor {
114 115 116 117 118 119 120 121 122
	return withAllStandaloneServices(domElement, override, (services) => {
		return new StandaloneDiffEditor(
			domElement,
			options,
			services,
			services.get(IInstantiationService),
			services.get(IContextKeyService),
			services.get(IKeybindingService),
			services.get(IContextViewService),
123
			services.get(IEditorWorkerService),
124
			services.get(ICodeEditorService),
125
			services.get(IStandaloneThemeService),
126
			services.get(INotificationService)
127 128
		);
	});
129 130
}

A
Alex Dima 已提交
131
export interface IDiffNavigator {
J
Johannes Rieken 已提交
132 133 134 135
	canNavigate(): boolean;
	next(): void;
	previous(): void;
	dispose(): void;
A
Alex Dima 已提交
136 137 138
}

export interface IDiffNavigatorOptions {
139 140 141
	readonly followsCaret?: boolean;
	readonly ignoreCharChanges?: boolean;
	readonly alwaysRevealFirst?: boolean;
A
Alex Dima 已提交
142 143
}

J
Johannes Rieken 已提交
144
export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: IDiffNavigatorOptions): IDiffNavigator {
A
Alex Dima 已提交
145 146 147
	return new DiffNavigator(diffEditor, opts);
}

A
Alex Dima 已提交
148
function doCreateModel(value: string, mode: TPromise<modes.IMode>, uri?: URI): ITextModel {
149
	return StaticServices.modelService.get().createModel(value, mode, uri);
150 151
}

A
Alex Dima 已提交
152 153 154 155
/**
 * Create a new editor model.
 * You can specify the language that should be set for this model or let the language be inferred from the `uri`.
 */
A
Alex Dima 已提交
156
export function createModel(value: string, language?: string, uri?: URI): ITextModel {
A
Alex Dima 已提交
157
	value = value || '';
158

A
Alex Dima 已提交
159 160 161 162 163 164 165 166 167
	if (!language) {
		let path = uri ? uri.path : null;

		let firstLF = value.indexOf('\n');
		let firstLine = value;
		if (firstLF !== -1) {
			firstLine = value.substring(0, firstLF);
		}

168
		return doCreateModel(value, StaticServices.modeService.get().getOrCreateModeByFilenameOrFirstLine(path, firstLine), uri);
169
	}
170
	return doCreateModel(value, StaticServices.modeService.get().getOrCreateMode(language), uri);
A
Alex Dima 已提交
171 172
}

A
Alex Dima 已提交
173 174 175
/**
 * Change the language for a model.
 */
A
Alex Dima 已提交
176
export function setModelLanguage(model: ITextModel, language: string): void {
177
	StaticServices.modelService.get().setMode(model, StaticServices.modeService.get().getOrCreateMode(language));
178 179
}

A
Alex Dima 已提交
180 181 182
/**
 * Set the markers for a model.
 */
A
Alex Dima 已提交
183
export function setModelMarkers(model: ITextModel, owner: string, markers: IMarkerData[]): void {
184 185 186
	if (model) {
		StaticServices.markerService.get().changeOne(owner, model.uri, markers);
	}
187 188
}

R
Roman Safronov 已提交
189
/**
R
rebornix 已提交
190
 * Get markers for owner and/or resource
R
rebornix 已提交
191
 * @returns {IMarker[]} list of markers
R
Roman Safronov 已提交
192 193
 * @param filter
 */
R
rsafronov 已提交
194
export function getModelMarkers(filter: { owner?: string, resource?: URI, take?: number }): IMarker[] {
R
Roman Safronov 已提交
195 196 197
	return StaticServices.markerService.get().read(filter);
}

A
Alex Dima 已提交
198 199 200
/**
 * Get the model that has `uri` if it exists.
 */
A
Alex Dima 已提交
201
export function getModel(uri: URI): ITextModel {
202
	return StaticServices.modelService.get().getModel(uri);
203 204
}

A
Alex Dima 已提交
205 206 207
/**
 * Get all the created models.
 */
A
Alex Dima 已提交
208
export function getModels(): ITextModel[] {
209
	return StaticServices.modelService.get().getModels();
A
Alex Dima 已提交
210 211
}

A
Alex Dima 已提交
212 213
/**
 * Emitted when a model is created.
A
Alex Dima 已提交
214
 * @event
A
Alex Dima 已提交
215
 */
A
Alex Dima 已提交
216
export function onDidCreateModel(listener: (model: ITextModel) => void): IDisposable {
217
	return StaticServices.modelService.get().onModelAdded(listener);
218 219
}

A
Alex Dima 已提交
220 221
/**
 * Emitted right before a model is disposed.
A
Alex Dima 已提交
222
 * @event
A
Alex Dima 已提交
223
 */
A
Alex Dima 已提交
224
export function onWillDisposeModel(listener: (model: ITextModel) => void): IDisposable {
225
	return StaticServices.modelService.get().onModelRemoved(listener);
226 227
}

A
Alex Dima 已提交
228 229
/**
 * Emitted when a different language is set to a model.
A
Alex Dima 已提交
230
 * @event
A
Alex Dima 已提交
231
 */
A
Alex Dima 已提交
232
export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextModel; readonly oldLanguage: string; }) => void): IDisposable {
233
	return StaticServices.modelService.get().onModelModeChanged((e) => {
A
Alex Dima 已提交
234 235 236 237 238
		listener({
			model: e.model,
			oldLanguage: e.oldModeId
		});
	});
239 240
}

A
Alex Dima 已提交
241 242 243 244
/**
 * Create a new web worker that has model syncing capabilities built in.
 * Specify an AMD module to load that will `create` an object that will be proxied.
 */
J
Johannes Rieken 已提交
245
export function createWebWorker<T>(opts: IWebWorkerOptions): MonacoWebWorker<T> {
246
	return actualCreateWebWorker<T>(StaticServices.modelService.get(), opts);
247 248
}

A
Alex Dima 已提交
249 250 251
/**
 * Colorize the contents of `domNode` using attribute `data-lang`.
 */
J
Johannes Rieken 已提交
252
export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): TPromise<void> {
253
	return Colorizer.colorizeElement(StaticServices.standaloneThemeService.get(), StaticServices.modeService.get(), domNode, options);
254 255
}

A
Alex Dima 已提交
256 257 258
/**
 * Colorize `text` using language `languageId`.
 */
J
Johannes Rieken 已提交
259
export function colorize(text: string, languageId: string, options: IColorizerOptions): TPromise<string> {
260
	return Colorizer.colorize(StaticServices.modeService.get(), text, languageId, options);
261 262
}

A
Alex Dima 已提交
263 264 265
/**
 * Colorize a line in a model.
 */
A
Alex Dima 已提交
266
export function colorizeModelLine(model: ITextModel, lineNumber: number, tabSize: number = 4): string {
267 268 269
	return Colorizer.colorizeModelLine(model, lineNumber, tabSize);
}

A
Alex Dima 已提交
270 271 272
/**
 * @internal
 */
A
Alex Dima 已提交
273 274
function getSafeTokenizationSupport(languageId: string): modes.ITokenizationSupport {
	let tokenizationSupport = modes.TokenizationRegistry.get(languageId);
A
Alex Dima 已提交
275 276 277 278 279
	if (tokenizationSupport) {
		return tokenizationSupport;
	}
	return {
		getInitialState: () => NULL_STATE,
A
Alex Dima 已提交
280
		tokenize: (line: string, state: modes.IState, deltaOffset: number) => nullTokenize(languageId, line, state, deltaOffset),
A
Tweaks  
Alex Dima 已提交
281
		tokenize2: undefined,
A
Alex Dima 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
	};
}

/**
 * Tokenize `text` using language `languageId`
 */
export function tokenize(text: string, languageId: string): Token[][] {
	let modeService = StaticServices.modeService.get();
	// Needed in order to get the mode registered for subsequent look-ups
	modeService.getOrCreateMode(languageId);

	let tokenizationSupport = getSafeTokenizationSupport(languageId);
	let lines = text.split(/\r\n|\r|\n/);
	let result: Token[][] = [];
	let state = tokenizationSupport.getInitialState();
	for (let i = 0, len = lines.length; i < len; i++) {
		let line = lines[i];
		let tokenizationResult = tokenizationSupport.tokenize(line, state, 0);

A
Alex Dima 已提交
301
		result[i] = tokenizationResult.tokens;
A
Alex Dima 已提交
302 303 304 305 306
		state = tokenizationResult.endState;
	}
	return result;
}

307 308 309
/**
 * Define a new theme.
 */
310
export function defineTheme(themeName: string, themeData: IStandaloneThemeData): void {
311
	StaticServices.standaloneThemeService.get().defineTheme(themeName, themeData);
312 313
}

314 315 316 317 318 319 320
/**
 * Switches to a theme.
 */
export function setTheme(themeName: string): void {
	StaticServices.standaloneThemeService.get().setTheme(themeName);
}

321 322 323 324 325 326 327 328 329 330 331 332
/**
 * @internal
 * --------------------------------------------
 * This is repeated here so it can be exported
 * because TS inlines const enums
 * --------------------------------------------
 */
enum ScrollType {
	Smooth = 0,
	Immediate = 1,
}

333 334 335 336 337 338 339 340 341 342 343
/**
 * @internal
 * --------------------------------------------
 * This is repeated here so it can be exported
 * because TS inlines const enums
 * --------------------------------------------
 */
enum RenderLineNumbersType {
	Off = 0,
	On = 1,
	Relative = 2,
344 345
	Interval = 3,
	Custom = 4
346 347
}

348 349 350
/**
 * @internal
 */
351
export function createMonacoEditorAPI(): typeof monaco.editor {
A
Alex Dima 已提交
352
	return {
353
		// methods
A
Alex Dima 已提交
354
		create: <any>create,
355
		onDidCreateEditor: <any>onDidCreateEditor,
356 357
		createDiffEditor: <any>createDiffEditor,
		createDiffNavigator: <any>createDiffNavigator,
358 359

		createModel: createModel,
A
Alex Dima 已提交
360 361
		setModelLanguage: setModelLanguage,
		setModelMarkers: setModelMarkers,
R
Roman Safronov 已提交
362
		getModelMarkers: getModelMarkers,
363 364 365 366
		getModels: getModels,
		getModel: getModel,
		onDidCreateModel: onDidCreateModel,
		onWillDisposeModel: onWillDisposeModel,
A
Alex Dima 已提交
367
		onDidChangeModelLanguage: onDidChangeModelLanguage,
368 369 370 371 372 373


		createWebWorker: createWebWorker,
		colorizeElement: colorizeElement,
		colorize: colorize,
		colorizeModelLine: colorizeModelLine,
A
Alex Dima 已提交
374
		tokenize: tokenize,
375
		defineTheme: defineTheme,
376
		setTheme: setTheme,
377 378 379

		// enums
		ScrollbarVisibility: ScrollbarVisibility,
380
		WrappingIndent: editorOptions.WrappingIndent,
381 382 383 384 385
		OverviewRulerLane: OverviewRulerLane,
		EndOfLinePreference: EndOfLinePreference,
		DefaultEndOfLine: DefaultEndOfLine,
		EndOfLineSequence: EndOfLineSequence,
		TrackedRangeStickiness: TrackedRangeStickiness,
386
		CursorChangeReason: CursorChangeReason,
A
Alex Dima 已提交
387
		MouseTargetType: MouseTargetType,
388 389
		TextEditorCursorStyle: editorOptions.TextEditorCursorStyle,
		TextEditorCursorBlinkingStyle: editorOptions.TextEditorCursorBlinkingStyle,
390 391
		ContentWidgetPositionPreference: ContentWidgetPositionPreference,
		OverlayWidgetPositionPreference: OverlayWidgetPositionPreference,
392
		RenderMinimap: editorOptions.RenderMinimap,
393
		ScrollType: <any>ScrollType,
394
		RenderLineNumbersType: <any>RenderLineNumbersType,
395 396

		// classes
397
		InternalEditorOptions: <any>editorOptions.InternalEditorOptions,
398 399
		BareFontInfo: <any>BareFontInfo,
		FontInfo: <any>FontInfo,
400 401
		TextModelResolvedOptions: <any>TextModelResolvedOptions,
		FindMatch: <any>FindMatch,
402 403

		// vars
A
Alex Dima 已提交
404
		EditorType: editorCommon.EditorType
A
Alex Dima 已提交
405
	};
406
}