feat: 添加vscode编辑器

This commit is contained in:
dhx
2022-09-29 16:48:09 +08:00
parent a93bdac4ff
commit 150898ec1e
1126 changed files with 933348 additions and 0 deletions
@@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { applyFontInfo } from './domFontInfo.js';
export class CharWidthRequest {
constructor(chr, type) {
this.chr = chr;
this.type = type;
this.width = 0;
}
fulfill(width) {
this.width = width;
}
}
class DomCharWidthReader {
constructor(bareFontInfo, requests) {
this._bareFontInfo = bareFontInfo;
this._requests = requests;
this._container = null;
this._testElements = null;
}
read() {
// Create a test container with all these test elements
this._createDomElements();
// Add the container to the DOM
document.body.appendChild(this._container);
// Read character widths
this._readFromDomElements();
// Remove the container from the DOM
document.body.removeChild(this._container);
this._container = null;
this._testElements = null;
}
_createDomElements() {
const container = document.createElement('div');
container.style.position = 'absolute';
container.style.top = '-50000px';
container.style.width = '50000px';
const regularDomNode = document.createElement('div');
applyFontInfo(regularDomNode, this._bareFontInfo);
container.appendChild(regularDomNode);
const boldDomNode = document.createElement('div');
applyFontInfo(boldDomNode, this._bareFontInfo);
boldDomNode.style.fontWeight = 'bold';
container.appendChild(boldDomNode);
const italicDomNode = document.createElement('div');
applyFontInfo(italicDomNode, this._bareFontInfo);
italicDomNode.style.fontStyle = 'italic';
container.appendChild(italicDomNode);
const testElements = [];
for (const request of this._requests) {
let parent;
if (request.type === 0 /* CharWidthRequestType.Regular */) {
parent = regularDomNode;
}
if (request.type === 2 /* CharWidthRequestType.Bold */) {
parent = boldDomNode;
}
if (request.type === 1 /* CharWidthRequestType.Italic */) {
parent = italicDomNode;
}
parent.appendChild(document.createElement('br'));
const testElement = document.createElement('span');
DomCharWidthReader._render(testElement, request);
parent.appendChild(testElement);
testElements.push(testElement);
}
this._container = container;
this._testElements = testElements;
}
static _render(testElement, request) {
if (request.chr === ' ') {
let htmlString = '\u00a0';
// Repeat character 256 (2^8) times
for (let i = 0; i < 8; i++) {
htmlString += htmlString;
}
testElement.innerText = htmlString;
}
else {
let testString = request.chr;
// Repeat character 256 (2^8) times
for (let i = 0; i < 8; i++) {
testString += testString;
}
testElement.textContent = testString;
}
}
_readFromDomElements() {
for (let i = 0, len = this._requests.length; i < len; i++) {
const request = this._requests[i];
const testElement = this._testElements[i];
request.fulfill(testElement.offsetWidth / 256);
}
}
}
export function readCharWidths(bareFontInfo, requests) {
const reader = new DomCharWidthReader(bareFontInfo, requests);
reader.read();
}
@@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FastDomNode } from '../../../base/browser/fastDomNode.js';
export function applyFontInfo(domNode, fontInfo) {
if (domNode instanceof FastDomNode) {
domNode.setFontFamily(fontInfo.getMassagedFontFamily());
domNode.setFontWeight(fontInfo.fontWeight);
domNode.setFontSize(fontInfo.fontSize);
domNode.setFontFeatureSettings(fontInfo.fontFeatureSettings);
domNode.setLineHeight(fontInfo.lineHeight);
domNode.setLetterSpacing(fontInfo.letterSpacing);
}
else {
domNode.style.fontFamily = fontInfo.getMassagedFontFamily();
domNode.style.fontWeight = fontInfo.fontWeight;
domNode.style.fontSize = fontInfo.fontSize + 'px';
domNode.style.fontFeatureSettings = fontInfo.fontFeatureSettings;
domNode.style.lineHeight = fontInfo.lineHeight + 'px';
domNode.style.letterSpacing = fontInfo.letterSpacing + 'px';
}
}
@@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import * as browser from '../../../base/browser/browser.js';
import * as arrays from '../../../base/common/arrays.js';
import { Emitter } from '../../../base/common/event.js';
import { Disposable } from '../../../base/common/lifecycle.js';
import * as objects from '../../../base/common/objects.js';
import * as platform from '../../../base/common/platform.js';
import { ElementSizeObserver } from './elementSizeObserver.js';
import { FontMeasurements } from './fontMeasurements.js';
import { migrateOptions } from './migrateOptions.js';
import { TabFocus } from './tabFocus.js';
import { ComputeOptionsMemory, ConfigurationChangedEvent, editorOptionsRegistry } from '../../common/config/editorOptions.js';
import { EditorZoom } from '../../common/config/editorZoom.js';
import { BareFontInfo } from '../../common/config/fontInfo.js';
import { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';
let EditorConfiguration = class EditorConfiguration extends Disposable {
constructor(isSimpleWidget, options, container, _accessibilityService) {
super();
this._accessibilityService = _accessibilityService;
this._onDidChange = this._register(new Emitter());
this.onDidChange = this._onDidChange.event;
this._onDidChangeFast = this._register(new Emitter());
this.onDidChangeFast = this._onDidChangeFast.event;
this._isDominatedByLongLines = false;
this._viewLineCount = 1;
this._lineNumbersDigitCount = 1;
this._reservedHeight = 0;
this._computeOptionsMemory = new ComputeOptionsMemory();
this.isSimpleWidget = isSimpleWidget;
this._containerObserver = this._register(new ElementSizeObserver(container, options.dimension));
this._rawOptions = deepCloneAndMigrateOptions(options);
this._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions);
this.options = this._computeOptions();
if (this.options.get(10 /* EditorOption.automaticLayout */)) {
this._containerObserver.startObserving();
}
this._register(EditorZoom.onDidChangeZoomLevel(() => this._recomputeOptions()));
this._register(TabFocus.onDidChangeTabFocus(() => this._recomputeOptions()));
this._register(this._containerObserver.onDidChange(() => this._recomputeOptions()));
this._register(FontMeasurements.onDidChange(() => this._recomputeOptions()));
this._register(browser.PixelRatio.onDidChange(() => this._recomputeOptions()));
this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(() => this._recomputeOptions()));
}
_recomputeOptions() {
const newOptions = this._computeOptions();
const changeEvent = EditorOptionsUtil.checkEquals(this.options, newOptions);
if (changeEvent === null) {
// nothing changed!
return;
}
this.options = newOptions;
this._onDidChangeFast.fire(changeEvent);
this._onDidChange.fire(changeEvent);
}
_computeOptions() {
const partialEnv = this._readEnvConfiguration();
const bareFontInfo = BareFontInfo.createFromValidatedSettings(this._validatedOptions, partialEnv.pixelRatio, this.isSimpleWidget);
const fontInfo = this._readFontInfo(bareFontInfo);
const env = {
memory: this._computeOptionsMemory,
outerWidth: partialEnv.outerWidth,
outerHeight: partialEnv.outerHeight - this._reservedHeight,
fontInfo: fontInfo,
extraEditorClassName: partialEnv.extraEditorClassName,
isDominatedByLongLines: this._isDominatedByLongLines,
viewLineCount: this._viewLineCount,
lineNumbersDigitCount: this._lineNumbersDigitCount,
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
pixelRatio: partialEnv.pixelRatio,
tabFocusMode: TabFocus.getTabFocusMode(),
accessibilitySupport: partialEnv.accessibilitySupport
};
return EditorOptionsUtil.computeOptions(this._validatedOptions, env);
}
_readEnvConfiguration() {
return {
extraEditorClassName: getExtraEditorClassName(),
outerWidth: this._containerObserver.getWidth(),
outerHeight: this._containerObserver.getHeight(),
emptySelectionClipboard: browser.isWebKit || browser.isFirefox,
pixelRatio: browser.PixelRatio.value,
accessibilitySupport: (this._accessibilityService.isScreenReaderOptimized()
? 2 /* AccessibilitySupport.Enabled */
: this._accessibilityService.getAccessibilitySupport())
};
}
_readFontInfo(bareFontInfo) {
return FontMeasurements.readFontInfo(bareFontInfo);
}
getRawOptions() {
return this._rawOptions;
}
updateOptions(_newOptions) {
const newOptions = deepCloneAndMigrateOptions(_newOptions);
const didChange = EditorOptionsUtil.applyUpdate(this._rawOptions, newOptions);
if (!didChange) {
return;
}
this._validatedOptions = EditorOptionsUtil.validateOptions(this._rawOptions);
this._recomputeOptions();
}
observeContainer(dimension) {
this._containerObserver.observe(dimension);
}
setIsDominatedByLongLines(isDominatedByLongLines) {
if (this._isDominatedByLongLines === isDominatedByLongLines) {
return;
}
this._isDominatedByLongLines = isDominatedByLongLines;
this._recomputeOptions();
}
setModelLineCount(modelLineCount) {
const lineNumbersDigitCount = digitCount(modelLineCount);
if (this._lineNumbersDigitCount === lineNumbersDigitCount) {
return;
}
this._lineNumbersDigitCount = lineNumbersDigitCount;
this._recomputeOptions();
}
setViewLineCount(viewLineCount) {
if (this._viewLineCount === viewLineCount) {
return;
}
this._viewLineCount = viewLineCount;
this._recomputeOptions();
}
setReservedHeight(reservedHeight) {
if (this._reservedHeight === reservedHeight) {
return;
}
this._reservedHeight = reservedHeight;
this._recomputeOptions();
}
};
EditorConfiguration = __decorate([
__param(3, IAccessibilityService)
], EditorConfiguration);
export { EditorConfiguration };
function digitCount(n) {
let r = 0;
while (n) {
n = Math.floor(n / 10);
r++;
}
return r ? r : 1;
}
function getExtraEditorClassName() {
let extra = '';
if (!browser.isSafari && !browser.isWebkitWebView) {
// Use user-select: none in all browsers except Safari and native macOS WebView
extra += 'no-user-select ';
}
if (browser.isSafari) {
// See https://github.com/microsoft/vscode/issues/108822
extra += 'no-minimap-shadow ';
extra += 'enable-user-select ';
}
if (platform.isMacintosh) {
extra += 'mac ';
}
return extra;
}
class ValidatedEditorOptions {
constructor() {
this._values = [];
}
_read(option) {
return this._values[option];
}
get(id) {
return this._values[id];
}
_write(option, value) {
this._values[option] = value;
}
}
export class ComputedEditorOptions {
constructor() {
this._values = [];
}
_read(id) {
if (id >= this._values.length) {
throw new Error('Cannot read uninitialized value');
}
return this._values[id];
}
get(id) {
return this._read(id);
}
_write(id, value) {
this._values[id] = value;
}
}
class EditorOptionsUtil {
static validateOptions(options) {
const result = new ValidatedEditorOptions();
for (const editorOption of editorOptionsRegistry) {
const value = (editorOption.name === '_never_' ? undefined : options[editorOption.name]);
result._write(editorOption.id, editorOption.validate(value));
}
return result;
}
static computeOptions(options, env) {
const result = new ComputedEditorOptions();
for (const editorOption of editorOptionsRegistry) {
result._write(editorOption.id, editorOption.compute(env, result, options._read(editorOption.id)));
}
return result;
}
static _deepEquals(a, b) {
if (typeof a !== 'object' || typeof b !== 'object' || !a || !b) {
return a === b;
}
if (Array.isArray(a) || Array.isArray(b)) {
return (Array.isArray(a) && Array.isArray(b) ? arrays.equals(a, b) : false);
}
if (Object.keys(a).length !== Object.keys(b).length) {
return false;
}
for (const key in a) {
if (!EditorOptionsUtil._deepEquals(a[key], b[key])) {
return false;
}
}
return true;
}
static checkEquals(a, b) {
const result = [];
let somethingChanged = false;
for (const editorOption of editorOptionsRegistry) {
const changed = !EditorOptionsUtil._deepEquals(a._read(editorOption.id), b._read(editorOption.id));
result[editorOption.id] = changed;
if (changed) {
somethingChanged = true;
}
}
return (somethingChanged ? new ConfigurationChangedEvent(result) : null);
}
/**
* Returns true if something changed.
* Modifies `options`.
*/
static applyUpdate(options, update) {
let changed = false;
for (const editorOption of editorOptionsRegistry) {
if (update.hasOwnProperty(editorOption.name)) {
const result = editorOption.applyUpdate(options[editorOption.name], update[editorOption.name]);
options[editorOption.name] = result.newValue;
changed = changed || result.didChange;
}
}
return changed;
}
}
function deepCloneAndMigrateOptions(_options) {
const options = objects.deepClone(_options);
migrateOptions(options);
return options;
}
@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from '../../../base/common/lifecycle.js';
import { Emitter } from '../../../base/common/event.js';
export class ElementSizeObserver extends Disposable {
constructor(referenceDomElement, dimension) {
super();
this._onDidChange = this._register(new Emitter());
this.onDidChange = this._onDidChange.event;
this._referenceDomElement = referenceDomElement;
this._width = -1;
this._height = -1;
this._resizeObserver = null;
this.measureReferenceDomElement(false, dimension);
}
dispose() {
this.stopObserving();
super.dispose();
}
getWidth() {
return this._width;
}
getHeight() {
return this._height;
}
startObserving() {
if (!this._resizeObserver && this._referenceDomElement) {
this._resizeObserver = new ResizeObserver((entries) => {
if (entries && entries[0] && entries[0].contentRect) {
this.observe({ width: entries[0].contentRect.width, height: entries[0].contentRect.height });
}
else {
this.observe();
}
});
this._resizeObserver.observe(this._referenceDomElement);
}
}
stopObserving() {
if (this._resizeObserver) {
this._resizeObserver.disconnect();
this._resizeObserver = null;
}
}
observe(dimension) {
this.measureReferenceDomElement(true, dimension);
}
measureReferenceDomElement(emitEvent, dimension) {
let observedWidth = 0;
let observedHeight = 0;
if (dimension) {
observedWidth = dimension.width;
observedHeight = dimension.height;
}
else if (this._referenceDomElement) {
observedWidth = this._referenceDomElement.clientWidth;
observedHeight = this._referenceDomElement.clientHeight;
}
observedWidth = Math.max(5, observedWidth);
observedHeight = Math.max(5, observedHeight);
if (this._width !== observedWidth || this._height !== observedHeight) {
this._width = observedWidth;
this._height = observedHeight;
if (emitEvent) {
this._onDidChange.fire();
}
}
}
}
@@ -0,0 +1,188 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as browser from '../../../base/browser/browser.js';
import { Emitter } from '../../../base/common/event.js';
import { Disposable } from '../../../base/common/lifecycle.js';
import { CharWidthRequest, readCharWidths } from './charWidthReader.js';
import { EditorFontLigatures } from '../../common/config/editorOptions.js';
import { FontInfo } from '../../common/config/fontInfo.js';
class FontMeasurementsImpl extends Disposable {
constructor() {
super();
this._onDidChange = this._register(new Emitter());
this.onDidChange = this._onDidChange.event;
this._cache = new FontMeasurementsCache();
this._evictUntrustedReadingsTimeout = -1;
}
dispose() {
if (this._evictUntrustedReadingsTimeout !== -1) {
window.clearTimeout(this._evictUntrustedReadingsTimeout);
this._evictUntrustedReadingsTimeout = -1;
}
super.dispose();
}
/**
* Clear all cached font information and trigger a change event.
*/
clearAllFontInfos() {
this._cache = new FontMeasurementsCache();
this._onDidChange.fire();
}
_writeToCache(item, value) {
this._cache.put(item, value);
if (!value.isTrusted && this._evictUntrustedReadingsTimeout === -1) {
// Try reading again after some time
this._evictUntrustedReadingsTimeout = window.setTimeout(() => {
this._evictUntrustedReadingsTimeout = -1;
this._evictUntrustedReadings();
}, 5000);
}
}
_evictUntrustedReadings() {
const values = this._cache.getValues();
let somethingRemoved = false;
for (const item of values) {
if (!item.isTrusted) {
somethingRemoved = true;
this._cache.remove(item);
}
}
if (somethingRemoved) {
this._onDidChange.fire();
}
}
/**
* Read font information.
*/
readFontInfo(bareFontInfo) {
if (!this._cache.has(bareFontInfo)) {
let readConfig = this._actualReadFontInfo(bareFontInfo);
if (readConfig.typicalHalfwidthCharacterWidth <= 2 || readConfig.typicalFullwidthCharacterWidth <= 2 || readConfig.spaceWidth <= 2 || readConfig.maxDigitWidth <= 2) {
// Hey, it's Bug 14341 ... we couldn't read
readConfig = new FontInfo({
pixelRatio: browser.PixelRatio.value,
fontFamily: readConfig.fontFamily,
fontWeight: readConfig.fontWeight,
fontSize: readConfig.fontSize,
fontFeatureSettings: readConfig.fontFeatureSettings,
lineHeight: readConfig.lineHeight,
letterSpacing: readConfig.letterSpacing,
isMonospace: readConfig.isMonospace,
typicalHalfwidthCharacterWidth: Math.max(readConfig.typicalHalfwidthCharacterWidth, 5),
typicalFullwidthCharacterWidth: Math.max(readConfig.typicalFullwidthCharacterWidth, 5),
canUseHalfwidthRightwardsArrow: readConfig.canUseHalfwidthRightwardsArrow,
spaceWidth: Math.max(readConfig.spaceWidth, 5),
middotWidth: Math.max(readConfig.middotWidth, 5),
wsmiddotWidth: Math.max(readConfig.wsmiddotWidth, 5),
maxDigitWidth: Math.max(readConfig.maxDigitWidth, 5),
}, false);
}
this._writeToCache(bareFontInfo, readConfig);
}
return this._cache.get(bareFontInfo);
}
_createRequest(chr, type, all, monospace) {
const result = new CharWidthRequest(chr, type);
all.push(result);
monospace === null || monospace === void 0 ? void 0 : monospace.push(result);
return result;
}
_actualReadFontInfo(bareFontInfo) {
const all = [];
const monospace = [];
const typicalHalfwidthCharacter = this._createRequest('n', 0 /* CharWidthRequestType.Regular */, all, monospace);
const typicalFullwidthCharacter = this._createRequest('\uff4d', 0 /* CharWidthRequestType.Regular */, all, null);
const space = this._createRequest(' ', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit0 = this._createRequest('0', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit1 = this._createRequest('1', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit2 = this._createRequest('2', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit3 = this._createRequest('3', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit4 = this._createRequest('4', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit5 = this._createRequest('5', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit6 = this._createRequest('6', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit7 = this._createRequest('7', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit8 = this._createRequest('8', 0 /* CharWidthRequestType.Regular */, all, monospace);
const digit9 = this._createRequest('9', 0 /* CharWidthRequestType.Regular */, all, monospace);
// monospace test: used for whitespace rendering
const rightwardsArrow = this._createRequest('→', 0 /* CharWidthRequestType.Regular */, all, monospace);
const halfwidthRightwardsArrow = this._createRequest('→', 0 /* CharWidthRequestType.Regular */, all, null);
// U+00B7 - MIDDLE DOT
const middot = this._createRequest('·', 0 /* CharWidthRequestType.Regular */, all, monospace);
// U+2E31 - WORD SEPARATOR MIDDLE DOT
const wsmiddotWidth = this._createRequest(String.fromCharCode(0x2E31), 0 /* CharWidthRequestType.Regular */, all, null);
// monospace test: some characters
const monospaceTestChars = '|/-_ilm%';
for (let i = 0, len = monospaceTestChars.length; i < len; i++) {
this._createRequest(monospaceTestChars.charAt(i), 0 /* CharWidthRequestType.Regular */, all, monospace);
this._createRequest(monospaceTestChars.charAt(i), 1 /* CharWidthRequestType.Italic */, all, monospace);
this._createRequest(monospaceTestChars.charAt(i), 2 /* CharWidthRequestType.Bold */, all, monospace);
}
readCharWidths(bareFontInfo, all);
const maxDigitWidth = Math.max(digit0.width, digit1.width, digit2.width, digit3.width, digit4.width, digit5.width, digit6.width, digit7.width, digit8.width, digit9.width);
let isMonospace = (bareFontInfo.fontFeatureSettings === EditorFontLigatures.OFF);
const referenceWidth = monospace[0].width;
for (let i = 1, len = monospace.length; isMonospace && i < len; i++) {
const diff = referenceWidth - monospace[i].width;
if (diff < -0.001 || diff > 0.001) {
isMonospace = false;
break;
}
}
let canUseHalfwidthRightwardsArrow = true;
if (isMonospace && halfwidthRightwardsArrow.width !== referenceWidth) {
// using a halfwidth rightwards arrow would break monospace...
canUseHalfwidthRightwardsArrow = false;
}
if (halfwidthRightwardsArrow.width > rightwardsArrow.width) {
// using a halfwidth rightwards arrow would paint a larger arrow than a regular rightwards arrow
canUseHalfwidthRightwardsArrow = false;
}
return new FontInfo({
pixelRatio: browser.PixelRatio.value,
fontFamily: bareFontInfo.fontFamily,
fontWeight: bareFontInfo.fontWeight,
fontSize: bareFontInfo.fontSize,
fontFeatureSettings: bareFontInfo.fontFeatureSettings,
lineHeight: bareFontInfo.lineHeight,
letterSpacing: bareFontInfo.letterSpacing,
isMonospace: isMonospace,
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacter.width,
typicalFullwidthCharacterWidth: typicalFullwidthCharacter.width,
canUseHalfwidthRightwardsArrow: canUseHalfwidthRightwardsArrow,
spaceWidth: space.width,
middotWidth: middot.width,
wsmiddotWidth: wsmiddotWidth.width,
maxDigitWidth: maxDigitWidth
}, true);
}
}
class FontMeasurementsCache {
constructor() {
this._keys = Object.create(null);
this._values = Object.create(null);
}
has(item) {
const itemId = item.getId();
return !!this._values[itemId];
}
get(item) {
const itemId = item.getId();
return this._values[itemId];
}
put(item, value) {
const itemId = item.getId();
this._keys[itemId] = item;
this._values[itemId] = value;
}
remove(item) {
const itemId = item.getId();
delete this._keys[itemId];
delete this._values[itemId];
}
getValues() {
return Object.keys(this._keys).map(id => this._values[id]);
}
}
export const FontMeasurements = new FontMeasurementsImpl();
@@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class EditorSettingMigration {
constructor(key, migrate) {
this.key = key;
this.migrate = migrate;
}
apply(options) {
const value = EditorSettingMigration._read(options, this.key);
const read = (key) => EditorSettingMigration._read(options, key);
const write = (key, value) => EditorSettingMigration._write(options, key, value);
this.migrate(value, read, write);
}
static _read(source, key) {
if (typeof source === 'undefined') {
return undefined;
}
const firstDotIndex = key.indexOf('.');
if (firstDotIndex >= 0) {
const firstSegment = key.substring(0, firstDotIndex);
return this._read(source[firstSegment], key.substring(firstDotIndex + 1));
}
return source[key];
}
static _write(target, key, value) {
const firstDotIndex = key.indexOf('.');
if (firstDotIndex >= 0) {
const firstSegment = key.substring(0, firstDotIndex);
target[firstSegment] = target[firstSegment] || {};
this._write(target[firstSegment], key.substring(firstDotIndex + 1), value);
return;
}
target[key] = value;
}
}
EditorSettingMigration.items = [];
function registerEditorSettingMigration(key, migrate) {
EditorSettingMigration.items.push(new EditorSettingMigration(key, migrate));
}
function registerSimpleEditorSettingMigration(key, values) {
registerEditorSettingMigration(key, (value, read, write) => {
if (typeof value !== 'undefined') {
for (const [oldValue, newValue] of values) {
if (value === oldValue) {
write(key, newValue);
return;
}
}
}
});
}
/**
* Compatibility with old options
*/
export function migrateOptions(options) {
EditorSettingMigration.items.forEach(migration => migration.apply(options));
}
registerSimpleEditorSettingMigration('wordWrap', [[true, 'on'], [false, 'off']]);
registerSimpleEditorSettingMigration('lineNumbers', [[true, 'on'], [false, 'off']]);
registerSimpleEditorSettingMigration('cursorBlinking', [['visible', 'solid']]);
registerSimpleEditorSettingMigration('renderWhitespace', [[true, 'boundary'], [false, 'none']]);
registerSimpleEditorSettingMigration('renderLineHighlight', [[true, 'line'], [false, 'none']]);
registerSimpleEditorSettingMigration('acceptSuggestionOnEnter', [[true, 'on'], [false, 'off']]);
registerSimpleEditorSettingMigration('tabCompletion', [[false, 'off'], [true, 'onlySnippets']]);
registerSimpleEditorSettingMigration('hover', [[true, { enabled: true }], [false, { enabled: false }]]);
registerSimpleEditorSettingMigration('parameterHints', [[true, { enabled: true }], [false, { enabled: false }]]);
registerSimpleEditorSettingMigration('autoIndent', [[false, 'advanced'], [true, 'full']]);
registerSimpleEditorSettingMigration('matchBrackets', [[true, 'always'], [false, 'never']]);
registerEditorSettingMigration('autoClosingBrackets', (value, read, write) => {
if (value === false) {
write('autoClosingBrackets', 'never');
if (typeof read('autoClosingQuotes') === 'undefined') {
write('autoClosingQuotes', 'never');
}
if (typeof read('autoSurround') === 'undefined') {
write('autoSurround', 'never');
}
}
});
registerEditorSettingMigration('renderIndentGuides', (value, read, write) => {
if (typeof value !== 'undefined') {
write('renderIndentGuides', undefined);
if (typeof read('guides.indentation') === 'undefined') {
write('guides.indentation', !!value);
}
}
});
registerEditorSettingMigration('highlightActiveIndentGuide', (value, read, write) => {
if (typeof value !== 'undefined') {
write('highlightActiveIndentGuide', undefined);
if (typeof read('guides.highlightActiveIndentation') === 'undefined') {
write('guides.highlightActiveIndentation', !!value);
}
}
});
const suggestFilteredTypesMapping = {
method: 'showMethods',
function: 'showFunctions',
constructor: 'showConstructors',
deprecated: 'showDeprecated',
field: 'showFields',
variable: 'showVariables',
class: 'showClasses',
struct: 'showStructs',
interface: 'showInterfaces',
module: 'showModules',
property: 'showProperties',
event: 'showEvents',
operator: 'showOperators',
unit: 'showUnits',
value: 'showValues',
constant: 'showConstants',
enum: 'showEnums',
enumMember: 'showEnumMembers',
keyword: 'showKeywords',
text: 'showWords',
color: 'showColors',
file: 'showFiles',
reference: 'showReferences',
folder: 'showFolders',
typeParameter: 'showTypeParameters',
snippet: 'showSnippets',
};
registerEditorSettingMigration('suggest.filteredTypes', (value, read, write) => {
if (value && typeof value === 'object') {
for (const entry of Object.entries(suggestFilteredTypesMapping)) {
const v = value[entry[0]];
if (v === false) {
if (typeof read(`suggest.${entry[1]}`) === 'undefined') {
write(`suggest.${entry[1]}`, false);
}
}
}
write('suggest.filteredTypes', undefined);
}
});
registerEditorSettingMigration('quickSuggestions', (input, read, write) => {
if (typeof input === 'boolean') {
const value = input ? 'on' : 'off';
const newValue = { comments: value, strings: value, other: value };
write('quickSuggestions', newValue);
}
});
@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from '../../../base/common/event.js';
class TabFocusImpl {
constructor() {
this._tabFocus = false;
this._onDidChangeTabFocus = new Emitter();
this.onDidChangeTabFocus = this._onDidChangeTabFocus.event;
}
getTabFocusMode() {
return this._tabFocus;
}
setTabFocusMode(tabFocusMode) {
if (this._tabFocus === tabFocusMode) {
return;
}
this._tabFocus = tabFocusMode;
this._onDidChangeTabFocus.fire(this._tabFocus);
}
}
/**
* 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 const TabFocus = new TabFocusImpl();