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

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
			snippetOrder: opts.snippetOrder,
E
Erich Gamma 已提交
265 266
			selectionHighlight: toBoolean(opts.selectionHighlight),
			referenceInfos: toBoolean(opts.referenceInfos),
M
Martin Aeschlimann 已提交
267
			folding: toBoolean(opts.folding),
A
Alex Dima 已提交
268 269
		});

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

A
Alex Dima 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297
	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 已提交
298 299
		let horizontalScrollbarSize = toIntegerWithDefault(raw.horizontalScrollbarSize, 10);
		let verticalScrollbarSize = toIntegerWithDefault(raw.verticalScrollbarSize, 14);
A
Alex Dima 已提交
300 301 302
		return new editorCommon.InternalEditorScrollbarOptions({
			vertical: visibilityFromString(raw.vertical),
			horizontal: visibilityFromString(raw.horizontal),
E
Erich Gamma 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

			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 已提交
318
		});
E
Erich Gamma 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	}
}

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 已提交
334
	let r = parseFloat(source);
E
Erich Gamma 已提交
335 336 337 338 339 340
	if (isNaN(r)) {
		r = defaultValue;
	}
	return r;
}

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

351 352 353 354 355 356 357 358 359 360
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 已提交
361 362 363 364 365 366 367 368 369 370
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 已提交
371 372 373 374 375 376 377 378 379 380 381
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;
}

382
function cursorBlinkingStyleFromString(cursorBlinkingStyle: string): editorCommon.TextEditorCursorBlinkingStyle {
383 384 385 386 387 388 389 390 391 392 393 394
	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;
395 396 397 398
	}
	return editorCommon.TextEditorCursorBlinkingStyle.Blink;
}

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

interface IValidatedIndentationOptions {
	tabSizeIsAuto: boolean;
	tabSize: number;
	insertSpacesIsAuto: boolean;
	insertSpaces: boolean;
}

413 414 415 416 417 418 419 420
export interface IElementSizeObserver {
	startObserving(): void;
	observe(dimension?:editorCommon.IDimension): void;
	dispose(): void;
	getWidth(): number;
	getHeight(): number;
}

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

423 424
	public editor:editorCommon.InternalEditorOptions;
	public editorClone:editorCommon.InternalEditorOptions;
E
Erich Gamma 已提交
425 426

	protected _configWithDefaults:ConfigurationWithDefaults;
427
	protected _elementSizeObserver: IElementSizeObserver;
E
Erich Gamma 已提交
428
	private _isDominatedByLongLines:boolean;
429
	private _maxLineNumber:number;
E
Erich Gamma 已提交
430

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

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

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

	protected _recomputeOptions(): void {
451 452
		this._setOptions(this._computeInternalOptions());
	}
453

454 455 456
	private _setOptions(newOptions:editorCommon.InternalEditorOptions): void {
		if (this.editor && this.editor.equals(newOptions)) {
			return;
E
Erich Gamma 已提交
457 458
		}

459 460 461 462
		let changeEvent = this.editor.createChangeEvent(newOptions);
		this.editor = newOptions;
		this.editorClone = this.editor.clone();
		this._onDidChange.fire(changeEvent);
E
Erich Gamma 已提交
463 464
	}

A
Alex Dima 已提交
465
	public getRawOptions(): editorCommon.IEditorOptions {
E
Erich Gamma 已提交
466 467 468
		return this._configWithDefaults.getEditorOptions();
	}

469
	private _computeInternalOptions(): editorCommon.InternalEditorOptions {
E
Erich Gamma 已提交
470 471
		let opts = this._configWithDefaults.getEditorOptions();

472
		let editorClassName = this._getEditorClassName(opts.theme, toBoolean(opts.fontLigatures));
473 474
		let fontFamily = String(opts.fontFamily) || DefaultConfig.editor.fontFamily;
		let fontSize = toInteger(opts.fontSize, 0, 100) || DefaultConfig.editor.fontSize;
E
Erich Gamma 已提交
475

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

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

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

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

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

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

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

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

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

527 528
	protected abstract _getCanUseTranslate3d(): boolean;

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

/**
 * 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.
	 */
A
Alex Dima 已提交
542 543
	public static apply(config:any, editor?:editorCommon.IEditor): void;
	public static apply(config:any, editor?:editorCommon.IEditor[]): void;
E
Erich Gamma 已提交
544 545 546 547 548
	public static apply(config:any, editorOrArray?:any): void {
		if (!config) {
			return;
		}

A
Alex Dima 已提交
549
		let editors:editorCommon.IEditor[] = editorOrArray;
E
Erich Gamma 已提交
550 551 552 553
		if (!Array.isArray(editorOrArray)) {
			editors = [editorOrArray];
		}

A
Alex Dima 已提交
554 555
		for (let i = 0; i < editors.length; i++) {
			let editor = editors[i];
E
Erich Gamma 已提交
556 557 558

			// Editor Settings (Code Editor, Diff, Terminal)
			if (editor && typeof editor.updateOptions === 'function') {
A
Alex Dima 已提交
559
				let type = editor.getEditorType();
A
Alex Dima 已提交
560
				if (type !== editorCommon.EditorType.ICodeEditor && type !== editorCommon.EditorType.IDiffEditor) {
E
Erich Gamma 已提交
561 562 563
					continue;
				}

A
Alex Dima 已提交
564
				let editorConfig = config[EditorConfiguration.EDITOR_SECTION];
A
Alex Dima 已提交
565
				if (type === editorCommon.EditorType.IDiffEditor) {
A
Alex Dima 已提交
566
					let diffEditorConfig = config[EditorConfiguration.DIFF_EDITOR_SECTION];
E
Erich Gamma 已提交
567 568 569 570
					if (diffEditorConfig) {
						if (!editorConfig) {
							editorConfig = diffEditorConfig;
						} else {
A
Alex Dima 已提交
571
							editorConfig = objects.mixin(editorConfig, diffEditorConfig);
E
Erich Gamma 已提交
572 573 574 575 576 577 578 579 580 581 582 583 584
						}
					}
				}

				if (editorConfig) {
					delete editorConfig.readOnly; // Prevent someone from making editor readonly
					editor.updateOptions(editorConfig);
				}
			}
		}
	}
}

A
Alex Dima 已提交
585
let configurationRegistry = <IConfigurationRegistry>Registry.as(Extensions.Configuration);
A
Alex Dima 已提交
586
let editorConfiguration:IConfigurationNode = {
E
Erich Gamma 已提交
587 588 589
	'id': 'editor',
	'order': 5,
	'type': 'object',
590
	'title': nls.localize('editorConfigurationTitle', "Editor"),
E
Erich Gamma 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603 604
	'properties' : {
		'editor.fontFamily' : {
			'type': 'string',
			'default': DefaultConfig.editor.fontFamily,
			'description': nls.localize('fontFamily', "Controls the font family.")
		},
		'editor.fontSize' : {
			'type': 'number',
			'default': DefaultConfig.editor.fontSize,
			'description': nls.localize('fontSize', "Controls the font size.")
		},
		'editor.lineHeight' : {
			'type': 'number',
			'default': DefaultConfig.editor.lineHeight,
605
			'description': nls.localize('lineHeight', "Controls the line height. Use 0 to compute the lineHeight from the fontSize.")
E
Erich Gamma 已提交
606 607 608 609 610 611 612 613 614 615 616
		},
		'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")
		},
617 618 619 620 621 622 623 624
		'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 已提交
625 626 627 628 629
		'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 已提交
630
		'editor.tabSize' : {
631 632
			'type': 'number',
			'default': DEFAULT_INDENTATION.tabSize,
E
Erich Gamma 已提交
633
			'minimum': 1,
634 635
			'description': nls.localize('tabSize', "The number of spaces a tab is equal to."),
			'errorMessage': nls.localize('tabSize.errorMessage', "Expected 'number'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
636 637
		},
		'editor.insertSpaces' : {
638 639
			'type': 'boolean',
			'default': DEFAULT_INDENTATION.insertSpaces,
640 641
			'description': nls.localize('insertSpaces', "Insert spaces when pressing Tab."),
			'errorMessage': nls.localize('insertSpaces.errorMessage', "Expected 'boolean'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
642
		},
643 644 645
		'editor.detectIndentation' : {
			'type': 'boolean',
			'default': DEFAULT_INDENTATION.detectIndentation,
A
Alex Dima 已提交
646
			'description': nls.localize('detectIndentation', "When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents.")
647
		},
E
Erich Gamma 已提交
648 649 650 651 652 653 654 655 656 657 658 659 660 661
		'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,
662
			'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 已提交
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
		},
		'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 已提交
686 687 688 689 690
		'editor.parameterHints' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.parameterHints,
			'description': nls.localize('parameterHints', "Enables parameter hints")
		},
E
Erich Gamma 已提交
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
		'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")
		},
706 707 708 709 710
		'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.")
		},
711 712 713 714 715 716
		'editor.snippetOrder': {
			'type': 'string',
			'enum': ['top', 'bottom', 'normal'],
			'default': 'normal',
			'description': nls.localize('snippetOrder', "Controls how snippets are sorted when shown with other suggestions.")
		},
E
Erich Gamma 已提交
717 718 719 720 721 722 723 724 725 726
		'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")
		},
727 728
		'editor.cursorBlinking' : {
			'type': 'string',
729
			'enum': ['blink', 'smooth', 'phase', 'expand', 'solid'],
730
			'default': DefaultConfig.editor.cursorBlinking,
731
			'description': nls.localize('cursorBlinking', "Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'")
732
		},
733 734 735 736 737
		'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 已提交
738 739
		'editor.cursorStyle' : {
			'type': 'string',
740
			'enum': ['block', 'line', 'underline'],
M
markrendle 已提交
741
			'default': DefaultConfig.editor.cursorStyle,
742
			'description': nls.localize('cursorStyle', "Controls the cursor style, accepted values are 'block', 'line' and 'underline'")
M
markrendle 已提交
743
		},
744 745 746 747 748
		'editor.fontLigatures' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.fontLigatures,
			'description': nls.localize('fontLigatures', "Enables font ligatures")
		},
E
Erich Gamma 已提交
749 750 751 752 753 754 755 756 757 758
		'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")
		},
759 760 761 762 763
		'editor.renderControlCharacters': {
			'type': 'boolean',
			default: DefaultConfig.editor.renderControlCharacters,
			description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters")
		},
764 765 766 767 768
		'editor.renderIndentGuides': {
			'type': 'boolean',
			default: DefaultConfig.editor.renderIndentGuides,
			description: nls.localize('renderIndentGuides', "Controls whether the editor should render indent guides")
		},
E
Erich Gamma 已提交
769 770 771 772 773
		'editor.referenceInfos' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.referenceInfos,
			'description': nls.localize('referenceInfos', "Controls if the editor shows reference information for the modes that support it")
		},
M
Martin Aeschlimann 已提交
774 775 776
		'editor.folding' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.folding,
777
			'description': nls.localize('folding', "Controls whether the editor has code folding enabled")
M
Martin Aeschlimann 已提交
778
		},
779 780 781 782 783 784 785
		'editor.useTabStops' : {
			'type': 'boolean',
			'default': DefaultConfig.editor.useTabStops,
			'description': nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops")
		},
		'editor.trimAutoWhitespace' : {
			'type': 'boolean',
786
			'default': DEFAULT_TRIM_AUTO_WHITESPACE,
787 788
			'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace")
		},
789
		'editor.stablePeek' : {
790
			'type': 'boolean',
791
			'default': false,
792
			'description': nls.localize('stablePeek', "Keep peek editors open even when double clicking their content or when hitting Escape.")
793
		},
E
Erich Gamma 已提交
794 795 796 797 798 799 800 801 802 803 804
		'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 已提交
805 806 807 808 809 810 811 812 813 814 815
};

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);