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

6
import 'vs/css!./standalone-tokens';
J
Johannes Rieken 已提交
7
import { IDisposable } from 'vs/base/common/lifecycle';
8
import { URI } from 'vs/base/common/uri';
A
Alex Dima 已提交
9 10
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
11
import { OpenerService } from 'vs/editor/browser/services/openerService';
12
import { DiffNavigator, IDiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
13
import { EditorOptions, ConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
A
Alex Dima 已提交
14 15
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { Token } from 'vs/editor/common/core/token';
A
Alexandru Dima 已提交
16
import { IEditor, EditorType } from 'vs/editor/common/editorCommon';
A
Alex Dima 已提交
17
import { FindMatch, ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
18
import * as modes from 'vs/editor/common/modes';
A
Alex Dima 已提交
19 20
import { NULL_STATE, nullTokenize } from 'vs/editor/common/modes/nullMode';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
A
Alex Dima 已提交
21
import { ILanguageSelection } from 'vs/editor/common/services/modeService';
A
Alex Dima 已提交
22
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
23
import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebWorker } from 'vs/editor/common/services/webWorker';
A
Alex Dima 已提交
24 25 26
import * as standaloneEnums from 'vs/editor/common/standalone/standaloneEnums';
import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer';
import { SimpleEditorModelResolverService } from 'vs/editor/standalone/browser/simpleServices';
27
import { IDiffEditorConstructionOptions, IStandaloneEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor, StandaloneDiffEditor, StandaloneEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor';
A
Alex Dima 已提交
28 29
import { DynamicStandaloneServices, IEditorOverrideServices, StaticServices } from 'vs/editor/standalone/browser/standaloneServices';
import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
30
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
A
Alex Dima 已提交
31 32
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
33
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
J
Johannes Rieken 已提交
34 35
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
A
Alex Dima 已提交
36
import { IMarker, IMarkerData } from 'vs/platform/markers/common/markers';
37
import { INotificationService } from 'vs/platform/notification/common/notification';
A
Alex Dima 已提交
38
import { IOpenerService } from 'vs/platform/opener/common/opener';
39
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
40
import { clearAllFontInfos } from 'vs/editor/browser/config/configuration';
41
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
42
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
A
Alex Dima 已提交
43
import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl';
44
import { splitLines } from 'vs/base/common/strings';
45

M
Matt Bierner 已提交
46 47
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

A
Alexandru Dima 已提交
48
function withAllStandaloneServices<T extends IEditor>(domElement: HTMLElement, override: IEditorOverrideServices, callback: (services: DynamicStandaloneServices) => T): T {
49 50
	let services = new DynamicStandaloneServices(domElement, override);

51
	let simpleEditorModelResolverService: SimpleEditorModelResolverService | null = null;
52
	if (!services.has(ITextModelService)) {
S
Sebastian Pahnke 已提交
53
		simpleEditorModelResolverService = new SimpleEditorModelResolverService(StaticServices.modelService.get());
54
		services.set(ITextModelService, simpleEditorModelResolverService);
55 56
	}

57
	if (!services.has(IOpenerService)) {
P
Pine Wu 已提交
58
		services.set(IOpenerService, new OpenerService(services.get(ICodeEditorService), services.get(ICommandService)));
59 60
	}

61
	let result = callback(services);
62

63 64 65 66
	if (simpleEditorModelResolverService) {
		simpleEditorModelResolverService.setEditor(result);
	}

67 68 69
	return result;
}

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

95 96 97 98 99 100 101 102 103 104 105
/**
 * 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);
	});
}

106 107 108 109 110
/**
 * 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 已提交
111
export function createDiffEditor(domElement: HTMLElement, options?: IDiffEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneDiffEditor {
A
Alex Dima 已提交
112
	return withAllStandaloneServices(domElement, override || {}, (services) => {
113 114 115 116 117 118 119 120
		return new StandaloneDiffEditor(
			domElement,
			options,
			services,
			services.get(IInstantiationService),
			services.get(IContextKeyService),
			services.get(IKeybindingService),
			services.get(IContextViewService),
121
			services.get(IEditorWorkerService),
122
			services.get(ICodeEditorService),
123
			services.get(IStandaloneThemeService),
124 125
			services.get(INotificationService),
			services.get(IConfigurationService),
126
			services.get(IContextMenuService),
127
			services.get(IEditorProgressService),
128
			services.get(IClipboardService)
129 130
		);
	});
131 132
}

A
Alex Dima 已提交
133
export interface IDiffNavigatorOptions {
134 135 136
	readonly followsCaret?: boolean;
	readonly ignoreCharChanges?: boolean;
	readonly alwaysRevealFirst?: boolean;
A
Alex Dima 已提交
137 138
}

J
Johannes Rieken 已提交
139
export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: IDiffNavigatorOptions): IDiffNavigator {
A
Alex Dima 已提交
140 141 142
	return new DiffNavigator(diffEditor, opts);
}

A
Alex Dima 已提交
143 144
function doCreateModel(value: string, languageSelection: ILanguageSelection, uri?: URI): ITextModel {
	return StaticServices.modelService.get().createModel(value, languageSelection, uri);
145 146
}

A
Alex Dima 已提交
147 148 149 150
/**
 * 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 已提交
151
export function createModel(value: string, language?: string, uri?: URI): ITextModel {
A
Alex Dima 已提交
152
	value = value || '';
153

A
Alex Dima 已提交
154 155 156 157 158 159 160
	if (!language) {
		let firstLF = value.indexOf('\n');
		let firstLine = value;
		if (firstLF !== -1) {
			firstLine = value.substring(0, firstLF);
		}

B
Benjamin Pasero 已提交
161
		return doCreateModel(value, StaticServices.modeService.get().createByFilepathOrFirstLine(uri || null, firstLine), uri);
162
	}
A
Alex Dima 已提交
163
	return doCreateModel(value, StaticServices.modeService.get().create(language), uri);
A
Alex Dima 已提交
164 165
}

A
Alex Dima 已提交
166 167 168
/**
 * Change the language for a model.
 */
M
Martin Aeschlimann 已提交
169
export function setModelLanguage(model: ITextModel, languageId: string): void {
A
Alex Dima 已提交
170
	StaticServices.modelService.get().setMode(model, StaticServices.modeService.get().create(languageId));
171 172
}

A
Alex Dima 已提交
173 174 175
/**
 * Set the markers for a model.
 */
A
Alex Dima 已提交
176
export function setModelMarkers(model: ITextModel, owner: string, markers: IMarkerData[]): void {
177 178 179
	if (model) {
		StaticServices.markerService.get().changeOne(owner, model.uri, markers);
	}
180 181
}

R
Roman Safronov 已提交
182
/**
R
rebornix 已提交
183
 * Get markers for owner and/or resource
184 185
 *
 * @returns list of markers
R
Roman Safronov 已提交
186
 */
R
rsafronov 已提交
187
export function getModelMarkers(filter: { owner?: string, resource?: URI, take?: number }): IMarker[] {
R
Roman Safronov 已提交
188 189 190
	return StaticServices.markerService.get().read(filter);
}

A
Alex Dima 已提交
191 192 193
/**
 * Get the model that has `uri` if it exists.
 */
A
Alex Dima 已提交
194
export function getModel(uri: URI): ITextModel | null {
195
	return StaticServices.modelService.get().getModel(uri);
196 197
}

A
Alex Dima 已提交
198 199 200
/**
 * Get all the created models.
 */
A
Alex Dima 已提交
201
export function getModels(): ITextModel[] {
202
	return StaticServices.modelService.get().getModels();
A
Alex Dima 已提交
203 204
}

A
Alex Dima 已提交
205 206
/**
 * Emitted when a model is created.
A
Alex Dima 已提交
207
 * @event
A
Alex Dima 已提交
208
 */
A
Alex Dima 已提交
209
export function onDidCreateModel(listener: (model: ITextModel) => void): IDisposable {
210
	return StaticServices.modelService.get().onModelAdded(listener);
211 212
}

A
Alex Dima 已提交
213 214
/**
 * Emitted right before a model is disposed.
A
Alex Dima 已提交
215
 * @event
A
Alex Dima 已提交
216
 */
A
Alex Dima 已提交
217
export function onWillDisposeModel(listener: (model: ITextModel) => void): IDisposable {
218
	return StaticServices.modelService.get().onModelRemoved(listener);
219 220
}

A
Alex Dima 已提交
221 222
/**
 * Emitted when a different language is set to a model.
A
Alex Dima 已提交
223
 * @event
A
Alex Dima 已提交
224
 */
A
Alex Dima 已提交
225
export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextModel; readonly oldLanguage: string; }) => void): IDisposable {
226
	return StaticServices.modelService.get().onModelModeChanged((e) => {
A
Alex Dima 已提交
227 228 229 230 231
		listener({
			model: e.model,
			oldLanguage: e.oldModeId
		});
	});
232 233
}

A
Alex Dima 已提交
234 235 236 237
/**
 * 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 已提交
238
export function createWebWorker<T>(opts: IWebWorkerOptions): MonacoWebWorker<T> {
239
	return actualCreateWebWorker<T>(StaticServices.modelService.get(), opts);
240 241
}

A
Alex Dima 已提交
242 243 244
/**
 * Colorize the contents of `domNode` using attribute `data-lang`.
 */
245
export function colorizeElement(domNode: HTMLElement, options: IColorizerElementOptions): Promise<void> {
A
Alex Dima 已提交
246 247 248
	const themeService = <StandaloneThemeServiceImpl>StaticServices.standaloneThemeService.get();
	themeService.registerEditorContainer(domNode);
	return Colorizer.colorizeElement(themeService, StaticServices.modeService.get(), domNode, options);
249 250
}

A
Alex Dima 已提交
251 252 253
/**
 * Colorize `text` using language `languageId`.
 */
254
export function colorize(text: string, languageId: string, options: IColorizerOptions): Promise<string> {
A
Alex Dima 已提交
255 256
	const themeService = <StandaloneThemeServiceImpl>StaticServices.standaloneThemeService.get();
	themeService.registerEditorContainer(document.body);
257
	return Colorizer.colorize(StaticServices.modeService.get(), text, languageId, options);
258 259
}

A
Alex Dima 已提交
260 261 262
/**
 * Colorize a line in a model.
 */
A
Alex Dima 已提交
263
export function colorizeModelLine(model: ITextModel, lineNumber: number, tabSize: number = 4): string {
A
Alex Dima 已提交
264 265
	const themeService = <StandaloneThemeServiceImpl>StaticServices.standaloneThemeService.get();
	themeService.registerEditorContainer(document.body);
266 267 268
	return Colorizer.colorizeModelLine(model, lineNumber, tabSize);
}

A
Alex Dima 已提交
269 270 271
/**
 * @internal
 */
M
Matt Bierner 已提交
272
function getSafeTokenizationSupport(language: string): Omit<modes.ITokenizationSupport, 'tokenize2'> {
M
Martin Aeschlimann 已提交
273
	let tokenizationSupport = modes.TokenizationRegistry.get(language);
A
Alex Dima 已提交
274 275 276 277 278
	if (tokenizationSupport) {
		return tokenizationSupport;
	}
	return {
		getInitialState: () => NULL_STATE,
279
		tokenize: (line: string, hasEOL: boolean, state: modes.IState, deltaOffset: number) => nullTokenize(language, line, state, deltaOffset)
A
Alex Dima 已提交
280 281 282 283 284 285 286 287 288
	};
}

/**
 * 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
A
Alex Dima 已提交
289
	modeService.triggerMode(languageId);
A
Alex Dima 已提交
290 291

	let tokenizationSupport = getSafeTokenizationSupport(languageId);
292
	let lines = splitLines(text);
A
Alex Dima 已提交
293 294 295 296
	let result: Token[][] = [];
	let state = tokenizationSupport.getInitialState();
	for (let i = 0, len = lines.length; i < len; i++) {
		let line = lines[i];
297
		let tokenizationResult = tokenizationSupport.tokenize(line, true, state, 0);
A
Alex Dima 已提交
298

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

305
/**
A
Alex Dima 已提交
306
 * Define a new theme or update an existing theme.
307
 */
308
export function defineTheme(themeName: string, themeData: IStandaloneThemeData): void {
309
	StaticServices.standaloneThemeService.get().defineTheme(themeName, themeData);
310 311
}

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

319 320 321 322 323 324 325
/**
 * Clears all cached font measurements and triggers re-measurement.
 */
export function remeasureFonts(): void {
	clearAllFontInfos();
}

326 327 328 329 330 331 332
/**
 * Register a command.
 */
export function registerCommand(id: string, handler: (accessor: any, ...args: any[]) => void): IDisposable {
	return CommandsRegistry.registerCommand({ id, handler });
}

333 334 335
/**
 * @internal
 */
336
export function createMonacoEditorAPI(): typeof monaco.editor {
A
Alex Dima 已提交
337
	return {
338
		// methods
A
Alex Dima 已提交
339
		create: <any>create,
340
		onDidCreateEditor: <any>onDidCreateEditor,
341 342
		createDiffEditor: <any>createDiffEditor,
		createDiffNavigator: <any>createDiffNavigator,
343

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
		createModel: <any>createModel,
		setModelLanguage: <any>setModelLanguage,
		setModelMarkers: <any>setModelMarkers,
		getModelMarkers: <any>getModelMarkers,
		getModels: <any>getModels,
		getModel: <any>getModel,
		onDidCreateModel: <any>onDidCreateModel,
		onWillDisposeModel: <any>onWillDisposeModel,
		onDidChangeModelLanguage: <any>onDidChangeModelLanguage,


		createWebWorker: <any>createWebWorker,
		colorizeElement: <any>colorizeElement,
		colorize: <any>colorize,
		colorizeModelLine: <any>colorizeModelLine,
		tokenize: <any>tokenize,
		defineTheme: <any>defineTheme,
		setTheme: <any>setTheme,
362
		remeasureFonts: remeasureFonts,
363
		registerCommand: registerCommand,
364 365

		// enums
366 367 368
		AccessibilitySupport: standaloneEnums.AccessibilitySupport,
		ContentWidgetPositionPreference: standaloneEnums.ContentWidgetPositionPreference,
		CursorChangeReason: standaloneEnums.CursorChangeReason,
A
Alex Dima 已提交
369
		DefaultEndOfLine: standaloneEnums.DefaultEndOfLine,
370 371 372
		EditorAutoIndentStrategy: standaloneEnums.EditorAutoIndentStrategy,
		EditorOption: standaloneEnums.EditorOption,
		EndOfLinePreference: standaloneEnums.EndOfLinePreference,
A
Alex Dima 已提交
373
		EndOfLineSequence: standaloneEnums.EndOfLineSequence,
374
		MinimapPosition: standaloneEnums.MinimapPosition,
A
Alex Dima 已提交
375 376
		MouseTargetType: standaloneEnums.MouseTargetType,
		OverlayWidgetPositionPreference: standaloneEnums.OverlayWidgetPositionPreference,
377 378
		OverviewRulerLane: standaloneEnums.OverviewRulerLane,
		RenderLineNumbersType: standaloneEnums.RenderLineNumbersType,
A
Alex Dima 已提交
379
		RenderMinimap: standaloneEnums.RenderMinimap,
380
		ScrollbarVisibility: standaloneEnums.ScrollbarVisibility,
A
Alex Dima 已提交
381
		ScrollType: standaloneEnums.ScrollType,
382 383 384 385
		TextEditorCursorBlinkingStyle: standaloneEnums.TextEditorCursorBlinkingStyle,
		TextEditorCursorStyle: standaloneEnums.TextEditorCursorStyle,
		TrackedRangeStickiness: standaloneEnums.TrackedRangeStickiness,
		WrappingIndent: standaloneEnums.WrappingIndent,
386 387

		// classes
388
		ConfigurationChangedEvent: <any>ConfigurationChangedEvent,
389 390
		BareFontInfo: <any>BareFontInfo,
		FontInfo: <any>FontInfo,
391 392
		TextModelResolvedOptions: <any>TextModelResolvedOptions,
		FindMatch: <any>FindMatch,
393 394

		// vars
A
Alexandru Dima 已提交
395
		EditorType: EditorType,
396
		EditorOptions: <any>EditorOptions
M
Martin Aeschlimann 已提交
397

A
Alex Dima 已提交
398
	};
399
}