commonEditorConfig.ts 34.9 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")
		},
571 572 573 574 575
		'editor.suggest.filterGraceful': {
			type: 'boolean',
			default: true,
			description: nls.localize('suggest.filterGraceful', "Controls whether filtering and sorting suggestions accounts for small typos.")
		},
J
Johannes Rieken 已提交
576
		'editor.selectionHighlight': {
E
Erich Gamma 已提交
577
			'type': 'boolean',
A
Alex Dima 已提交
578
			'default': EDITOR_DEFAULTS.contribInfo.selectionHighlight,
E
Erich Gamma 已提交
579 580
			'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight similar matches to the selection")
		},
581 582
		'editor.occurrencesHighlight': {
			'type': 'boolean',
A
Alex Dima 已提交
583
			'default': EDITOR_DEFAULTS.contribInfo.occurrencesHighlight,
584 585
			'description': nls.localize('occurrencesHighlight', "Controls whether the editor should highlight semantic symbol occurrences")
		},
J
Johannes Rieken 已提交
586
		'editor.overviewRulerLanes': {
E
Erich Gamma 已提交
587 588 589 590
			'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")
		},
591
		'editor.overviewRulerBorder': {
592
			'type': 'boolean',
A
Alex Dima 已提交
593
			'default': EDITOR_DEFAULTS.viewInfo.overviewRulerBorder,
594
			'description': nls.localize('overviewRulerBorder', "Controls if a border should be drawn around the overview ruler.")
595
		},
J
Johannes Rieken 已提交
596
		'editor.cursorBlinking': {
597
			'type': 'string',
598
			'enum': ['blink', 'smooth', 'phase', 'expand', 'solid'],
599
			'default': editorOptions.blinkingStyleToString(EDITOR_DEFAULTS.viewInfo.cursorBlinking),
A
Alex Dima 已提交
600
			'description': nls.localize('cursorBlinking', "Control the cursor animation style.")
601
		},
602 603
		'editor.mouseWheelZoom': {
			'type': 'boolean',
A
Alex Dima 已提交
604
			'default': EDITOR_DEFAULTS.viewInfo.mouseWheelZoom,
605 606
			'description': nls.localize('mouseWheelZoom', "Zoom the font of the editor when using mouse wheel and holding Ctrl")
		},
J
Johannes Rieken 已提交
607
		'editor.cursorStyle': {
M
markrendle 已提交
608
			'type': 'string',
609
			'enum': ['block', 'block-outline', 'line', 'line-thin', 'underline', 'underline-thin'],
610
			'default': editorOptions.cursorStyleToString(EDITOR_DEFAULTS.viewInfo.cursorStyle),
611
			'description': nls.localize('cursorStyle', "Controls the cursor style, accepted values are 'block', 'block-outline', 'line', 'line-thin', 'underline' and 'underline-thin'")
M
markrendle 已提交
612
		},
613
		'editor.cursorWidth': {
614
			'type': 'integer',
615 616
			'default': EDITOR_DEFAULTS.viewInfo.cursorWidth,
			'description': nls.localize('cursorWidth', "Controls the width of the cursor when editor.cursorStyle is set to 'line'")
617
		},
J
Johannes Rieken 已提交
618
		'editor.fontLigatures': {
619
			'type': 'boolean',
A
Alex Dima 已提交
620
			'default': EDITOR_DEFAULTS.viewInfo.fontLigatures,
621 622
			'description': nls.localize('fontLigatures', "Enables font ligatures")
		},
J
Johannes Rieken 已提交
623
		'editor.hideCursorInOverviewRuler': {
E
Erich Gamma 已提交
624
			'type': 'boolean',
A
Alex Dima 已提交
625
			'default': EDITOR_DEFAULTS.viewInfo.hideCursorInOverviewRuler,
E
Erich Gamma 已提交
626 627 628
			'description': nls.localize('hideCursorInOverviewRuler', "Controls if the cursor should be hidden in the overview ruler.")
		},
		'editor.renderWhitespace': {
629 630
			'type': 'string',
			'enum': ['none', 'boundary', 'all'],
A
Alex Dima 已提交
631
			default: EDITOR_DEFAULTS.viewInfo.renderWhitespace,
632
			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 已提交
633
		},
634 635
		'editor.renderControlCharacters': {
			'type': 'boolean',
A
Alex Dima 已提交
636
			default: EDITOR_DEFAULTS.viewInfo.renderControlCharacters,
637 638
			description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters")
		},
639 640
		'editor.renderIndentGuides': {
			'type': 'boolean',
A
Alex Dima 已提交
641
			default: EDITOR_DEFAULTS.viewInfo.renderIndentGuides,
642 643
			description: nls.localize('renderIndentGuides', "Controls whether the editor should render indent guides")
		},
644 645 646 647 648
		'editor.highlightActiveIndentGuide': {
			'type': 'boolean',
			default: EDITOR_DEFAULTS.viewInfo.highlightActiveIndentGuide,
			description: nls.localize('highlightActiveIndentGuide', "Controls whether the editor should highlight the active indent guide")
		},
649
		'editor.renderLineHighlight': {
650 651
			'type': 'string',
			'enum': ['none', 'gutter', 'line', 'all'],
A
Alex Dima 已提交
652
			default: EDITOR_DEFAULTS.viewInfo.renderLineHighlight,
653
			description: nls.localize('renderLineHighlight', "Controls how the editor should render the current line highlight, possibilities are 'none', 'gutter', 'line', and 'all'.")
654
		},
J
Johannes Rieken 已提交
655
		'editor.codeLens': {
E
Erich Gamma 已提交
656
			'type': 'boolean',
A
Alex Dima 已提交
657
			'default': EDITOR_DEFAULTS.contribInfo.codeLens,
J
Johannes Rieken 已提交
658
			'description': nls.localize('codeLens', "Controls if the editor shows CodeLens")
E
Erich Gamma 已提交
659
		},
J
Johannes Rieken 已提交
660
		'editor.folding': {
M
Martin Aeschlimann 已提交
661
			'type': 'boolean',
A
Alex Dima 已提交
662
			'default': EDITOR_DEFAULTS.contribInfo.folding,
663
			'description': nls.localize('folding', "Controls whether the editor has code folding enabled")
M
Martin Aeschlimann 已提交
664
		},
665 666 667 668
		'editor.foldingStrategy': {
			'type': 'string',
			'enum': ['auto', 'indentation'],
			'enumDescriptions': [
A
Alex Dima 已提交
669
				nls.localize('foldingStrategyAuto', 'If available, use a language specific folding strategy, otherwise falls back to the indentation based strategy.'),
670 671 672 673 674
				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.")
		},
675 676 677 678 679
		'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.")
680
		},
681
		'editor.matchBrackets': {
682
			'type': 'boolean',
A
Alex Dima 已提交
683
			'default': EDITOR_DEFAULTS.contribInfo.matchBrackets,
684
			'description': nls.localize('matchBrackets', "Highlight matching brackets when one of them is selected.")
685
		},
I
isidor 已提交
686 687
		'editor.glyphMargin': {
			'type': 'boolean',
A
Alex Dima 已提交
688
			'default': EDITOR_DEFAULTS.viewInfo.glyphMargin,
I
isidor 已提交
689 690
			'description': nls.localize('glyphMargin', "Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.")
		},
J
Johannes Rieken 已提交
691
		'editor.useTabStops': {
692
			'type': 'boolean',
693
			'default': EDITOR_DEFAULTS.useTabStops,
694 695
			'description': nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops")
		},
J
Johannes Rieken 已提交
696
		'editor.trimAutoWhitespace': {
697
			'type': 'boolean',
698
			'default': EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,
699 700
			'description': nls.localize('trimAutoWhitespace', "Remove trailing auto inserted whitespace")
		},
J
Johannes Rieken 已提交
701
		'editor.stablePeek': {
702
			'type': 'boolean',
703
			'default': false,
704
			'description': nls.localize('stablePeek', "Keep peek editors open even when double clicking their content or when hitting Escape.")
705
		},
706
		'editor.dragAndDrop': {
707
			'type': 'boolean',
708
			'default': EDITOR_DEFAULTS.dragAndDrop,
709
			'description': nls.localize('dragAndDrop', "Controls if the editor should allow to move selections via drag and drop.")
710
		},
711 712 713 714 715 716 717 718 719 720 721
		'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.")
		},
722 723 724 725 726
		'editor.showUnused': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.showUnused,
			'description': nls.localize('showUnused', "Controls fading out of unused code.")
		},
727
		'editor.links': {
728
			'type': 'boolean',
729 730
			'default': EDITOR_DEFAULTS.contribInfo.links,
			'description': nls.localize('links', "Controls whether the editor should detect links and make them clickable")
731
		},
R
rebornix 已提交
732
		'editor.colorDecorators': {
733
			'type': 'boolean',
R
rebornix 已提交
734
			'default': EDITOR_DEFAULTS.contribInfo.colorDecorators,
735
			'description': nls.localize('colorDecorators', "Controls whether the editor should render the inline color decorators and color picker.")
736
		},
737 738 739 740 741
		'editor.lightbulb.enabled': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.lightbulbEnabled,
			'description': nls.localize('codeActions', "Enables the code action lightbulb")
		},
742 743 744 745 746 747 748 749 750 751 752 753
		'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 已提交
754
			'description': nls.localize('codeActionsOnSave', "Code action kinds to be run on save.")
755 756 757 758 759 760
		},
		'editor.codeActionsOnSaveTimeout': {
			'type': 'number',
			'default': EDITOR_DEFAULTS.contribInfo.codeActionsOnSaveTimeout,
			'description': nls.localize('codeActionsOnSaveTimeout', "Timeout for code actions run on save.")
		},
761 762 763 764
		'editor.selectionClipboard': {
			'type': 'boolean',
			'default': EDITOR_DEFAULTS.contribInfo.selectionClipboard,
			'description': nls.localize('selectionClipboard', "Controls if the Linux primary clipboard should be supported."),
765
			'included': platform.isLinux
766
		},
J
Johannes Rieken 已提交
767
		'diffEditor.renderSideBySide': {
E
Erich Gamma 已提交
768 769 770 771
			'type': 'boolean',
			'default': true,
			'description': nls.localize('sideBySide', "Controls if the diff editor shows the diff side by side or inline")
		},
J
Johannes Rieken 已提交
772
		'diffEditor.ignoreTrimWhitespace': {
E
Erich Gamma 已提交
773 774 775
			'type': 'boolean',
			'default': true,
			'description': nls.localize('ignoreTrimWhitespace', "Controls if the diff editor shows changes in leading or trailing whitespace as diffs")
776
		},
777 778 779 780
		'editor.largeFileOptimizations': {
			'type': 'boolean',
			'default': EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
			'description': nls.localize('largeFileOptimizations', "Special handling for large files to disable certain memory intensive features.")
781
		},
782 783 784 785
		'diffEditor.renderIndicators': {
			'type': 'boolean',
			'default': true,
			'description': nls.localize('renderIndicators', "Controls if the diff editor shows +/- indicators for added/removed changes")
E
Erich Gamma 已提交
786 787
		}
	}
A
Alex Dima 已提交
788 789
};

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
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);
}

810
configurationRegistry.registerConfiguration(editorConfiguration);