commonEditorConfig.ts 34.7 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
import * as nls from 'vs/nls';
M
Matt Bierner 已提交
8
import { Event, Emitter } from 'vs/base/common/event';
J
Johannes Rieken 已提交
9
import { Disposable } from 'vs/base/common/lifecycle';
A
Alex Dima 已提交
10
import * as objects from 'vs/base/common/objects';
A
Alex Dima 已提交
11
import * as platform from 'vs/base/common/platform';
12
import { Extensions, IConfigurationRegistry, IConfigurationNode, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
13
import { Registry } from 'vs/platform/registry/common/platform';
A
Alex Dima 已提交
14
import * as editorCommon from 'vs/editor/common/editorCommon';
15
import { FontInfo, BareFontInfo } from 'vs/editor/common/config/fontInfo';
A
Alex Dima 已提交
16
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
17
import * as editorOptions from 'vs/editor/common/config/editorOptions';
18 19 20
import EDITOR_DEFAULTS = editorOptions.EDITOR_DEFAULTS;
import EDITOR_FONT_DEFAULTS = editorOptions.EDITOR_FONT_DEFAULTS;
import EDITOR_MODEL_DEFAULTS = editorOptions.EDITOR_MODEL_DEFAULTS;
E
Erich Gamma 已提交
21

22 23 24 25 26 27 28
/**
 * 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 {
J
Johannes Rieken 已提交
29
	onDidChangeTabFocus: Event<boolean>;
30
	getTabFocusMode(): boolean;
J
Johannes Rieken 已提交
31
	setTabFocusMode(tabFocusMode: boolean): void;
32 33
}

A
Alex Dima 已提交
34
export const TabFocus: ITabFocus = new class implements ITabFocus {
35 36
	private _tabFocus: boolean = false;

M
Matt Bierner 已提交
37
	private readonly _onDidChangeTabFocus: Emitter<boolean> = new Emitter<boolean>();
38
	public readonly onDidChangeTabFocus: Event<boolean> = this._onDidChangeTabFocus.event;
39 40 41 42 43

	public getTabFocusMode(): boolean {
		return this._tabFocus;
	}

J
Johannes Rieken 已提交
44
	public setTabFocusMode(tabFocusMode: boolean): void {
45 46 47 48 49 50 51 52 53
		if (this._tabFocus === tabFocusMode) {
			return;
		}

		this._tabFocus = tabFocusMode;
		this._onDidChangeTabFocus.fire(this._tabFocus);
	}
};

A
Alex Dima 已提交
54 55 56 57
export interface IEnvConfiguration {
	extraEditorClassName: string;
	outerWidth: number;
	outerHeight: number;
58
	emptySelectionClipboard: boolean;
A
Alex Dima 已提交
59 60
	pixelRatio: number;
	zoomLevel: number;
61
	accessibilitySupport: platform.AccessibilitySupport;
62 63
}

64 65
const hasOwnProperty = Object.hasOwnProperty;

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

68 69
	protected _rawOptions: editorOptions.IEditorOptions;
	protected _validatedOptions: editorOptions.IValidatedEditorOptions;
70
	public editor: editorOptions.InternalEditorOptions;
J
Johannes Rieken 已提交
71
	private _isDominatedByLongLines: boolean;
72
	private _lineNumbersDigitCount: number;
E
Erich Gamma 已提交
73

74
	private _onDidChange = this._register(new Emitter<editorOptions.IConfigurationChangedEvent>());
75
	public readonly onDidChange: Event<editorOptions.IConfigurationChangedEvent> = this._onDidChange.event;
A
Alex Dima 已提交
76

A
Alex Dima 已提交
77
	constructor(options: editorOptions.IEditorOptions) {
A
Alex Dima 已提交
78
		super();
79

80 81 82 83 84
		// Do a "deep clone of sorts" on the incoming options
		this._rawOptions = objects.mixin({}, options || {});
		this._rawOptions.scrollbar = objects.mixin({}, this._rawOptions.scrollbar || {});
		this._rawOptions.minimap = objects.mixin({}, this._rawOptions.minimap || {});
		this._rawOptions.find = objects.mixin({}, this._rawOptions.find || {});
A
Alex Dima 已提交
85
		this._rawOptions.hover = objects.mixin({}, this._rawOptions.hover || {});
86

87
		this._validatedOptions = editorOptions.EditorOptionsValidator.validate(this._rawOptions, EDITOR_DEFAULTS);
A
Alex Dima 已提交
88
		this.editor = null;
E
Erich Gamma 已提交
89
		this._isDominatedByLongLines = false;
90
		this._lineNumbersDigitCount = 1;
A
Alex Dima 已提交
91

92
		this._register(EditorZoom.onDidChangeZoomLevel(_ => this._recomputeOptions()));
93
		this._register(TabFocus.onDidChangeTabFocus(_ => this._recomputeOptions()));
E
Erich Gamma 已提交
94 95
	}

A
Alex Dima 已提交
96 97 98
	public observeReferenceElement(dimension?: editorCommon.IDimension): void {
	}

E
Erich Gamma 已提交
99 100 101 102 103
	public dispose(): void {
		super.dispose();
	}

	protected _recomputeOptions(): void {
A
Alex Dima 已提交
104 105
		const oldOptions = this.editor;
		const newOptions = this._computeInternalOptions();
106

A
Alex Dima 已提交
107
		if (oldOptions && oldOptions.equals(newOptions)) {
108
			return;
E
Erich Gamma 已提交
109 110
		}

111
		this.editor = newOptions;
E
Erich Gamma 已提交
112

A
Alex Dima 已提交
113 114
		if (oldOptions) {
			this._onDidChange.fire(oldOptions.createChangeEvent(newOptions));
115
		}
E
Erich Gamma 已提交
116
	}
117

118
	public getRawOptions(): editorOptions.IEditorOptions {
119
		return this._rawOptions;
E
Erich Gamma 已提交
120
	}
121

122
	private _computeInternalOptions(): editorOptions.InternalEditorOptions {
123
		const opts = this._validatedOptions;
A
Alex Dima 已提交
124 125
		const partialEnv = this._getEnvConfiguration();
		const bareFontInfo = BareFontInfo.createFromRawSettings(this._rawOptions, partialEnv.zoomLevel);
A
Alex Dima 已提交
126
		const env: editorOptions.IEnvironmentalOptions = {
A
Alex Dima 已提交
127 128
			outerWidth: partialEnv.outerWidth,
			outerHeight: partialEnv.outerHeight,
129
			fontInfo: this.readConfiguration(bareFontInfo),
130
			extraEditorClassName: partialEnv.extraEditorClassName,
131 132
			isDominatedByLongLines: this._isDominatedByLongLines,
			lineNumbersDigitCount: this._lineNumbersDigitCount,
133
			emptySelectionClipboard: partialEnv.emptySelectionClipboard,
A
Alex Dima 已提交
134
			pixelRatio: partialEnv.pixelRatio,
135 136
			tabFocusMode: TabFocus.getTabFocusMode(),
			accessibilitySupport: partialEnv.accessibilitySupport
A
Alex Dima 已提交
137
		};
138
		return editorOptions.InternalEditorOptionsFactory.createInternalEditorOptions(env, opts);
E
Erich Gamma 已提交
139 140
	}

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
	private static _primitiveArrayEquals(a: any[], b: any[]): boolean {
		if (a.length !== b.length) {
			return false;
		}
		for (let i = 0; i < a.length; i++) {
			if (a[i] !== b[i]) {
				return false;
			}
		}
		return true;
	}

	private static _subsetEquals(base: object, subset: object): boolean {
		for (let key in subset) {
			if (hasOwnProperty.call(subset, key)) {
				const subsetValue = subset[key];
				const baseValue = base[key];

				if (baseValue === subsetValue) {
					continue;
				}
				if (Array.isArray(baseValue) && Array.isArray(subsetValue)) {
					if (!this._primitiveArrayEquals(baseValue, subsetValue)) {
						return false;
					}
					continue;
				}
				if (typeof baseValue === 'object' && typeof subsetValue === 'object') {
					if (!this._subsetEquals(baseValue, subsetValue)) {
						return false;
					}
					continue;
				}

				return false;
			}
		}
		return true;
	}

181
	public updateOptions(newOptions: editorOptions.IEditorOptions): void {
182 183 184 185 186 187
		if (typeof newOptions === 'undefined') {
			return;
		}
		if (CommonEditorConfiguration._subsetEquals(this._rawOptions, newOptions)) {
			return;
		}
188
		this._rawOptions = objects.mixin(this._rawOptions, newOptions || {});
189
		this._validatedOptions = editorOptions.EditorOptionsValidator.validate(this._rawOptions, EDITOR_DEFAULTS);
E
Erich Gamma 已提交
190 191 192
		this._recomputeOptions();
	}

J
Johannes Rieken 已提交
193
	public setIsDominatedByLongLines(isDominatedByLongLines: boolean): void {
E
Erich Gamma 已提交
194 195 196 197
		this._isDominatedByLongLines = isDominatedByLongLines;
		this._recomputeOptions();
	}

J
Johannes Rieken 已提交
198
	public setMaxLineNumber(maxLineNumber: number): void {
199
		let digitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
200
		if (this._lineNumbersDigitCount === digitCount) {
A
Alex Dima 已提交
201 202
			return;
		}
203
		this._lineNumbersDigitCount = digitCount;
E
Erich Gamma 已提交
204 205 206
		this._recomputeOptions();
	}

207
	private static _digitCount(n: number): number {
A
Alex Dima 已提交
208
		let r = 0;
209 210 211 212 213 214
		while (n) {
			n = Math.floor(n / 10);
			r++;
		}
		return r ? r : 1;
	}
A
Alex Dima 已提交
215
	protected abstract _getEnvConfiguration(): IEnvConfiguration;
216

217
	protected abstract readConfiguration(styling: BareFontInfo): FontInfo;
218

E
Erich Gamma 已提交
219 220
}

221
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
222
const editorConfiguration: IConfigurationNode = {
E
Erich Gamma 已提交
223 224 225
	'id': 'editor',
	'order': 5,
	'type': 'object',
226
	'title': nls.localize('editorConfigurationTitle', "Editor"),
227
	'overridable': true,
S
Sandeep Somavarapu 已提交
228
	'scope': ConfigurationScope.RESOURCE,
J
Johannes Rieken 已提交
229 230
	'properties': {
		'editor.fontFamily': {
E
Erich Gamma 已提交
231
			'type': 'string',
232
			'default': EDITOR_FONT_DEFAULTS.fontFamily,
E
Erich Gamma 已提交
233 234
			'description': nls.localize('fontFamily', "Controls the font family.")
		},
J
Johannes Rieken 已提交
235
		'editor.fontWeight': {
236
			'type': 'string',
237
			'enum': ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
238
			'default': EDITOR_FONT_DEFAULTS.fontWeight,
239 240
			'description': nls.localize('fontWeight', "Controls the font weight.")
		},
J
Johannes Rieken 已提交
241
		'editor.fontSize': {
E
Erich Gamma 已提交
242
			'type': 'number',
243
			'default': EDITOR_FONT_DEFAULTS.fontSize,
244
			'description': nls.localize('fontSize', "Controls the font size in pixels.")
E
Erich Gamma 已提交
245
		},
J
Johannes Rieken 已提交
246
		'editor.lineHeight': {
E
Erich Gamma 已提交
247
			'type': 'number',
248
			'default': EDITOR_FONT_DEFAULTS.lineHeight,
249
			'description': nls.localize('lineHeight', "Controls the line height. Use 0 to compute the lineHeight from the fontSize.")
E
Erich Gamma 已提交
250
		},
251 252
		'editor.letterSpacing': {
			'type': 'number',
253
			'default': EDITOR_FONT_DEFAULTS.letterSpacing,
254 255
			'description': nls.localize('letterSpacing', "Controls the letter spacing in pixels.")
		},
J
Johannes Rieken 已提交
256
		'editor.lineNumbers': {
257
			'type': 'string',
258
			'enum': ['off', 'on', 'relative', 'interval'],
259 260 261
			'enumDescriptions': [
				nls.localize('lineNumbers.off', "Line numbers are not rendered."),
				nls.localize('lineNumbers.on', "Line numbers are rendered as absolute number."),
262 263
				nls.localize('lineNumbers.relative', "Line numbers are rendered as distance in lines to cursor position."),
				nls.localize('lineNumbers.interval', "Line numbers are rendered every 10 lines.")
264
			],
265
			'default': 'on',
A
Alex Dima 已提交
266
			'description': nls.localize('lineNumbers', "Controls the display of line numbers.")
E
Erich Gamma 已提交
267
		},
J
Johannes Rieken 已提交
268
		'editor.rulers': {
269 270 271 272
			'type': 'array',
			'items': {
				'type': 'number'
			},
A
Alex Dima 已提交
273
			'default': EDITOR_DEFAULTS.viewInfo.rulers,
274
			'description': nls.localize('rulers', "Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty")
275
		},
J
Johannes Rieken 已提交
276
		'editor.wordSeparators': {
A
Alex Dima 已提交
277
			'type': 'string',
278
			'default': EDITOR_DEFAULTS.wordSeparators,
A
Alex Dima 已提交
279 280
			'description': nls.localize('wordSeparators', "Characters that will be used as word separators when doing word related navigations or operations")
		},
J
Johannes Rieken 已提交
281
		'editor.tabSize': {
282
			'type': 'number',
283
			'default': EDITOR_MODEL_DEFAULTS.tabSize,
E
Erich Gamma 已提交
284
			'minimum': 1,
285
			'description': nls.localize('tabSize', "The number of spaces a tab is equal to. This setting is overridden based on the file contents when `editor.detectIndentation` is on."),
286
			'errorMessage': nls.localize('tabSize.errorMessage', "Expected 'number'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
287
		},
J
Johannes Rieken 已提交
288
		'editor.insertSpaces': {
289
			'type': 'boolean',
290
			'default': EDITOR_MODEL_DEFAULTS.insertSpaces,
291
			'description': nls.localize('insertSpaces', "Insert spaces when pressing Tab. This setting is overridden based on the file contents when `editor.detectIndentation` is on."),
292
			'errorMessage': nls.localize('insertSpaces.errorMessage', "Expected 'boolean'. Note that the value \"auto\" has been replaced by the `editor.detectIndentation` setting.")
E
Erich Gamma 已提交
293
		},
J
Johannes Rieken 已提交
294
		'editor.detectIndentation': {
295
			'type': 'boolean',
296
			'default': EDITOR_MODEL_DEFAULTS.detectIndentation,
A
Alex Dima 已提交
297
			'description': nls.localize('detectIndentation', "When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents.")
298
		},
J
Johannes Rieken 已提交
299
		'editor.roundedSelection': {
E
Erich Gamma 已提交
300
			'type': 'boolean',
A
Alex Dima 已提交
301
			'default': EDITOR_DEFAULTS.viewInfo.roundedSelection,
E
Erich Gamma 已提交
302 303
			'description': nls.localize('roundedSelection', "Controls if selections have rounded corners")
		},
J
Johannes Rieken 已提交
304
		'editor.scrollBeyondLastLine': {
E
Erich Gamma 已提交
305
			'type': 'boolean',
A
Alex Dima 已提交
306
			'default': EDITOR_DEFAULTS.viewInfo.scrollBeyondLastLine,
E
Erich Gamma 已提交
307 308
			'description': nls.localize('scrollBeyondLastLine', "Controls if the editor will scroll beyond the last line")
		},
309 310 311
		'editor.scrollBeyondLastColumn': {
			'type': 'number',
			'default': EDITOR_DEFAULTS.viewInfo.scrollBeyondLastColumn,
A
Alex Dima 已提交
312
			'description': nls.localize('scrollBeyondLastColumn', "Controls the number of extra characters beyond which the editor will scroll horizontally")
313
		},
314 315 316 317 318
		'editor.smoothScrolling': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.viewInfo.smoothScrolling,
			'description': nls.localize('smoothScrolling', "Controls if the editor will scroll using an animation")
		},
319 320
		'editor.minimap.enabled': {
			'type': 'boolean',
A
Alex Dima 已提交
321
			'default': EDITOR_DEFAULTS.viewInfo.minimap.enabled,
322 323
			'description': nls.localize('minimap.enabled', "Controls if the minimap is shown")
		},
324 325 326 327
		'editor.minimap.side': {
			'type': 'string',
			'enum': ['left', 'right'],
			'default': EDITOR_DEFAULTS.viewInfo.minimap.side,
A
Alex Dima 已提交
328
			'description': nls.localize('minimap.side', "Controls the side where to render the minimap.")
329
		},
330 331 332 333
		'editor.minimap.showSlider': {
			'type': 'string',
			'enum': ['always', 'mouseover'],
			'default': EDITOR_DEFAULTS.viewInfo.minimap.showSlider,
A
Alex Dima 已提交
334
			'description': nls.localize('minimap.showSlider', "Controls whether the minimap slider is automatically hidden.")
335
		},
336
		'editor.minimap.renderCharacters': {
337
			'type': 'boolean',
A
Alex Dima 已提交
338
			'default': EDITOR_DEFAULTS.viewInfo.minimap.renderCharacters,
339
			'description': nls.localize('minimap.renderCharacters', "Render the actual characters on a line (as opposed to color blocks)")
340
		},
A
Alex Dima 已提交
341 342
		'editor.minimap.maxColumn': {
			'type': 'number',
A
Alex Dima 已提交
343
			'default': EDITOR_DEFAULTS.viewInfo.minimap.maxColumn,
A
Alex Dima 已提交
344 345
			'description': nls.localize('minimap.maxColumn', "Limit the width of the minimap to render at most a certain number of columns")
		},
A
Alex Dima 已提交
346 347 348 349 350
		'editor.hover.enabled': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.hover.enabled,
			'description': nls.localize('hover.enabled', "Controls if the hover is shown")
		},
351 352 353 354 355
		'editor.hover.delay': {
			'type': 'number',
			'default': EDITOR_DEFAULTS.contribInfo.hover.delay,
			'description': nls.localize('hover.delay', "Controls the delay after which to show the hover")
		},
356 357 358 359 360
		'editor.hover.sticky': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.hover.sticky,
			'description': nls.localize('hover.sticky', "Controls if the hover should remain visible when mouse is moved over it")
		},
361 362 363
		'editor.find.seedSearchStringFromSelection': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.find.seedSearchStringFromSelection,
364
			'description': nls.localize('find.seedSearchStringFromSelection', "Controls if we seed the search string in Find Widget from editor selection")
365
		},
R
rebornix 已提交
366 367 368 369 370
		'editor.find.autoFindInSelection': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.find.autoFindInSelection,
			'description': nls.localize('find.autoFindInSelection', "Controls if Find in Selection flag is turned on when multiple characters or lines of text are selected in the editor")
		},
371 372 373
		'editor.find.globalFindClipboard': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.find.globalFindClipboard,
374 375
			'description': nls.localize('find.globalFindClipboard', "Controls if the Find Widget should read or modify the shared find clipboard on macOS"),
			'included': platform.isMacintosh
376
		},
J
Johannes Rieken 已提交
377
		'editor.wordWrap': {
378
			'type': 'string',
A
Alex Dima 已提交
379
			'enum': ['off', 'on', 'wordWrapColumn', 'bounded'],
380 381 382
			'enumDescriptions': [
				nls.localize('wordWrap.off', "Lines will never wrap."),
				nls.localize('wordWrap.on', "Lines will wrap at the viewport width."),
A
Alex Dima 已提交
383 384 385 386 387 388
				nls.localize({
					key: 'wordWrap.wordWrapColumn',
					comment: [
						'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
					]
				}, "Lines will wrap at `editor.wordWrapColumn`."),
A
Alex Dima 已提交
389 390 391 392
				nls.localize({
					key: 'wordWrap.bounded',
					comment: [
						'- viewport means the edge of the visible window size.',
A
Alex Dima 已提交
393
						'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
A
Alex Dima 已提交
394 395
					]
				}, "Lines will wrap at the minimum of viewport and `editor.wordWrapColumn`."),
396
			],
397
			'default': EDITOR_DEFAULTS.wordWrap,
A
Alex Dima 已提交
398 399 400 401 402 403 404
			'description': nls.localize({
				key: 'wordWrap',
				comment: [
					'- \'off\', \'on\', \'wordWrapColumn\' and \'bounded\' refer to values the setting can take and should not be localized.',
					'- `editor.wordWrapColumn` refers to a different setting and should not be localized.'
				]
			}, "Controls how lines should wrap. Can be:\n - 'off' (disable wrapping),\n - 'on' (viewport wrapping),\n - 'wordWrapColumn' (wrap at `editor.wordWrapColumn`) or\n - 'bounded' (wrap at minimum of viewport and `editor.wordWrapColumn`).")
405 406 407
		},
		'editor.wordWrapColumn': {
			'type': 'integer',
408
			'default': EDITOR_DEFAULTS.wordWrapColumn,
409
			'minimum': 1,
A
Alex Dima 已提交
410 411 412 413 414 415 416
			'description': nls.localize({
				key: 'wordWrapColumn',
				comment: [
					'- `editor.wordWrap` refers to a different setting and should not be localized.',
					'- \'wordWrapColumn\' and \'bounded\' refer to values the different setting can take and should not be localized.'
				]
			}, "Controls the wrapping column of the editor when `editor.wordWrap` is 'wordWrapColumn' or 'bounded'.")
417
		},
J
Johannes Rieken 已提交
418
		'editor.wrappingIndent': {
E
Erich Gamma 已提交
419
			'type': 'string',
420
			'enum': ['none', 'same', 'indent', 'deepIndent'],
421
			'default': 'same',
422
			'description': nls.localize('wrappingIndent', "Controls the indentation of wrapped lines. Can be one of 'none', 'same', 'indent' or 'deepIndent'.")
E
Erich Gamma 已提交
423
		},
J
Johannes Rieken 已提交
424
		'editor.mouseWheelScrollSensitivity': {
E
Erich Gamma 已提交
425
			'type': 'number',
A
Alex Dima 已提交
426
			'default': EDITOR_DEFAULTS.viewInfo.scrollbar.mouseWheelScrollSensitivity,
E
Erich Gamma 已提交
427 428
			'description': nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events")
		},
429
		'editor.multiCursorModifier': {
430
			'type': 'string',
431 432
			'enum': ['ctrlCmd', 'alt'],
			'enumDescriptions': [
433 434
				nls.localize('multiCursorModifier.ctrlCmd', "Maps to `Control` on Windows and Linux and to `Command` on macOS."),
				nls.localize('multiCursorModifier.alt', "Maps to `Alt` on Windows and Linux and to `Option` on macOS.")
435
			],
436
			'default': 'alt',
437 438 439 440 441 442
			'description': nls.localize({
				key: 'multiCursorModifier',
				comment: [
					'- `ctrlCmd` refers to a value the setting can take and should not be localized.',
					'- `Control` and `Command` refer to the modifier keys Ctrl or Cmd on the keyboard and can be localized.'
				]
443
			}, "The modifier to be used to add multiple cursors with the mouse. `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on macOS. The Go To Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier.")
444
		},
A
Alex Dima 已提交
445
		'editor.multiCursorMergeOverlapping': {
446
			'type': 'boolean',
A
Alex Dima 已提交
447 448
			'default': EDITOR_DEFAULTS.multiCursorMergeOverlapping,
			'description': nls.localize('multiCursorMergeOverlapping', "Merge multiple cursors when they are overlapping.")
449
		},
J
Johannes Rieken 已提交
450
		'editor.quickSuggestions': {
451
			'anyOf': [
452 453 454
				{
					type: 'boolean',
				},
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
				{
					type: 'object',
					properties: {
						strings: {
							type: 'boolean',
							default: false,
							description: nls.localize('quickSuggestions.strings', "Enable quick suggestions inside strings.")
						},
						comments: {
							type: 'boolean',
							default: false,
							description: nls.localize('quickSuggestions.comments', "Enable quick suggestions inside comments.")
						},
						other: {
							type: 'boolean',
							default: true,
							description: nls.localize('quickSuggestions.other', "Enable quick suggestions outside of strings and comments.")
						},
					}
				}
			],
A
Alex Dima 已提交
476
			'default': EDITOR_DEFAULTS.contribInfo.quickSuggestions,
477
			'description': nls.localize('quickSuggestions', "Controls if suggestions should automatically show up while typing")
E
Erich Gamma 已提交
478
		},
J
Johannes Rieken 已提交
479
		'editor.quickSuggestionsDelay': {
E
Erich Gamma 已提交
480
			'type': 'integer',
A
Alex Dima 已提交
481
			'default': EDITOR_DEFAULTS.contribInfo.quickSuggestionsDelay,
E
Erich Gamma 已提交
482 483 484
			'minimum': 0,
			'description': nls.localize('quickSuggestionsDelay', "Controls the delay in ms after which quick suggestions will show up")
		},
J
Johannes Rieken 已提交
485
		'editor.parameterHints': {
J
Joao Moreno 已提交
486
			'type': 'boolean',
A
Alex Dima 已提交
487
			'default': EDITOR_DEFAULTS.contribInfo.parameterHints,
488
			'description': nls.localize('parameterHints', "Enables pop-up that shows parameter documentation and type information as you type")
J
Joao Moreno 已提交
489
		},
J
Johannes Rieken 已提交
490
		'editor.autoClosingBrackets': {
E
Erich Gamma 已提交
491
			'type': 'boolean',
492
			'default': EDITOR_DEFAULTS.autoClosingBrackets,
E
Erich Gamma 已提交
493 494
			'description': nls.localize('autoClosingBrackets', "Controls if the editor should automatically close brackets after opening them")
		},
J
Johannes Rieken 已提交
495
		'editor.formatOnType': {
E
Erich Gamma 已提交
496
			'type': 'boolean',
A
Alex Dima 已提交
497
			'default': EDITOR_DEFAULTS.contribInfo.formatOnType,
E
Erich Gamma 已提交
498 499
			'description': nls.localize('formatOnType', "Controls if the editor should automatically format the line after typing")
		},
500 501
		'editor.formatOnPaste': {
			'type': 'boolean',
A
Alex Dima 已提交
502
			'default': EDITOR_DEFAULTS.contribInfo.formatOnPaste,
503
			'description': nls.localize('formatOnPaste', "Controls if the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.")
504
		},
505 506 507
		'editor.autoIndent': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.autoIndent,
G
Guangcong Luo 已提交
508
			'description': nls.localize('autoIndent', "Controls if the editor should automatically adjust the indentation when users type, paste or move lines. Indentation rules of the language must be available.")
509
		},
J
Johannes Rieken 已提交
510
		'editor.suggestOnTriggerCharacters': {
E
Erich Gamma 已提交
511
			'type': 'boolean',
A
Alex Dima 已提交
512
			'default': EDITOR_DEFAULTS.contribInfo.suggestOnTriggerCharacters,
E
Erich Gamma 已提交
513 514
			'description': nls.localize('suggestOnTriggerCharacters', "Controls if suggestions should automatically show up when typing trigger characters")
		},
J
Johannes Rieken 已提交
515
		'editor.acceptSuggestionOnEnter': {
516 517
			'type': 'string',
			'enum': ['on', 'smart', 'off'],
A
Alex Dima 已提交
518
			'default': EDITOR_DEFAULTS.contribInfo.acceptSuggestionOnEnter,
519
			'description': nls.localize('acceptSuggestionOnEnter', "Controls if suggestions should be accepted on 'Enter' - in addition to 'Tab'. Helps to avoid ambiguity between inserting new lines or accepting suggestions. The value 'smart' means only accept a suggestion with Enter when it makes a textual change")
520 521 522
		},
		'editor.acceptSuggestionOnCommitCharacter': {
			'type': 'boolean',
A
Alex Dima 已提交
523
			'default': EDITOR_DEFAULTS.contribInfo.acceptSuggestionOnCommitCharacter,
524
			'description': nls.localize('acceptSuggestionOnCommitCharacter', "Controls if suggestions should be accepted on commit characters. For instance in JavaScript the semi-colon (';') can be a commit character that accepts a suggestion and types that character.")
525
		},
526
		'editor.snippetSuggestions': {
527
			'type': 'string',
528
			'enum': ['top', 'bottom', 'inline', 'none'],
J
Johannes Rieken 已提交
529 530 531 532 533 534
			'enumDescriptions': [
				nls.localize('snippetSuggestions.top', "Show snippet suggestions on top of other suggestions."),
				nls.localize('snippetSuggestions.bottom', "Show snippet suggestions below other suggestions."),
				nls.localize('snippetSuggestions.inline', "Show snippets suggestions with other suggestions."),
				nls.localize('snippetSuggestions.none', "Do not show snippet suggestions."),
			],
A
Alex Dima 已提交
535
			'default': EDITOR_DEFAULTS.contribInfo.snippetSuggestions,
536
			'description': nls.localize('snippetSuggestions', "Controls whether snippets are shown with other suggestions and how they are sorted.")
537
		},
538 539
		'editor.emptySelectionClipboard': {
			'type': 'boolean',
540
			'default': EDITOR_DEFAULTS.emptySelectionClipboard,
541 542
			'description': nls.localize('emptySelectionClipboard', "Controls whether copying without a selection copies the current line.")
		},
543
		'editor.wordBasedSuggestions': {
544
			'type': 'boolean',
A
Alex Dima 已提交
545
			'default': EDITOR_DEFAULTS.contribInfo.wordBasedSuggestions,
J
Johannes Rieken 已提交
546
			'description': nls.localize('wordBasedSuggestions', "Controls whether completions should be computed based on words in the document.")
547
		},
J
Johannes Rieken 已提交
548
		'editor.suggestSelection': {
549
			'type': 'string',
J
Johannes Rieken 已提交
550
			'enum': ['first', 'recentlyUsed', 'recentlyUsedByPrefix'],
J
Johannes Rieken 已提交
551
			'enumDescriptions': [
J
Johannes Rieken 已提交
552 553 554
				nls.localize('suggestSelection.first', "Always select the first suggestion."),
				nls.localize('suggestSelection.recentlyUsed', "Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently."),
				nls.localize('suggestSelection.recentlyUsedByPrefix', "Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`."),
J
Johannes Rieken 已提交
555
			],
J
Johannes Rieken 已提交
556 557
			'default': 'recentlyUsed',
			'description': nls.localize('suggestSelection', "Controls how suggestions are pre-selected when showing the suggest list.")
558
		},
J
Johannes Rieken 已提交
559
		'editor.suggestFontSize': {
J
Joao Moreno 已提交
560 561 562 563 564
			'type': 'integer',
			'default': 0,
			'minimum': 0,
			'description': nls.localize('suggestFontSize', "Font size for the suggest widget")
		},
J
Johannes Rieken 已提交
565
		'editor.suggestLineHeight': {
J
Joao Moreno 已提交
566 567 568 569 570
			'type': 'integer',
			'default': 0,
			'minimum': 0,
			'description': nls.localize('suggestLineHeight', "Line height for the suggest widget")
		},
J
Johannes Rieken 已提交
571
		'editor.selectionHighlight': {
E
Erich Gamma 已提交
572
			'type': 'boolean',
A
Alex Dima 已提交
573
			'default': EDITOR_DEFAULTS.contribInfo.selectionHighlight,
E
Erich Gamma 已提交
574 575
			'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight similar matches to the selection")
		},
576 577
		'editor.occurrencesHighlight': {
			'type': 'boolean',
A
Alex Dima 已提交
578
			'default': EDITOR_DEFAULTS.contribInfo.occurrencesHighlight,
579 580
			'description': nls.localize('occurrencesHighlight', "Controls whether the editor should highlight semantic symbol occurrences")
		},
J
Johannes Rieken 已提交
581
		'editor.overviewRulerLanes': {
E
Erich Gamma 已提交
582 583 584 585
			'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")
		},
586
		'editor.overviewRulerBorder': {
587
			'type': 'boolean',
A
Alex Dima 已提交
588
			'default': EDITOR_DEFAULTS.viewInfo.overviewRulerBorder,
589
			'description': nls.localize('overviewRulerBorder', "Controls if a border should be drawn around the overview ruler.")
590
		},
J
Johannes Rieken 已提交
591
		'editor.cursorBlinking': {
592
			'type': 'string',
593
			'enum': ['blink', 'smooth', 'phase', 'expand', 'solid'],
594
			'default': editorOptions.blinkingStyleToString(EDITOR_DEFAULTS.viewInfo.cursorBlinking),
A
Alex Dima 已提交
595
			'description': nls.localize('cursorBlinking', "Control the cursor animation style.")
596
		},
597 598
		'editor.mouseWheelZoom': {
			'type': 'boolean',
A
Alex Dima 已提交
599
			'default': EDITOR_DEFAULTS.viewInfo.mouseWheelZoom,
600 601
			'description': nls.localize('mouseWheelZoom', "Zoom the font of the editor when using mouse wheel and holding Ctrl")
		},
J
Johannes Rieken 已提交
602
		'editor.cursorStyle': {
M
markrendle 已提交
603
			'type': 'string',
604
			'enum': ['block', 'block-outline', 'line', 'line-thin', 'underline', 'underline-thin'],
605
			'default': editorOptions.cursorStyleToString(EDITOR_DEFAULTS.viewInfo.cursorStyle),
606
			'description': nls.localize('cursorStyle', "Controls the cursor style, accepted values are 'block', 'block-outline', 'line', 'line-thin', 'underline' and 'underline-thin'")
M
markrendle 已提交
607
		},
608
		'editor.cursorWidth': {
609
			'type': 'integer',
610 611
			'default': EDITOR_DEFAULTS.viewInfo.cursorWidth,
			'description': nls.localize('cursorWidth', "Controls the width of the cursor when editor.cursorStyle is set to 'line'")
612
		},
J
Johannes Rieken 已提交
613
		'editor.fontLigatures': {
614
			'type': 'boolean',
A
Alex Dima 已提交
615
			'default': EDITOR_DEFAULTS.viewInfo.fontLigatures,
616 617
			'description': nls.localize('fontLigatures', "Enables font ligatures")
		},
J
Johannes Rieken 已提交
618
		'editor.hideCursorInOverviewRuler': {
E
Erich Gamma 已提交
619
			'type': 'boolean',
A
Alex Dima 已提交
620
			'default': EDITOR_DEFAULTS.viewInfo.hideCursorInOverviewRuler,
E
Erich Gamma 已提交
621 622 623
			'description': nls.localize('hideCursorInOverviewRuler', "Controls if the cursor should be hidden in the overview ruler.")
		},
		'editor.renderWhitespace': {
624 625
			'type': 'string',
			'enum': ['none', 'boundary', 'all'],
A
Alex Dima 已提交
626
			default: EDITOR_DEFAULTS.viewInfo.renderWhitespace,
627
			description: nls.localize('renderWhitespace', "Controls how the editor should render whitespace characters, possibilities are 'none', 'boundary', and 'all'. The 'boundary' option does not render single spaces between words.")
E
Erich Gamma 已提交
628
		},
629 630
		'editor.renderControlCharacters': {
			'type': 'boolean',
A
Alex Dima 已提交
631
			default: EDITOR_DEFAULTS.viewInfo.renderControlCharacters,
632 633
			description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters")
		},
634 635
		'editor.renderIndentGuides': {
			'type': 'boolean',
A
Alex Dima 已提交
636
			default: EDITOR_DEFAULTS.viewInfo.renderIndentGuides,
637 638
			description: nls.localize('renderIndentGuides', "Controls whether the editor should render indent guides")
		},
639 640 641 642 643
		'editor.highlightActiveIndentGuide': {
			'type': 'boolean',
			default: EDITOR_DEFAULTS.viewInfo.highlightActiveIndentGuide,
			description: nls.localize('highlightActiveIndentGuide', "Controls whether the editor should highlight the active indent guide")
		},
644
		'editor.renderLineHighlight': {
645 646
			'type': 'string',
			'enum': ['none', 'gutter', 'line', 'all'],
A
Alex Dima 已提交
647
			default: EDITOR_DEFAULTS.viewInfo.renderLineHighlight,
648
			description: nls.localize('renderLineHighlight', "Controls how the editor should render the current line highlight, possibilities are 'none', 'gutter', 'line', and 'all'.")
649
		},
J
Johannes Rieken 已提交
650
		'editor.codeLens': {
E
Erich Gamma 已提交
651
			'type': 'boolean',
A
Alex Dima 已提交
652
			'default': EDITOR_DEFAULTS.contribInfo.codeLens,
J
Johannes Rieken 已提交
653
			'description': nls.localize('codeLens', "Controls if the editor shows CodeLens")
E
Erich Gamma 已提交
654
		},
J
Johannes Rieken 已提交
655
		'editor.folding': {
M
Martin Aeschlimann 已提交
656
			'type': 'boolean',
A
Alex Dima 已提交
657
			'default': EDITOR_DEFAULTS.contribInfo.folding,
658
			'description': nls.localize('folding', "Controls whether the editor has code folding enabled")
M
Martin Aeschlimann 已提交
659
		},
660 661 662 663
		'editor.foldingStrategy': {
			'type': 'string',
			'enum': ['auto', 'indentation'],
			'enumDescriptions': [
A
Alex Dima 已提交
664
				nls.localize('foldingStrategyAuto', 'If available, use a language specific folding strategy, otherwise falls back to the indentation based strategy.'),
665 666 667 668 669
				nls.localize('foldingStrategyIndentation', 'Always use the indentation based folding strategy')
			],
			'default': EDITOR_DEFAULTS.contribInfo.foldingStrategy,
			'description': nls.localize('foldingStrategy', "Controls the way folding ranges are computed. 'auto' picks uses a language specific folding strategy, if available. 'indentation' forces that the indentation based folding strategy is used.")
		},
670 671 672 673 674
		'editor.showFoldingControls': {
			'type': 'string',
			'enum': ['always', 'mouseover'],
			'default': EDITOR_DEFAULTS.contribInfo.showFoldingControls,
			'description': nls.localize('showFoldingControls', "Controls whether the fold controls on the gutter are automatically hidden.")
675
		},
676
		'editor.matchBrackets': {
677
			'type': 'boolean',
A
Alex Dima 已提交
678
			'default': EDITOR_DEFAULTS.contribInfo.matchBrackets,
679
			'description': nls.localize('matchBrackets', "Highlight matching brackets when one of them is selected.")
680
		},
I
isidor 已提交
681 682
		'editor.glyphMargin': {
			'type': 'boolean',
A
Alex Dima 已提交
683
			'default': EDITOR_DEFAULTS.viewInfo.glyphMargin,
I
isidor 已提交
684 685
			'description': nls.localize('glyphMargin', "Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.")
		},
J
Johannes Rieken 已提交
686
		'editor.useTabStops': {
687
			'type': 'boolean',
688
			'default': EDITOR_DEFAULTS.useTabStops,
689 690
			'description': nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops")
		},
J
Johannes Rieken 已提交
691
		'editor.trimAutoWhitespace': {
692
			'type': 'boolean',
693
			'default': EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,
694 695
			'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace")
		},
J
Johannes Rieken 已提交
696
		'editor.stablePeek': {
697
			'type': 'boolean',
698
			'default': false,
699
			'description': nls.localize('stablePeek', "Keep peek editors open even when double clicking their content or when hitting Escape.")
700
		},
701
		'editor.dragAndDrop': {
702
			'type': 'boolean',
703
			'default': EDITOR_DEFAULTS.dragAndDrop,
704
			'description': nls.localize('dragAndDrop', "Controls if the editor should allow to move selections via drag and drop.")
705
		},
706 707 708 709 710 711 712 713 714 715 716
		'editor.accessibilitySupport': {
			'type': 'string',
			'enum': ['auto', 'on', 'off'],
			'enumDescriptions': [
				nls.localize('accessibilitySupport.auto', "The editor will use platform APIs to detect when a Screen Reader is attached."),
				nls.localize('accessibilitySupport.on', "The editor will be permanently optimized for usage with a Screen Reader."),
				nls.localize('accessibilitySupport.off', "The editor will never be optimized for usage with a Screen Reader."),
			],
			'default': EDITOR_DEFAULTS.accessibilitySupport,
			'description': nls.localize('accessibilitySupport', "Controls whether the editor should run in a mode where it is optimized for screen readers.")
		},
717 718 719 720 721
		'editor.showUnused': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.showUnused,
			'description': nls.localize('showUnused', "Controls fading out of unused code.")
		},
722
		'editor.links': {
723
			'type': 'boolean',
724 725
			'default': EDITOR_DEFAULTS.contribInfo.links,
			'description': nls.localize('links', "Controls whether the editor should detect links and make them clickable")
726
		},
R
rebornix 已提交
727
		'editor.colorDecorators': {
728
			'type': 'boolean',
R
rebornix 已提交
729
			'default': EDITOR_DEFAULTS.contribInfo.colorDecorators,
730
			'description': nls.localize('colorDecorators', "Controls whether the editor should render the inline color decorators and color picker.")
731
		},
732 733 734 735 736
		'editor.lightbulb.enabled': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.lightbulbEnabled,
			'description': nls.localize('codeActions', "Enables the code action lightbulb")
		},
737 738 739 740 741 742 743 744 745 746 747 748
		'editor.codeActionsOnSave': {
			'type': 'object',
			'properties': {
				'source.organizeImports': {
					'type': 'boolean',
					'description': nls.localize('codeActionsOnSave.organizeImports', "Run organize imports on save?")
				}
			},
			'additionalProperties': {
				'type': 'boolean'
			},
			'default': EDITOR_DEFAULTS.contribInfo.codeActionsOnSave,
M
Matt Bierner 已提交
749
			'description': nls.localize('codeActionsOnSave', "Code action kinds to be run on save.")
750 751 752 753 754 755
		},
		'editor.codeActionsOnSaveTimeout': {
			'type': 'number',
			'default': EDITOR_DEFAULTS.contribInfo.codeActionsOnSaveTimeout,
			'description': nls.localize('codeActionsOnSaveTimeout', "Timeout for code actions run on save.")
		},
756 757 758 759
		'editor.selectionClipboard': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.selectionClipboard,
			'description': nls.localize('selectionClipboard', "Controls if the Linux primary clipboard should be supported."),
760
			'included': platform.isLinux
761
		},
J
Johannes Rieken 已提交
762
		'diffEditor.renderSideBySide': {
E
Erich Gamma 已提交
763 764 765 766
			'type': 'boolean',
			'default': true,
			'description': nls.localize('sideBySide', "Controls if the diff editor shows the diff side by side or inline")
		},
J
Johannes Rieken 已提交
767
		'diffEditor.ignoreTrimWhitespace': {
E
Erich Gamma 已提交
768 769 770
			'type': 'boolean',
			'default': true,
			'description': nls.localize('ignoreTrimWhitespace', "Controls if the diff editor shows changes in leading or trailing whitespace as diffs")
771
		},
772 773 774 775
		'editor.largeFileOptimizations': {
			'type': 'boolean',
			'default': EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
			'description': nls.localize('largeFileOptimizations', "Special handling for large files to disable certain memory intensive features.")
776
		},
777 778 779 780
		'diffEditor.renderIndicators': {
			'type': 'boolean',
			'default': true,
			'description': nls.localize('renderIndicators', "Controls if the diff editor shows +/- indicators for added/removed changes")
E
Erich Gamma 已提交
781 782
		}
	}
A
Alex Dima 已提交
783 784
};

785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
let cachedEditorConfigurationKeys: { [key: string]: boolean; } = null;
function getEditorConfigurationKeys(): { [key: string]: boolean; } {
	if (cachedEditorConfigurationKeys === null) {
		cachedEditorConfigurationKeys = Object.create(null);
		Object.keys(editorConfiguration.properties).forEach((prop) => {
			cachedEditorConfigurationKeys[prop] = true;
		});
	}
	return cachedEditorConfigurationKeys;
}

export function isEditorConfigurationKey(key: string): boolean {
	const editorConfigurationKeys = getEditorConfigurationKeys();
	return (editorConfigurationKeys[`editor.${key}`] || false);
}
export function isDiffEditorConfigurationKey(key: string): boolean {
	const editorConfigurationKeys = getEditorConfigurationKeys();
	return (editorConfigurationKeys[`diffEditor.${key}`] || false);
}

805
configurationRegistry.registerConfiguration(editorConfiguration);