commonEditorConfig.ts 29.6 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';

A
Alex Dima 已提交
7 8
import * as nls from 'vs/nls';
import Event, {Emitter} from 'vs/base/common/event';
A
Alex Dima 已提交
9 10
import {Disposable} from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
A
Alex Dima 已提交
11 12
import * as platform from 'vs/base/common/platform';
import {Extensions, IConfigurationRegistry, IConfigurationNode} from 'vs/platform/configuration/common/configurationRegistry';
E
Erich Gamma 已提交
13
import {Registry} from 'vs/platform/platform';
14
import {DefaultConfig, DEFAULT_INDENTATION, DEFAULT_TRIM_AUTO_WHITESPACE, GOLDEN_LINE_HEIGHT_RATIO} from 'vs/editor/common/config/defaultConfig';
A
Alex Dima 已提交
15
import * as editorCommon from 'vs/editor/common/editorCommon';
16
import {EditorLayoutProvider} from 'vs/editor/common/viewLayout/editorLayoutProvider';
17
import {ScrollbarVisibility} from 'vs/base/common/scrollable';
E
Erich Gamma 已提交
18

19 20 21 22 23 24 25 26 27 28 29
// TODO@Alex: investigate if it is better to stick to 31 bits (see smi = SMall Integer)
// See https://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/#tagged-values
/**
 * MAX_INT that fits in 32 bits
 */
const MAX_SAFE_INT = 0x7fffffff;
/**
 * MIN_INT that fits in 32 bits
 */
const MIN_SAFE_INT = -0x80000000;

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
export interface IEditorZoom {
	onDidChangeZoomLevel:Event<number>;
	getZoomLevel(): number;
	setZoomLevel(zoomLevel:number): void;
}

export const EditorZoom: IEditorZoom = new class {

	private _zoomLevel: number = 0;

	private _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>();
	public onDidChangeZoomLevel:Event<number> = this._onDidChangeZoomLevel.event;

	public getZoomLevel(): number {
		return this._zoomLevel;
	}

	public setZoomLevel(zoomLevel:number): void {
		zoomLevel = Math.min(Math.max(-9, zoomLevel), 9);
		if (this._zoomLevel === zoomLevel) {
			return;
		}

		this._zoomLevel = zoomLevel;
		this._onDidChangeZoomLevel.fire(this._zoomLevel);
	}
};
E
Erich Gamma 已提交
57

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/**
 * 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);
	}
};

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
/**
 * Experimental screen reader support toggle
 */
export class GlobalScreenReaderNVDA {

	private static _value = false;
	private static _onChange = new Emitter<boolean>();
	public static onChange: Event<boolean> = GlobalScreenReaderNVDA._onChange.event;

	public static getValue(): boolean {
		return this._value;
	}

	public static setValue(value:boolean): void {
		if (this._value === value) {
			return;
		}
		this._value = value;
		this._onChange.fire(this._value);
	}
}

E
Erich Gamma 已提交
112 113
export class ConfigurationWithDefaults {

A
Alex Dima 已提交
114
	private _editor:editorCommon.IEditorOptions;
E
Erich Gamma 已提交
115

A
Alex Dima 已提交
116 117
	constructor(options:editorCommon.IEditorOptions) {
		this._editor = <editorCommon.IEditorOptions>objects.clone(DefaultConfig.editor);
E
Erich Gamma 已提交
118 119 120 121

		this._mergeOptionsIn(options);
	}

A
Alex Dima 已提交
122
	public getEditorOptions(): editorCommon.IEditorOptions {
E
Erich Gamma 已提交
123 124 125
		return this._editor;
	}

A
Alex Dima 已提交
126 127
	private _mergeOptionsIn(newOptions:editorCommon.IEditorOptions): void {
		this._editor = objects.mixin(this._editor, newOptions || {});
E
Erich Gamma 已提交
128 129
	}

A
Alex Dima 已提交
130
	public updateOptions(newOptions:editorCommon.IEditorOptions): void {
E
Erich Gamma 已提交
131 132 133 134 135 136 137 138 139 140 141
		// Apply new options
		this._mergeOptionsIn(newOptions);
	}
}

class InternalEditorOptionsHelper {

	constructor() {
	}

	public static createInternalEditorOptions(
142
		outerWidth:number, outerHeight:number,
A
Alex Dima 已提交
143
		opts:editorCommon.IEditorOptions,
144 145
		fontInfo: editorCommon.FontInfo,
		editorClassName:string,
E
Erich Gamma 已提交
146
		isDominatedByLongLines:boolean,
147
		maxLineNumber: number,
148
		canUseTranslate3d: boolean
149
	): editorCommon.InternalEditorOptions {
E
Erich Gamma 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

		let wrappingColumn = toInteger(opts.wrappingColumn, -1);

		let stopRenderingLineAfter:number;
		if (typeof opts.stopRenderingLineAfter !== 'undefined') {
			stopRenderingLineAfter = toInteger(opts.stopRenderingLineAfter, -1);
		} else if (wrappingColumn >= 0) {
			stopRenderingLineAfter = -1;
		} else {
			stopRenderingLineAfter = 10000;
		}

		let mouseWheelScrollSensitivity = toFloat(opts.mouseWheelScrollSensitivity, 1);
		let scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, mouseWheelScrollSensitivity);

		let glyphMargin = toBoolean(opts.glyphMargin);
		let lineNumbers = opts.lineNumbers;
		let lineNumbersMinChars = toInteger(opts.lineNumbersMinChars, 1);
		let lineDecorationsWidth = toInteger(opts.lineDecorationsWidth, 0);
M
Martin Aeschlimann 已提交
169
		if (opts.folding) {
170
			lineDecorationsWidth += 16;
M
Martin Aeschlimann 已提交
171
		}
E
Erich Gamma 已提交
172 173 174 175
		let layoutInfo = EditorLayoutProvider.compute({
			outerWidth: outerWidth,
			outerHeight: outerHeight,
			showGlyphMargin: glyphMargin,
176
			lineHeight: fontInfo.lineHeight,
E
Erich Gamma 已提交
177 178 179
			showLineNumbers: !!lineNumbers,
			lineNumbersMinChars: lineNumbersMinChars,
			lineDecorationsWidth: lineDecorationsWidth,
180
			maxDigitWidth: fontInfo.maxDigitWidth,
181
			maxLineNumber: maxLineNumber,
E
Erich Gamma 已提交
182 183 184 185 186 187 188 189 190 191 192
			verticalScrollbarWidth: scrollbar.verticalScrollbarSize,
			horizontalScrollbarHeight: scrollbar.horizontalScrollbarSize,
			scrollbarArrowSize: scrollbar.arrowSize,
			verticalScrollbarHasArrows: scrollbar.verticalHasArrows
		});

		if (isDominatedByLongLines && wrappingColumn > 0) {
			// Force viewport width wrapping if model is dominated by long lines
			wrappingColumn = 0;
		}

193
		let bareWrappingInfo: { isViewportWrapping: boolean; wrappingColumn: number; };
E
Erich Gamma 已提交
194 195
		if (wrappingColumn === 0) {
			// If viewport width wrapping is enabled
196
			bareWrappingInfo = {
E
Erich Gamma 已提交
197
				isViewportWrapping: true,
198
				wrappingColumn: Math.max(1, Math.floor((layoutInfo.contentWidth - layoutInfo.verticalScrollbarWidth) / fontInfo.typicalHalfwidthCharacterWidth))
E
Erich Gamma 已提交
199 200 201
			};
		} else if (wrappingColumn > 0) {
			// Wrapping is enabled
202
			bareWrappingInfo = {
E
Erich Gamma 已提交
203 204 205 206
				isViewportWrapping: false,
				wrappingColumn: wrappingColumn
			};
		} else {
207
			bareWrappingInfo = {
E
Erich Gamma 已提交
208 209 210 211
				isViewportWrapping: false,
				wrappingColumn: -1
			};
		}
212 213 214 215 216 217 218 219
		let wrappingInfo = new editorCommon.EditorWrappingInfo({
			isViewportWrapping: bareWrappingInfo.isViewportWrapping,
			wrappingColumn: bareWrappingInfo.wrappingColumn,
			wrappingIndent: wrappingIndentFromString(opts.wrappingIndent),
			wordWrapBreakBeforeCharacters: String(opts.wordWrapBreakBeforeCharacters),
			wordWrapBreakAfterCharacters: String(opts.wordWrapBreakAfterCharacters),
			wordWrapBreakObtrusiveCharacters: String(opts.wordWrapBreakObtrusiveCharacters),
		});
E
Erich Gamma 已提交
220

221 222
		let readOnly = toBoolean(opts.readOnly);

223
		let tabFocusMode = TabFocus.getTabFocusMode();
224 225 226 227
		if (readOnly) {
			tabFocusMode = true;
		}

228
		let viewInfo = new editorCommon.InternalEditorViewOptions({
229
			theme: opts.theme,
230
			canUseTranslate3d: canUseTranslate3d,
231 232 233
			experimentalScreenReader: toBoolean(opts.experimentalScreenReader),
			rulers: toSortedIntegerArray(opts.rulers),
			ariaLabel: String(opts.ariaLabel),
E
Erich Gamma 已提交
234 235 236 237 238 239
			lineNumbers: lineNumbers,
			selectOnLineNumbers: toBoolean(opts.selectOnLineNumbers),
			glyphMargin: glyphMargin,
			revealHorizontalRightPadding: toInteger(opts.revealHorizontalRightPadding, 0),
			roundedSelection: toBoolean(opts.roundedSelection),
			overviewRulerLanes: toInteger(opts.overviewRulerLanes, 0, 3),
240
			cursorBlinking: cursorBlinkingStyleFromString(opts.cursorBlinking),
241
			mouseWheelZoom: toBoolean(opts.mouseWheelZoom),
A
Alex Dima 已提交
242
			cursorStyle: cursorStyleFromString(opts.cursorStyle),
E
Erich Gamma 已提交
243 244
			hideCursorInOverviewRuler: toBoolean(opts.hideCursorInOverviewRuler),
			scrollBeyondLastLine: toBoolean(opts.scrollBeyondLastLine),
245 246 247
			editorClassName: editorClassName,
			stopRenderingLineAfter: stopRenderingLineAfter,
			renderWhitespace: toBoolean(opts.renderWhitespace),
248
			renderControlCharacters: toBoolean(opts.renderControlCharacters),
249
			renderIndentGuides: toBoolean(opts.renderIndentGuides),
250 251 252
			scrollbar: scrollbar,
		});

A
Alex Dima 已提交
253
		let contribInfo = new editorCommon.EditorContribOptions({
254
			selectionClipboard: toBoolean(opts.selectionClipboard),
E
Erich Gamma 已提交
255 256 257 258
			hover: toBoolean(opts.hover),
			contextmenu: toBoolean(opts.contextmenu),
			quickSuggestions: toBoolean(opts.quickSuggestions),
			quickSuggestionsDelay: toInteger(opts.quickSuggestionsDelay),
J
Joao Moreno 已提交
259
			parameterHints: toBoolean(opts.parameterHints),
E
Erich Gamma 已提交
260 261 262
			iconsInSuggestions: toBoolean(opts.iconsInSuggestions),
			formatOnType: toBoolean(opts.formatOnType),
			suggestOnTriggerCharacters: toBoolean(opts.suggestOnTriggerCharacters),
263
			acceptSuggestionOnEnter: toBoolean(opts.acceptSuggestionOnEnter),
264
			snippetSuggestions: opts.snippetSuggestions,
265
			tabCompletion: opts.tabCompletion,
266
			wordBasedSuggestions: opts.wordBasedSuggestions,
E
Erich Gamma 已提交
267
			selectionHighlight: toBoolean(opts.selectionHighlight),
268
			codeLens: opts.referenceInfos && opts.codeLens,
M
Martin Aeschlimann 已提交
269
			folding: toBoolean(opts.folding),
A
Alex Dima 已提交
270 271
		});

272 273 274 275
		return new editorCommon.InternalEditorOptions({
			lineHeight: fontInfo.lineHeight, // todo -> duplicated in styling
			readOnly: readOnly,
			wordSeparators: String(opts.wordSeparators),
A
Alex Dima 已提交
276
			autoClosingBrackets: toBoolean(opts.autoClosingBrackets),
277
			useTabStops: toBoolean(opts.useTabStops),
278
			tabFocusMode: tabFocusMode,
E
Erich Gamma 已提交
279
			layoutInfo: layoutInfo,
280
			fontInfo: fontInfo,
281
			viewInfo: viewInfo,
E
Erich Gamma 已提交
282
			wrappingInfo: wrappingInfo,
A
Alex Dima 已提交
283
			contribInfo: contribInfo,
284
		});
E
Erich Gamma 已提交
285 286
	}

A
Alex Dima 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299
	private static _sanitizeScrollbarOpts(raw:editorCommon.IEditorScrollbarOptions, mouseWheelScrollSensitivity:number): editorCommon.InternalEditorScrollbarOptions {

		var visibilityFromString = (visibility: string) => {
			switch (visibility) {
				case 'hidden':
					return ScrollbarVisibility.Hidden;
				case 'visible':
					return ScrollbarVisibility.Visible;
				default:
					return ScrollbarVisibility.Auto;
			}
		};

A
Alex Dima 已提交
300 301
		let horizontalScrollbarSize = toIntegerWithDefault(raw.horizontalScrollbarSize, 10);
		let verticalScrollbarSize = toIntegerWithDefault(raw.verticalScrollbarSize, 14);
A
Alex Dima 已提交
302 303 304
		return new editorCommon.InternalEditorScrollbarOptions({
			vertical: visibilityFromString(raw.vertical),
			horizontal: visibilityFromString(raw.horizontal),
E
Erich Gamma 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

			arrowSize: toIntegerWithDefault(raw.arrowSize, 11),
			useShadows: toBooleanWithDefault(raw.useShadows, true),

			verticalHasArrows: toBooleanWithDefault(raw.verticalHasArrows, false),
			horizontalHasArrows: toBooleanWithDefault(raw.horizontalHasArrows, false),

			horizontalScrollbarSize: horizontalScrollbarSize,
			horizontalSliderSize: toIntegerWithDefault(raw.horizontalSliderSize, horizontalScrollbarSize),

			verticalScrollbarSize: verticalScrollbarSize,
			verticalSliderSize: toIntegerWithDefault(raw.verticalSliderSize, verticalScrollbarSize),

			handleMouseWheel: toBooleanWithDefault(raw.handleMouseWheel, true),
			mouseWheelScrollSensitivity: mouseWheelScrollSensitivity
A
Alex Dima 已提交
320
		});
E
Erich Gamma 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
	}
}

function toBoolean(value:any): boolean {
	return value === 'false' ? false : Boolean(value);
}

function toBooleanWithDefault(value:any, defaultValue:boolean): boolean {
	if (typeof value === 'undefined') {
		return defaultValue;
	}
	return toBoolean(value);
}

function toFloat(source: any, defaultValue: number): number {
A
Alex Dima 已提交
336
	let r = parseFloat(source);
E
Erich Gamma 已提交
337 338 339 340 341 342
	if (isNaN(r)) {
		r = defaultValue;
	}
	return r;
}

343
function toInteger(source:any, minimum:number = MIN_SAFE_INT, maximum:number = MAX_SAFE_INT): number {
A
Alex Dima 已提交
344
	let r = parseInt(source, 10);
E
Erich Gamma 已提交
345 346 347
	if (isNaN(r)) {
		r = 0;
	}
348 349 350
	r = Math.max(minimum, r);
	r = Math.min(maximum, r);
	return r | 0;
E
Erich Gamma 已提交
351 352
}

353 354 355 356 357 358 359 360 361 362
function toSortedIntegerArray(source:any): number[] {
	if (!Array.isArray(source)) {
		return [];
	}
	let arrSource = <any[]>source;
	let r = arrSource.map(el => toInteger(el));
	r.sort();
	return r;
}

A
Alex Dima 已提交
363 364 365 366 367 368 369 370 371 372
function wrappingIndentFromString(wrappingIndent:string): editorCommon.WrappingIndent {
	if (wrappingIndent === 'indent') {
		return editorCommon.WrappingIndent.Indent;
	} else if (wrappingIndent === 'same') {
		return editorCommon.WrappingIndent.Same;
	} else {
		return editorCommon.WrappingIndent.None;
	}
}

A
Alex Dima 已提交
373 374 375 376 377 378 379 380 381 382 383
function cursorStyleFromString(cursorStyle:string): editorCommon.TextEditorCursorStyle {
	if (cursorStyle === 'line') {
		return editorCommon.TextEditorCursorStyle.Line;
	} else if (cursorStyle === 'block') {
		return editorCommon.TextEditorCursorStyle.Block;
	} else if (cursorStyle === 'underline') {
		return editorCommon.TextEditorCursorStyle.Underline;
	}
	return editorCommon.TextEditorCursorStyle.Line;
}

384
function cursorBlinkingStyleFromString(cursorBlinkingStyle: string): editorCommon.TextEditorCursorBlinkingStyle {
385 386 387 388 389 390 391 392 393 394 395 396
	switch (cursorBlinkingStyle) {
		case 'blink':
			return editorCommon.TextEditorCursorBlinkingStyle.Blink;
		case 'smooth':
			return editorCommon.TextEditorCursorBlinkingStyle.Smooth;
		case 'phase':
			return editorCommon.TextEditorCursorBlinkingStyle.Phase;
		case 'expand':
			return editorCommon.TextEditorCursorBlinkingStyle.Expand;
		case 'visible': // maintain compatibility
		case 'solid':
			return editorCommon.TextEditorCursorBlinkingStyle.Solid;
397 398 399 400
	}
	return editorCommon.TextEditorCursorBlinkingStyle.Blink;
}

E
Erich Gamma 已提交
401 402 403 404 405 406 407
function toIntegerWithDefault(source:any, defaultValue:number): number {
	if (typeof source === 'undefined') {
		return defaultValue;
	}
	return toInteger(source);
}

408 409 410 411 412 413 414 415
export interface IElementSizeObserver {
	startObserving(): void;
	observe(dimension?:editorCommon.IDimension): void;
	dispose(): void;
	getWidth(): number;
	getHeight(): number;
}

A
Alex Dima 已提交
416
export abstract class CommonEditorConfiguration extends Disposable implements editorCommon.IConfiguration {
E
Erich Gamma 已提交
417

418 419
	public editor:editorCommon.InternalEditorOptions;
	public editorClone:editorCommon.InternalEditorOptions;
E
Erich Gamma 已提交
420 421

	protected _configWithDefaults:ConfigurationWithDefaults;
422
	protected _elementSizeObserver: IElementSizeObserver;
E
Erich Gamma 已提交
423
	private _isDominatedByLongLines:boolean;
424
	private _maxLineNumber:number;
E
Erich Gamma 已提交
425

A
Alex Dima 已提交
426 427
	private _onDidChange = this._register(new Emitter<editorCommon.IConfigurationChangedEvent>());
	public onDidChange: Event<editorCommon.IConfigurationChangedEvent> = this._onDidChange.event;
A
Alex Dima 已提交
428

429
	constructor(options:editorCommon.IEditorOptions, elementSizeObserver: IElementSizeObserver = null) {
A
Alex Dima 已提交
430
		super();
E
Erich Gamma 已提交
431
		this._configWithDefaults = new ConfigurationWithDefaults(options);
432
		this._elementSizeObserver = elementSizeObserver;
E
Erich Gamma 已提交
433
		this._isDominatedByLongLines = false;
434
		this._maxLineNumber = 1;
E
Erich Gamma 已提交
435
		this.editor = this._computeInternalOptions();
436
		this.editorClone = this.editor.clone();
437
		this._register(EditorZoom.onDidChangeZoomLevel(_ => this._recomputeOptions()));
438
		this._register(TabFocus.onDidChangeTabFocus(_ => this._recomputeOptions()));
E
Erich Gamma 已提交
439 440 441 442 443 444 445
	}

	public dispose(): void {
		super.dispose();
	}

	protected _recomputeOptions(): void {
446 447
		this._setOptions(this._computeInternalOptions());
	}
448

449 450 451
	private _setOptions(newOptions:editorCommon.InternalEditorOptions): void {
		if (this.editor && this.editor.equals(newOptions)) {
			return;
E
Erich Gamma 已提交
452 453
		}

454 455 456 457
		let changeEvent = this.editor.createChangeEvent(newOptions);
		this.editor = newOptions;
		this.editorClone = this.editor.clone();
		this._onDidChange.fire(changeEvent);
E
Erich Gamma 已提交
458 459
	}

A
Alex Dima 已提交
460
	public getRawOptions(): editorCommon.IEditorOptions {
E
Erich Gamma 已提交
461 462 463
		return this._configWithDefaults.getEditorOptions();
	}

464
	private _computeInternalOptions(): editorCommon.InternalEditorOptions {
E
Erich Gamma 已提交
465 466
		let opts = this._configWithDefaults.getEditorOptions();

467
		let editorClassName = this._getEditorClassName(opts.theme, toBoolean(opts.fontLigatures));
468
		let fontFamily = String(opts.fontFamily) || DefaultConfig.editor.fontFamily;
469
		let fontWeight = String(opts.fontWeight) || DefaultConfig.editor.fontWeight;
470 471 472
		let fontSize = toFloat(opts.fontSize, DefaultConfig.editor.fontSize);
		fontSize = Math.max(0, fontSize);
		fontSize = Math.min(100, fontSize);
E
Erich Gamma 已提交
473

474 475
		let lineHeight = toInteger(opts.lineHeight, 0, 150);
		if (lineHeight === 0) {
476
			lineHeight = Math.round(GOLDEN_LINE_HEIGHT_RATIO * fontSize);
E
Erich Gamma 已提交
477
		}
478
		let editorZoomLevelMultiplier = 1 + (EditorZoom.getZoomLevel() * 0.1);
479 480
		fontSize *= editorZoomLevelMultiplier;
		lineHeight *= editorZoomLevelMultiplier;
E
Erich Gamma 已提交
481

482 483 484 485 486 487
		let disableTranslate3d = toBoolean(opts.disableTranslate3d);
		let canUseTranslate3d = this._getCanUseTranslate3d();
		if (disableTranslate3d) {
			canUseTranslate3d = false;
		}

488
		return InternalEditorOptionsHelper.createInternalEditorOptions(
E
Erich Gamma 已提交
489 490 491
			this.getOuterWidth(),
			this.getOuterHeight(),
			opts,
A
Alex Dima 已提交
492 493
			this.readConfiguration(new editorCommon.BareFontInfo({
				fontFamily: fontFamily,
494
				fontWeight: fontWeight,
A
Alex Dima 已提交
495 496 497
				fontSize: fontSize,
				lineHeight: lineHeight
			})),
498
			editorClassName,
E
Erich Gamma 已提交
499
			this._isDominatedByLongLines,
500
			this._maxLineNumber,
501
			canUseTranslate3d
E
Erich Gamma 已提交
502 503 504
		);
	}

A
Alex Dima 已提交
505
	public updateOptions(newOptions:editorCommon.IEditorOptions): void {
E
Erich Gamma 已提交
506 507 508 509 510 511 512 513 514
		this._configWithDefaults.updateOptions(newOptions);
		this._recomputeOptions();
	}

	public setIsDominatedByLongLines(isDominatedByLongLines:boolean): void {
		this._isDominatedByLongLines = isDominatedByLongLines;
		this._recomputeOptions();
	}

515 516
	public setMaxLineNumber(maxLineNumber:number): void {
		this._maxLineNumber = maxLineNumber;
E
Erich Gamma 已提交
517 518 519
		this._recomputeOptions();
	}

520
	protected abstract _getEditorClassName(theme:string, fontLigatures:boolean): string;
E
Erich Gamma 已提交
521

522
	protected abstract getOuterWidth(): number;
E
Erich Gamma 已提交
523

524
	protected abstract getOuterHeight(): number;
E
Erich Gamma 已提交
525

526 527
	protected abstract _getCanUseTranslate3d(): boolean;

528
	protected abstract readConfiguration(styling: editorCommon.BareFontInfo): editorCommon.FontInfo;
E
Erich Gamma 已提交
529 530 531 532 533 534 535 536 537 538 539 540
}

/**
 * Helper to update Monaco Editor Settings from configurations service.
 */
export class EditorConfiguration {
	public static EDITOR_SECTION = 'editor';
	public static DIFF_EDITOR_SECTION = 'diffEditor';

	/**
	 * Ask the provided configuration service to apply its configuration to the provided editor.
	 */
541
	public static apply(config: any, editor: editorCommon.IEditor): void {
E
Erich Gamma 已提交
542 543 544 545
		if (!config) {
			return;
		}

546 547 548 549 550 551
		// Editor Settings (Code Editor, Diff, Terminal)
		if (editor && typeof editor.updateOptions === 'function') {
			let type = editor.getEditorType();
			if (type !== editorCommon.EditorType.ICodeEditor && type !== editorCommon.EditorType.IDiffEditor) {
				return;
			}
E
Erich Gamma 已提交
552

553 554 555 556 557 558 559 560
			let editorConfig = config[EditorConfiguration.EDITOR_SECTION];
			if (type === editorCommon.EditorType.IDiffEditor) {
				let diffEditorConfig = config[EditorConfiguration.DIFF_EDITOR_SECTION];
				if (diffEditorConfig) {
					if (!editorConfig) {
						editorConfig = diffEditorConfig;
					} else {
						editorConfig = objects.mixin(editorConfig, diffEditorConfig);
E
Erich Gamma 已提交
561 562
					}
				}
563
			}
E
Erich Gamma 已提交
564

565 566 567
			if (editorConfig) {
				delete editorConfig.readOnly; // Prevent someone from making editor readonly
				editor.updateOptions(editorConfig);
E
Erich Gamma 已提交
568 569 570 571 572
			}
		}
	}
}

A
Alex Dima 已提交
573
let configurationRegistry = <IConfigurationRegistry>Registry.as(Extensions.Configuration);
A
Alex Dima 已提交
574
let editorConfiguration:IConfigurationNode = {
E
Erich Gamma 已提交
575 576 577
	'id': 'editor',
	'order': 5,
	'type': 'object',
578
	'title': nls.localize('editorConfigurationTitle', "Editor"),
E
Erich Gamma 已提交
579 580 581 582 583 584
	'properties' : {
		'editor.fontFamily' : {
			'type': 'string',
			'default': DefaultConfig.editor.fontFamily,
			'description': nls.localize('fontFamily', "Controls the font family.")
		},
585 586 587 588 589
		'editor.fontWeight' : {
			'type': 'string',
			'default': DefaultConfig.editor.fontWeight,
			'description': nls.localize('fontWeight', "Controls the font weight.")
		},
E
Erich Gamma 已提交
590 591 592 593 594 595 596 597
		'editor.fontSize' : {
			'type': 'number',
			'default': DefaultConfig.editor.fontSize,
			'description': nls.localize('fontSize', "Controls the font size.")
		},
		'editor.lineHeight' : {
			'type': 'number',
			'default': DefaultConfig.editor.lineHeight,
598
			'description': nls.localize('lineHeight', "Controls the line height. Use 0 to compute the lineHeight from the fontSize.")
E
Erich Gamma 已提交
599 600 601 602 603 604 605 606 607 608 609
		},
		'editor.lineNumbers' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.lineNumbers,
			'description': nls.localize('lineNumbers', "Controls visibility of line numbers")
		},
		'editor.glyphMargin' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.glyphMargin,
			'description': nls.localize('glyphMargin', "Controls visibility of the glyph margin")
		},
610 611 612 613 614 615 616 617
		'editor.rulers' : {
			'type': 'array',
			'items': {
				'type': 'number'
			},
			'default': DefaultConfig.editor.rulers,
			'description': nls.localize('rulers', "Columns at which to show vertical rulers")
		},
A
Alex Dima 已提交
618 619 620 621 622
		'editor.wordSeparators' : {
			'type': 'string',
			'default': DefaultConfig.editor.wordSeparators,
			'description': nls.localize('wordSeparators', "Characters that will be used as word separators when doing word related navigations or operations")
		},
E
Erich Gamma 已提交
623
		'editor.tabSize' : {
624 625
			'type': 'number',
			'default': DEFAULT_INDENTATION.tabSize,
E
Erich Gamma 已提交
626
			'minimum': 1,
627
			'description': nls.localize('tabSize', "The number of spaces a tab is equal to. This setting is overriden based on the file contents when `editor.detectIndentation` is on."),
628
			'errorMessage': nls.localize('tabSize.errorMessage', "Expected 'number'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
629 630
		},
		'editor.insertSpaces' : {
631 632
			'type': 'boolean',
			'default': DEFAULT_INDENTATION.insertSpaces,
633
			'description': nls.localize('insertSpaces', "Insert spaces when pressing Tab. This setting is overriden based on the file contents when `editor.detectIndentation` is on."),
634
			'errorMessage': nls.localize('insertSpaces.errorMessage', "Expected 'boolean'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
635
		},
636 637 638
		'editor.detectIndentation' : {
			'type': 'boolean',
			'default': DEFAULT_INDENTATION.detectIndentation,
A
Alex Dima 已提交
639
			'description': nls.localize('detectIndentation', "When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents.")
640
		},
E
Erich Gamma 已提交
641 642 643 644 645 646 647 648 649 650 651 652 653 654
		'editor.roundedSelection' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.roundedSelection,
			'description': nls.localize('roundedSelection', "Controls if selections have rounded corners")
		},
		'editor.scrollBeyondLastLine' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.scrollBeyondLastLine,
			'description': nls.localize('scrollBeyondLastLine', "Controls if the editor will scroll beyond the last line")
		},
		'editor.wrappingColumn' : {
			'type': 'integer',
			'default': DefaultConfig.editor.wrappingColumn,
			'minimum': -1,
655
			'description': nls.localize('wrappingColumn', "Controls after how many characters the editor will wrap to the next line. Setting this to 0 turns on viewport width wrapping (word wrapping). Setting this to -1 forces the editor to never wrap.")
E
Erich Gamma 已提交
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
		},
		'editor.wrappingIndent' : {
			'type': 'string',
			'enum': ['none', 'same', 'indent'],
			'default': DefaultConfig.editor.wrappingIndent,
			'description': nls.localize('wrappingIndent', "Controls the indentation of wrapped lines. Can be one of 'none', 'same' or 'indent'.")
		},
		'editor.mouseWheelScrollSensitivity' : {
			'type': 'number',
			'default': DefaultConfig.editor.mouseWheelScrollSensitivity,
			'description': nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events")
		},
		'editor.quickSuggestions' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.quickSuggestions,
			'description': nls.localize('quickSuggestions', "Controls if quick suggestions should show up or not while typing")
		},
		'editor.quickSuggestionsDelay' : {
			'type': 'integer',
			'default': DefaultConfig.editor.quickSuggestionsDelay,
			'minimum': 0,
			'description': nls.localize('quickSuggestionsDelay', "Controls the delay in ms after which quick suggestions will show up")
		},
J
Joao Moreno 已提交
679 680 681 682 683
		'editor.parameterHints' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.parameterHints,
			'description': nls.localize('parameterHints', "Enables parameter hints")
		},
E
Erich Gamma 已提交
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
		'editor.autoClosingBrackets' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.autoClosingBrackets,
			'description': nls.localize('autoClosingBrackets', "Controls if the editor should automatically close brackets after opening them")
		},
		'editor.formatOnType' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.formatOnType,
			'description': nls.localize('formatOnType', "Controls if the editor should automatically format the line after typing")
		},
		'editor.suggestOnTriggerCharacters' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.suggestOnTriggerCharacters,
			'description': nls.localize('suggestOnTriggerCharacters', "Controls if suggestions should automatically show up when typing trigger characters")
		},
699 700 701 702 703
		'editor.acceptSuggestionOnEnter' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.acceptSuggestionOnEnter,
			'description': nls.localize('acceptSuggestionOnEnter', "Controls if suggestions should be accepted 'Enter' - in addition to 'Tab'. Helps to avoid ambiguity between inserting new lines or accepting suggestions.")
		},
704
		'editor.snippetSuggestions': {
705
			'type': 'string',
706 707 708
			'enum': ['top', 'bottom', 'inline', 'none'],
			'default': DefaultConfig.editor.snippetSuggestions,
			'description': nls.localize('snippetSuggestions', "Controls whether snippets are shown with other suggestions and how they are sorted.")
709
		},
710 711 712 713 714
		'editor.wordBasedSuggestions': {
			'type': 'boolean',
			'default': DefaultConfig.editor.wordBasedSuggestions,
			'description': nls.localize('wordBasedSuggestions', "Enable word based suggestions.")
		},
715 716 717
		'editor.tabCompletion': {
			'type': 'boolean',
			'default': DefaultConfig.editor.tabCompletion,
718
			'description': nls.localize('tabCompletion', "Insert snippets when their prefix matches. Works best when 'quickSuggestions' aren't enabled.")
719
		},
E
Erich Gamma 已提交
720 721 722 723 724 725 726 727 728 729
		'editor.selectionHighlight' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.selectionHighlight,
			'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight similar matches to the selection")
		},
		'editor.overviewRulerLanes' : {
			'type': 'integer',
			'default': 3,
			'description': nls.localize('overviewRulerLanes', "Controls the number of decorations that can show up at the same position in the overview ruler")
		},
730 731
		'editor.cursorBlinking' : {
			'type': 'string',
732
			'enum': ['blink', 'smooth', 'phase', 'expand', 'solid'],
733
			'default': DefaultConfig.editor.cursorBlinking,
734
			'description': nls.localize('cursorBlinking', "Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'")
735
		},
736 737 738 739 740
		'editor.mouseWheelZoom': {
			'type': 'boolean',
			'default': DefaultConfig.editor.mouseWheelZoom,
			'description': nls.localize('mouseWheelZoom', "Zoom the font of the editor when using mouse wheel and holding Ctrl")
		},
M
markrendle 已提交
741 742
		'editor.cursorStyle' : {
			'type': 'string',
743
			'enum': ['block', 'line', 'underline'],
M
markrendle 已提交
744
			'default': DefaultConfig.editor.cursorStyle,
745
			'description': nls.localize('cursorStyle', "Controls the cursor style, accepted values are 'block', 'line' and 'underline'")
M
markrendle 已提交
746
		},
747 748 749 750 751
		'editor.fontLigatures' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.fontLigatures,
			'description': nls.localize('fontLigatures', "Enables font ligatures")
		},
E
Erich Gamma 已提交
752 753 754 755 756 757 758 759 760 761
		'editor.hideCursorInOverviewRuler' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.hideCursorInOverviewRuler,
			'description': nls.localize('hideCursorInOverviewRuler', "Controls if the cursor should be hidden in the overview ruler.")
		},
		'editor.renderWhitespace': {
			'type': 'boolean',
			default: DefaultConfig.editor.renderWhitespace,
			description: nls.localize('renderWhitespace', "Controls whether the editor should render whitespace characters")
		},
762 763 764 765 766
		'editor.renderControlCharacters': {
			'type': 'boolean',
			default: DefaultConfig.editor.renderControlCharacters,
			description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters")
		},
767 768 769 770 771
		'editor.renderIndentGuides': {
			'type': 'boolean',
			default: DefaultConfig.editor.renderIndentGuides,
			description: nls.localize('renderIndentGuides', "Controls whether the editor should render indent guides")
		},
772
		'editor.codeLens' : {
E
Erich Gamma 已提交
773
			'type': 'boolean',
774 775
			'default': DefaultConfig.editor.codeLens,
			'description': nls.localize('codeLens', "Controls if the editor shows code lenses")
E
Erich Gamma 已提交
776
		},
M
Martin Aeschlimann 已提交
777 778 779
		'editor.folding' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.folding,
780
			'description': nls.localize('folding', "Controls whether the editor has code folding enabled")
M
Martin Aeschlimann 已提交
781
		},
782 783 784 785 786 787 788
		'editor.useTabStops' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.useTabStops,
			'description': nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops")
		},
		'editor.trimAutoWhitespace' : {
			'type': 'boolean',
789
			'default': DEFAULT_TRIM_AUTO_WHITESPACE,
790 791
			'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace")
		},
792
		'editor.stablePeek' : {
793
			'type': 'boolean',
794
			'default': false,
795
			'description': nls.localize('stablePeek', "Keep peek editors open even when double clicking their content or when hitting Escape.")
796
		},
E
Erich Gamma 已提交
797 798 799 800 801 802 803 804 805 806 807
		'diffEditor.renderSideBySide' : {
			'type': 'boolean',
			'default': true,
			'description': nls.localize('sideBySide', "Controls if the diff editor shows the diff side by side or inline")
		},
		'diffEditor.ignoreTrimWhitespace' : {
			'type': 'boolean',
			'default': true,
			'description': nls.localize('ignoreTrimWhitespace', "Controls if the diff editor shows changes in leading or trailing whitespace as diffs")
		}
	}
A
Alex Dima 已提交
808 809 810 811 812 813 814 815 816 817 818
};

if (platform.isLinux) {
	editorConfiguration['properties']['editor.selectionClipboard'] = {
		'type': 'boolean',
		'default': DefaultConfig.editor.selectionClipboard,
		'description': nls.localize('selectionClipboard', "Controls if the Linux primary clipboard should be supported.")
	};
}

configurationRegistry.registerConfiguration(editorConfiguration);