@21epub/epub-thirdparty
Version:
epub-thirdparty
1,049 lines • 133 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from '../../../nls.js';
import * as platform from '../../../base/common/platform.js';
import { USUAL_WORD_SEPARATORS } from '../model/wordHelper.js';
/**
* @internal
* The width of the minimap gutter, in pixels.
*/
export const MINIMAP_GUTTER_WIDTH = 8;
//#endregion
/**
* An event describing that the configuration of the editor has changed.
*/
export class ConfigurationChangedEvent {
/**
* @internal
*/
constructor(values) {
this._values = values;
}
hasChanged(id) {
return this._values[id];
}
}
/**
* @internal
*/
export class ValidatedEditorOptions {
constructor() {
this._values = [];
}
_read(option) {
return this._values[option];
}
get(id) {
return this._values[id];
}
_write(option, value) {
this._values[option] = value;
}
}
/**
* @internal
*/
export class ComputeOptionsMemory {
constructor() {
this.stableMinimapLayoutInput = null;
this.stableFitMaxMinimapScale = 0;
this.stableFitRemainingWidth = 0;
}
}
/**
* @internal
*/
class BaseEditorOption {
constructor(id, name, defaultValue, schema) {
this.id = id;
this.name = name;
this.defaultValue = defaultValue;
this.schema = schema;
}
compute(env, options, value) {
return value;
}
}
/**
* @internal
*/
class ComputedEditorOption {
constructor(id, deps = null) {
this.schema = undefined;
this.id = id;
this.name = '_never_';
this.defaultValue = undefined;
this.deps = deps;
}
validate(input) {
return this.defaultValue;
}
}
class SimpleEditorOption {
constructor(id, name, defaultValue, schema) {
this.id = id;
this.name = name;
this.defaultValue = defaultValue;
this.schema = schema;
}
validate(input) {
if (typeof input === 'undefined') {
return this.defaultValue;
}
return input;
}
compute(env, options, value) {
return value;
}
}
/**
* @internal
*/
export function boolean(value, defaultValue) {
if (typeof value === 'undefined') {
return defaultValue;
}
if (value === 'false') {
// treat the string 'false' as false
return false;
}
return Boolean(value);
}
class EditorBooleanOption extends SimpleEditorOption {
constructor(id, name, defaultValue, schema = undefined) {
if (typeof schema !== 'undefined') {
schema.type = 'boolean';
schema.default = defaultValue;
}
super(id, name, defaultValue, schema);
}
validate(input) {
return boolean(input, this.defaultValue);
}
}
/**
* @internal
*/
export function clampedInt(value, defaultValue, minimum, maximum) {
if (typeof value === 'undefined') {
return defaultValue;
}
let r = parseInt(value, 10);
if (isNaN(r)) {
return defaultValue;
}
r = Math.max(minimum, r);
r = Math.min(maximum, r);
return r | 0;
}
class EditorIntOption extends SimpleEditorOption {
constructor(id, name, defaultValue, minimum, maximum, schema = undefined) {
if (typeof schema !== 'undefined') {
schema.type = 'integer';
schema.default = defaultValue;
schema.minimum = minimum;
schema.maximum = maximum;
}
super(id, name, defaultValue, schema);
this.minimum = minimum;
this.maximum = maximum;
}
static clampedInt(value, defaultValue, minimum, maximum) {
return clampedInt(value, defaultValue, minimum, maximum);
}
validate(input) {
return EditorIntOption.clampedInt(input, this.defaultValue, this.minimum, this.maximum);
}
}
class EditorFloatOption extends SimpleEditorOption {
constructor(id, name, defaultValue, validationFn, schema) {
if (typeof schema !== 'undefined') {
schema.type = 'number';
schema.default = defaultValue;
}
super(id, name, defaultValue, schema);
this.validationFn = validationFn;
}
static clamp(n, min, max) {
if (n < min) {
return min;
}
if (n > max) {
return max;
}
return n;
}
static float(value, defaultValue) {
if (typeof value === 'number') {
return value;
}
if (typeof value === 'undefined') {
return defaultValue;
}
const r = parseFloat(value);
return (isNaN(r) ? defaultValue : r);
}
validate(input) {
return this.validationFn(EditorFloatOption.float(input, this.defaultValue));
}
}
class EditorStringOption extends SimpleEditorOption {
static string(value, defaultValue) {
if (typeof value !== 'string') {
return defaultValue;
}
return value;
}
constructor(id, name, defaultValue, schema = undefined) {
if (typeof schema !== 'undefined') {
schema.type = 'string';
schema.default = defaultValue;
}
super(id, name, defaultValue, schema);
}
validate(input) {
return EditorStringOption.string(input, this.defaultValue);
}
}
/**
* @internal
*/
export function stringSet(value, defaultValue, allowedValues) {
if (typeof value !== 'string') {
return defaultValue;
}
if (allowedValues.indexOf(value) === -1) {
return defaultValue;
}
return value;
}
class EditorStringEnumOption extends SimpleEditorOption {
constructor(id, name, defaultValue, allowedValues, schema = undefined) {
if (typeof schema !== 'undefined') {
schema.type = 'string';
schema.enum = allowedValues;
schema.default = defaultValue;
}
super(id, name, defaultValue, schema);
this._allowedValues = allowedValues;
}
validate(input) {
return stringSet(input, this.defaultValue, this._allowedValues);
}
}
class EditorEnumOption extends BaseEditorOption {
constructor(id, name, defaultValue, defaultStringValue, allowedValues, convert, schema = undefined) {
if (typeof schema !== 'undefined') {
schema.type = 'string';
schema.enum = allowedValues;
schema.default = defaultStringValue;
}
super(id, name, defaultValue, schema);
this._allowedValues = allowedValues;
this._convert = convert;
}
validate(input) {
if (typeof input !== 'string') {
return this.defaultValue;
}
if (this._allowedValues.indexOf(input) === -1) {
return this.defaultValue;
}
return this._convert(input);
}
}
//#endregion
//#region autoIndent
function _autoIndentFromString(autoIndent) {
switch (autoIndent) {
case 'none': return 0 /* None */;
case 'keep': return 1 /* Keep */;
case 'brackets': return 2 /* Brackets */;
case 'advanced': return 3 /* Advanced */;
case 'full': return 4 /* Full */;
}
}
//#endregion
//#region accessibilitySupport
class EditorAccessibilitySupport extends BaseEditorOption {
constructor() {
super(2 /* accessibilitySupport */, 'accessibilitySupport', 0 /* Unknown */, {
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. Word wrapping will be disabled."),
nls.localize('accessibilitySupport.off', "The editor will never be optimized for usage with a Screen Reader."),
],
default: 'auto',
description: nls.localize('accessibilitySupport', "Controls whether the editor should run in a mode where it is optimized for screen readers. Setting to on will disable word wrapping.")
});
}
validate(input) {
switch (input) {
case 'auto': return 0 /* Unknown */;
case 'off': return 1 /* Disabled */;
case 'on': return 2 /* Enabled */;
}
return this.defaultValue;
}
compute(env, options, value) {
if (value === 0 /* Unknown */) {
// The editor reads the `accessibilitySupport` from the environment
return env.accessibilitySupport;
}
return value;
}
}
class EditorComments extends BaseEditorOption {
constructor() {
const defaults = {
insertSpace: true,
ignoreEmptyLines: true,
};
super(19 /* comments */, 'comments', defaults, {
'editor.comments.insertSpace': {
type: 'boolean',
default: defaults.insertSpace,
description: nls.localize('comments.insertSpace', "Controls whether a space character is inserted when commenting.")
},
'editor.comments.ignoreEmptyLines': {
type: 'boolean',
default: defaults.ignoreEmptyLines,
description: nls.localize('comments.ignoreEmptyLines', 'Controls if empty lines should be ignored with toggle, add or remove actions for line comments.')
},
});
}
validate(_input) {
if (!_input || typeof _input !== 'object') {
return this.defaultValue;
}
const input = _input;
return {
insertSpace: boolean(input.insertSpace, this.defaultValue.insertSpace),
ignoreEmptyLines: boolean(input.ignoreEmptyLines, this.defaultValue.ignoreEmptyLines),
};
}
}
function _cursorBlinkingStyleFromString(cursorBlinkingStyle) {
switch (cursorBlinkingStyle) {
case 'blink': return 1 /* Blink */;
case 'smooth': return 2 /* Smooth */;
case 'phase': return 3 /* Phase */;
case 'expand': return 4 /* Expand */;
case 'solid': return 5 /* Solid */;
}
}
//#endregion
//#region cursorStyle
/**
* The style in which the editor's cursor should be rendered.
*/
export var TextEditorCursorStyle;
(function (TextEditorCursorStyle) {
/**
* As a vertical line (sitting between two characters).
*/
TextEditorCursorStyle[TextEditorCursorStyle["Line"] = 1] = "Line";
/**
* As a block (sitting on top of a character).
*/
TextEditorCursorStyle[TextEditorCursorStyle["Block"] = 2] = "Block";
/**
* As a horizontal line (sitting under a character).
*/
TextEditorCursorStyle[TextEditorCursorStyle["Underline"] = 3] = "Underline";
/**
* As a thin vertical line (sitting between two characters).
*/
TextEditorCursorStyle[TextEditorCursorStyle["LineThin"] = 4] = "LineThin";
/**
* As an outlined block (sitting on top of a character).
*/
TextEditorCursorStyle[TextEditorCursorStyle["BlockOutline"] = 5] = "BlockOutline";
/**
* As a thin horizontal line (sitting under a character).
*/
TextEditorCursorStyle[TextEditorCursorStyle["UnderlineThin"] = 6] = "UnderlineThin";
})(TextEditorCursorStyle || (TextEditorCursorStyle = {}));
function _cursorStyleFromString(cursorStyle) {
switch (cursorStyle) {
case 'line': return TextEditorCursorStyle.Line;
case 'block': return TextEditorCursorStyle.Block;
case 'underline': return TextEditorCursorStyle.Underline;
case 'line-thin': return TextEditorCursorStyle.LineThin;
case 'block-outline': return TextEditorCursorStyle.BlockOutline;
case 'underline-thin': return TextEditorCursorStyle.UnderlineThin;
}
}
//#endregion
//#region editorClassName
class EditorClassName extends ComputedEditorOption {
constructor() {
super(126 /* editorClassName */, [65 /* mouseStyle */, 33 /* extraEditorClassName */]);
}
compute(env, options, _) {
const classNames = ['monaco-editor'];
if (options.get(33 /* extraEditorClassName */)) {
classNames.push(options.get(33 /* extraEditorClassName */));
}
if (env.extraEditorClassName) {
classNames.push(env.extraEditorClassName);
}
if (options.get(65 /* mouseStyle */) === 'default') {
classNames.push('mouse-default');
}
else if (options.get(65 /* mouseStyle */) === 'copy') {
classNames.push('mouse-copy');
}
if (options.get(99 /* showUnused */)) {
classNames.push('showUnused');
}
if (options.get(124 /* showDeprecated */)) {
classNames.push('showDeprecated');
}
return classNames.join(' ');
}
}
//#endregion
//#region emptySelectionClipboard
class EditorEmptySelectionClipboard extends EditorBooleanOption {
constructor() {
super(32 /* emptySelectionClipboard */, 'emptySelectionClipboard', true, { description: nls.localize('emptySelectionClipboard', "Controls whether copying without a selection copies the current line.") });
}
compute(env, options, value) {
return value && env.emptySelectionClipboard;
}
}
class EditorFind extends BaseEditorOption {
constructor() {
const defaults = {
cursorMoveOnType: true,
seedSearchStringFromSelection: 'always',
autoFindInSelection: 'never',
globalFindClipboard: false,
addExtraSpaceOnTop: true,
loop: true
};
super(35 /* find */, 'find', defaults, {
'editor.find.cursorMoveOnType': {
type: 'boolean',
default: defaults.cursorMoveOnType,
description: nls.localize('find.cursorMoveOnType', "Controls whether the cursor should jump to find matches while typing.")
},
'editor.find.seedSearchStringFromSelection': {
type: 'string',
enum: ['never', 'always', 'selection'],
default: defaults.seedSearchStringFromSelection,
enumDescriptions: [
nls.localize('editor.find.seedSearchStringFromSelection.never', 'Never seed search string from the editor selection.'),
nls.localize('editor.find.seedSearchStringFromSelection.always', 'Always seed search string from the editor selection, including word at cursor position.'),
nls.localize('editor.find.seedSearchStringFromSelection.selection', 'Only seed search string from the editor selection.')
],
description: nls.localize('find.seedSearchStringFromSelection', "Controls whether the search string in the Find Widget is seeded from the editor selection.")
},
'editor.find.autoFindInSelection': {
type: 'string',
enum: ['never', 'always', 'multiline'],
default: defaults.autoFindInSelection,
enumDescriptions: [
nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in Selection automatically (default).'),
nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in Selection automatically.'),
nls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in Selection automatically when multiple lines of content are selected.')
],
description: nls.localize('find.autoFindInSelection', "Controls the condition for turning on Find in Selection automatically.")
},
'editor.find.globalFindClipboard': {
type: 'boolean',
default: defaults.globalFindClipboard,
description: nls.localize('find.globalFindClipboard', "Controls whether the Find Widget should read or modify the shared find clipboard on macOS."),
included: platform.isMacintosh
},
'editor.find.addExtraSpaceOnTop': {
type: 'boolean',
default: defaults.addExtraSpaceOnTop,
description: nls.localize('find.addExtraSpaceOnTop', "Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.")
},
'editor.find.loop': {
type: 'boolean',
default: defaults.loop,
description: nls.localize('find.loop', "Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.")
},
});
}
validate(_input) {
if (!_input || typeof _input !== 'object') {
return this.defaultValue;
}
const input = _input;
return {
cursorMoveOnType: boolean(input.cursorMoveOnType, this.defaultValue.cursorMoveOnType),
seedSearchStringFromSelection: typeof _input.seedSearchStringFromSelection === 'boolean'
? (_input.seedSearchStringFromSelection ? 'always' : 'never')
: stringSet(input.seedSearchStringFromSelection, this.defaultValue.seedSearchStringFromSelection, ['never', 'always', 'selection']),
autoFindInSelection: typeof _input.autoFindInSelection === 'boolean'
? (_input.autoFindInSelection ? 'always' : 'never')
: stringSet(input.autoFindInSelection, this.defaultValue.autoFindInSelection, ['never', 'always', 'multiline']),
globalFindClipboard: boolean(input.globalFindClipboard, this.defaultValue.globalFindClipboard),
addExtraSpaceOnTop: boolean(input.addExtraSpaceOnTop, this.defaultValue.addExtraSpaceOnTop),
loop: boolean(input.loop, this.defaultValue.loop),
};
}
}
//#endregion
//#region fontLigatures
/**
* @internal
*/
export class EditorFontLigatures extends BaseEditorOption {
constructor() {
super(44 /* fontLigatures */, 'fontLigatures', EditorFontLigatures.OFF, {
anyOf: [
{
type: 'boolean',
description: nls.localize('fontLigatures', "Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property."),
},
{
type: 'string',
description: nls.localize('fontFeatureSettings', "Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.")
}
],
description: nls.localize('fontLigaturesGeneral', "Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property."),
default: false
});
}
validate(input) {
if (typeof input === 'undefined') {
return this.defaultValue;
}
if (typeof input === 'string') {
if (input === 'false') {
return EditorFontLigatures.OFF;
}
if (input === 'true') {
return EditorFontLigatures.ON;
}
return input;
}
if (Boolean(input)) {
return EditorFontLigatures.ON;
}
return EditorFontLigatures.OFF;
}
}
EditorFontLigatures.OFF = '"liga" off, "calt" off';
EditorFontLigatures.ON = '"liga" on, "calt" on';
//#endregion
//#region fontInfo
class EditorFontInfo extends ComputedEditorOption {
constructor() {
super(43 /* fontInfo */);
}
compute(env, options, _) {
return env.fontInfo;
}
}
//#endregion
//#region fontSize
class EditorFontSize extends SimpleEditorOption {
constructor() {
super(45 /* fontSize */, 'fontSize', EDITOR_FONT_DEFAULTS.fontSize, {
type: 'number',
minimum: 6,
maximum: 100,
default: EDITOR_FONT_DEFAULTS.fontSize,
description: nls.localize('fontSize', "Controls the font size in pixels.")
});
}
validate(input) {
let r = EditorFloatOption.float(input, this.defaultValue);
if (r === 0) {
return EDITOR_FONT_DEFAULTS.fontSize;
}
return EditorFloatOption.clamp(r, 6, 100);
}
compute(env, options, value) {
// The final fontSize respects the editor zoom level.
// So take the result from env.fontInfo
return env.fontInfo.fontSize;
}
}
//#endregion
//#region fontWeight
class EditorFontWeight extends BaseEditorOption {
constructor() {
super(46 /* fontWeight */, 'fontWeight', EDITOR_FONT_DEFAULTS.fontWeight, {
anyOf: [
{
type: 'number',
minimum: EditorFontWeight.MINIMUM_VALUE,
maximum: EditorFontWeight.MAXIMUM_VALUE,
errorMessage: nls.localize('fontWeightErrorMessage', "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.")
},
{
type: 'string',
pattern: '^(normal|bold|1000|[1-9][0-9]{0,2})$'
},
{
enum: EditorFontWeight.SUGGESTION_VALUES
}
],
default: EDITOR_FONT_DEFAULTS.fontWeight,
description: nls.localize('fontWeight', "Controls the font weight. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000.")
});
}
validate(input) {
if (input === 'normal' || input === 'bold') {
return input;
}
return String(EditorIntOption.clampedInt(input, EDITOR_FONT_DEFAULTS.fontWeight, EditorFontWeight.MINIMUM_VALUE, EditorFontWeight.MAXIMUM_VALUE));
}
}
EditorFontWeight.SUGGESTION_VALUES = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
EditorFontWeight.MINIMUM_VALUE = 1;
EditorFontWeight.MAXIMUM_VALUE = 1000;
class EditorGoToLocation extends BaseEditorOption {
constructor() {
const defaults = {
multiple: 'peek',
multipleDefinitions: 'peek',
multipleTypeDefinitions: 'peek',
multipleDeclarations: 'peek',
multipleImplementations: 'peek',
multipleReferences: 'peek',
alternativeDefinitionCommand: 'editor.action.goToReferences',
alternativeTypeDefinitionCommand: 'editor.action.goToReferences',
alternativeDeclarationCommand: 'editor.action.goToReferences',
alternativeImplementationCommand: '',
alternativeReferenceCommand: '',
};
const jsonSubset = {
type: 'string',
enum: ['peek', 'gotoAndPeek', 'goto'],
default: defaults.multiple,
enumDescriptions: [
nls.localize('editor.gotoLocation.multiple.peek', 'Show peek view of the results (default)'),
nls.localize('editor.gotoLocation.multiple.gotoAndPeek', 'Go to the primary result and show a peek view'),
nls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and enable peek-less navigation to others')
]
};
const alternativeCommandOptions = ['', 'editor.action.referenceSearch.trigger', 'editor.action.goToReferences', 'editor.action.peekImplementation', 'editor.action.goToImplementation', 'editor.action.peekTypeDefinition', 'editor.action.goToTypeDefinition', 'editor.action.peekDeclaration', 'editor.action.revealDeclaration', 'editor.action.peekDefinition', 'editor.action.revealDefinitionAside', 'editor.action.revealDefinition'];
super(50 /* gotoLocation */, 'gotoLocation', defaults, {
'editor.gotoLocation.multiple': {
deprecationMessage: nls.localize('editor.gotoLocation.multiple.deprecated', "This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead."),
},
'editor.gotoLocation.multipleDefinitions': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleDefinitions', "Controls the behavior the 'Go to Definition'-command when multiple target locations exist.") }, jsonSubset),
'editor.gotoLocation.multipleTypeDefinitions': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleTypeDefinitions', "Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist.") }, jsonSubset),
'editor.gotoLocation.multipleDeclarations': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleDeclarations', "Controls the behavior the 'Go to Declaration'-command when multiple target locations exist.") }, jsonSubset),
'editor.gotoLocation.multipleImplementations': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleImplemenattions', "Controls the behavior the 'Go to Implementations'-command when multiple target locations exist.") }, jsonSubset),
'editor.gotoLocation.multipleReferences': Object.assign({ description: nls.localize('editor.editor.gotoLocation.multipleReferences', "Controls the behavior the 'Go to References'-command when multiple target locations exist.") }, jsonSubset),
'editor.gotoLocation.alternativeDefinitionCommand': {
type: 'string',
default: defaults.alternativeDefinitionCommand,
enum: alternativeCommandOptions,
description: nls.localize('alternativeDefinitionCommand', "Alternative command id that is being executed when the result of 'Go to Definition' is the current location.")
},
'editor.gotoLocation.alternativeTypeDefinitionCommand': {
type: 'string',
default: defaults.alternativeTypeDefinitionCommand,
enum: alternativeCommandOptions,
description: nls.localize('alternativeTypeDefinitionCommand', "Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.")
},
'editor.gotoLocation.alternativeDeclarationCommand': {
type: 'string',
default: defaults.alternativeDeclarationCommand,
enum: alternativeCommandOptions,
description: nls.localize('alternativeDeclarationCommand', "Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.")
},
'editor.gotoLocation.alternativeImplementationCommand': {
type: 'string',
default: defaults.alternativeImplementationCommand,
enum: alternativeCommandOptions,
description: nls.localize('alternativeImplementationCommand', "Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.")
},
'editor.gotoLocation.alternativeReferenceCommand': {
type: 'string',
default: defaults.alternativeReferenceCommand,
enum: alternativeCommandOptions,
description: nls.localize('alternativeReferenceCommand', "Alternative command id that is being executed when the result of 'Go to Reference' is the current location.")
},
});
}
validate(_input) {
var _a, _b, _c, _d, _e;
if (!_input || typeof _input !== 'object') {
return this.defaultValue;
}
const input = _input;
return {
multiple: stringSet(input.multiple, this.defaultValue.multiple, ['peek', 'gotoAndPeek', 'goto']),
multipleDefinitions: (_a = input.multipleDefinitions) !== null && _a !== void 0 ? _a : stringSet(input.multipleDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),
multipleTypeDefinitions: (_b = input.multipleTypeDefinitions) !== null && _b !== void 0 ? _b : stringSet(input.multipleTypeDefinitions, 'peek', ['peek', 'gotoAndPeek', 'goto']),
multipleDeclarations: (_c = input.multipleDeclarations) !== null && _c !== void 0 ? _c : stringSet(input.multipleDeclarations, 'peek', ['peek', 'gotoAndPeek', 'goto']),
multipleImplementations: (_d = input.multipleImplementations) !== null && _d !== void 0 ? _d : stringSet(input.multipleImplementations, 'peek', ['peek', 'gotoAndPeek', 'goto']),
multipleReferences: (_e = input.multipleReferences) !== null && _e !== void 0 ? _e : stringSet(input.multipleReferences, 'peek', ['peek', 'gotoAndPeek', 'goto']),
alternativeDefinitionCommand: EditorStringOption.string(input.alternativeDefinitionCommand, this.defaultValue.alternativeDefinitionCommand),
alternativeTypeDefinitionCommand: EditorStringOption.string(input.alternativeTypeDefinitionCommand, this.defaultValue.alternativeTypeDefinitionCommand),
alternativeDeclarationCommand: EditorStringOption.string(input.alternativeDeclarationCommand, this.defaultValue.alternativeDeclarationCommand),
alternativeImplementationCommand: EditorStringOption.string(input.alternativeImplementationCommand, this.defaultValue.alternativeImplementationCommand),
alternativeReferenceCommand: EditorStringOption.string(input.alternativeReferenceCommand, this.defaultValue.alternativeReferenceCommand),
};
}
}
class EditorHover extends BaseEditorOption {
constructor() {
const defaults = {
enabled: true,
delay: 300,
sticky: true,
above: true,
};
super(52 /* hover */, 'hover', defaults, {
'editor.hover.enabled': {
type: 'boolean',
default: defaults.enabled,
description: nls.localize('hover.enabled', "Controls whether the hover is shown.")
},
'editor.hover.delay': {
type: 'number',
default: defaults.delay,
description: nls.localize('hover.delay', "Controls the delay in milliseconds after which the hover is shown.")
},
'editor.hover.sticky': {
type: 'boolean',
default: defaults.sticky,
description: nls.localize('hover.sticky', "Controls whether the hover should remain visible when mouse is moved over it.")
},
'editor.hover.above': {
type: 'boolean',
default: defaults.above,
description: nls.localize('hover.above', "Prefer showing hovers above the line, if there's space.")
},
});
}
validate(_input) {
if (!_input || typeof _input !== 'object') {
return this.defaultValue;
}
const input = _input;
return {
enabled: boolean(input.enabled, this.defaultValue.enabled),
delay: EditorIntOption.clampedInt(input.delay, this.defaultValue.delay, 0, 10000),
sticky: boolean(input.sticky, this.defaultValue.sticky),
above: boolean(input.above, this.defaultValue.above),
};
}
}
/**
* @internal
*/
export class EditorLayoutInfoComputer extends ComputedEditorOption {
constructor() {
super(129 /* layoutInfo */, [
49 /* glyphMargin */, 57 /* lineDecorationsWidth */, 37 /* folding */,
64 /* minimap */, 91 /* scrollbar */, 59 /* lineNumbers */,
60 /* lineNumbersMinChars */, 93 /* scrollBeyondLastLine */,
116 /* wordWrap */, 119 /* wordWrapColumn */, 120 /* wordWrapOverride1 */, 121 /* wordWrapOverride2 */,
2 /* accessibilitySupport */
]);
}
compute(env, options, _) {
return EditorLayoutInfoComputer.computeLayout(options, {
memory: env.memory,
outerWidth: env.outerWidth,
outerHeight: env.outerHeight,
isDominatedByLongLines: env.isDominatedByLongLines,
lineHeight: env.fontInfo.lineHeight,
viewLineCount: env.viewLineCount,
lineNumbersDigitCount: env.lineNumbersDigitCount,
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
maxDigitWidth: env.fontInfo.maxDigitWidth,
pixelRatio: env.pixelRatio
});
}
static computeContainedMinimapLineCount(input) {
const typicalViewportLineCount = input.height / input.lineHeight;
const extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;
const desiredRatio = (input.viewLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);
const minimapLineCount = Math.floor(input.viewLineCount / desiredRatio);
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
}
static _computeMinimapLayout(input, memory) {
const outerWidth = input.outerWidth;
const outerHeight = input.outerHeight;
const pixelRatio = input.pixelRatio;
if (!input.minimap.enabled) {
return {
renderMinimap: 0 /* None */,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: Math.floor(pixelRatio * outerHeight),
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: outerHeight,
};
}
// Can use memory if only the `viewLineCount` and `remainingWidth` have changed
const stableMinimapLayoutInput = memory.stableMinimapLayoutInput;
const couldUseMemory = (stableMinimapLayoutInput
// && input.outerWidth === lastMinimapLayoutInput.outerWidth !!! INTENTIONAL OMITTED
&& input.outerHeight === stableMinimapLayoutInput.outerHeight
&& input.lineHeight === stableMinimapLayoutInput.lineHeight
&& input.typicalHalfwidthCharacterWidth === stableMinimapLayoutInput.typicalHalfwidthCharacterWidth
&& input.pixelRatio === stableMinimapLayoutInput.pixelRatio
&& input.scrollBeyondLastLine === stableMinimapLayoutInput.scrollBeyondLastLine
&& input.minimap.enabled === stableMinimapLayoutInput.minimap.enabled
&& input.minimap.side === stableMinimapLayoutInput.minimap.side
&& input.minimap.size === stableMinimapLayoutInput.minimap.size
&& input.minimap.showSlider === stableMinimapLayoutInput.minimap.showSlider
&& input.minimap.renderCharacters === stableMinimapLayoutInput.minimap.renderCharacters
&& input.minimap.maxColumn === stableMinimapLayoutInput.minimap.maxColumn
&& input.minimap.scale === stableMinimapLayoutInput.minimap.scale
&& input.verticalScrollbarWidth === stableMinimapLayoutInput.verticalScrollbarWidth
// && input.viewLineCount === lastMinimapLayoutInput.viewLineCount !!! INTENTIONAL OMITTED
// && input.remainingWidth === lastMinimapLayoutInput.remainingWidth !!! INTENTIONAL OMITTED
&& input.isViewportWrapping === stableMinimapLayoutInput.isViewportWrapping);
const lineHeight = input.lineHeight;
const typicalHalfwidthCharacterWidth = input.typicalHalfwidthCharacterWidth;
const scrollBeyondLastLine = input.scrollBeyondLastLine;
const minimapRenderCharacters = input.minimap.renderCharacters;
let minimapScale = (pixelRatio >= 2 ? Math.round(input.minimap.scale * 2) : input.minimap.scale);
const minimapMaxColumn = input.minimap.maxColumn;
const minimapSize = input.minimap.size;
const minimapSide = input.minimap.side;
const verticalScrollbarWidth = input.verticalScrollbarWidth;
const viewLineCount = input.viewLineCount;
const remainingWidth = input.remainingWidth;
const isViewportWrapping = input.isViewportWrapping;
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
let minimapHeightIsEditorHeight = false;
let minimapIsSampling = false;
let minimapLineHeight = baseCharHeight * minimapScale;
let minimapCharWidth = minimapScale / pixelRatio;
let minimapWidthMultiplier = 1;
if (minimapSize === 'fill' || minimapSize === 'fit') {
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
viewLineCount: viewLineCount,
scrollBeyondLastLine: scrollBeyondLastLine,
height: outerHeight,
lineHeight: lineHeight,
pixelRatio: pixelRatio
});
// ratio is intentionally not part of the layout to avoid the layout changing all the time
// when doing sampling
const ratio = viewLineCount / minimapLineCount;
if (ratio > 1) {
minimapHeightIsEditorHeight = true;
minimapIsSampling = true;
minimapScale = 1;
minimapLineHeight = 1;
minimapCharWidth = minimapScale / pixelRatio;
}
else {
let fitBecomesFill = false;
let maxMinimapScale = minimapScale + 1;
if (minimapSize === 'fit') {
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {
// There is a loop when using `fit` and viewport wrapping:
// - view line count impacts minimap layout
// - minimap layout impacts viewport width
// - viewport width impacts view line count
// To break the loop, once we go to a smaller minimap scale, we try to stick with it.
fitBecomesFill = true;
maxMinimapScale = memory.stableFitMaxMinimapScale;
}
else {
fitBecomesFill = (effectiveMinimapHeight > minimapCanvasInnerHeight);
}
}
if (minimapSize === 'fill' || fitBecomesFill) {
minimapHeightIsEditorHeight = true;
const configuredMinimapScale = minimapScale;
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {
// There is a loop when using `fill` and viewport wrapping:
// - view line count impacts minimap layout
// - minimap layout impacts viewport width
// - viewport width impacts view line count
// To break the loop, once we go to a smaller minimap scale, we try to stick with it.
maxMinimapScale = memory.stableFitMaxMinimapScale;
}
minimapScale = Math.min(maxMinimapScale, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
if (minimapScale > configuredMinimapScale) {
minimapWidthMultiplier = Math.min(2, minimapScale / configuredMinimapScale);
}
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
if (isViewportWrapping) {
// remember for next time
memory.stableMinimapLayoutInput = input;
memory.stableFitRemainingWidth = remainingWidth;
memory.stableFitMaxMinimapScale = minimapScale;
}
else {
memory.stableMinimapLayoutInput = null;
memory.stableFitRemainingWidth = 0;
}
}
}
}
// Given:
// (leaving 2px for the cursor to have space after the last character)
// viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth
// minimapWidth = viewportColumn * minimapCharWidth
// contentWidth = remainingWidth - minimapWidth
// What are good values for contentWidth and minimapWidth ?
// minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth
// typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth
// typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth
// (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth
// minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth)
const minimapMaxWidth = Math.floor(minimapMaxColumn * minimapCharWidth);
const minimapWidth = Math.min(minimapMaxWidth, Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH);
let minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
const minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
const renderMinimap = (minimapRenderCharacters ? 1 /* Text */ : 2 /* Blocks */);
const minimapLeft = (minimapSide === 'left' ? 0 : (outerWidth - minimapWidth - verticalScrollbarWidth));
return {
renderMinimap,
minimapLeft,
minimapWidth,
minimapHeightIsEditorHeight,
minimapIsSampling,
minimapScale,
minimapLineHeight,
minimapCanvasInnerWidth,
minimapCanvasInnerHeight,
minimapCanvasOuterWidth,
minimapCanvasOuterHeight,
};
}
static computeLayout(options, env) {
const outerWidth = env.outerWidth | 0;
const outerHeight = env.outerHeight | 0;
const lineHeight = env.lineHeight | 0;
const lineNumbersDigitCount = env.lineNumbersDigitCount | 0;
const typicalHalfwidthCharacterWidth = env.typicalHalfwidthCharacterWidth;
const maxDigitWidth = env.maxDigitWidth;
const pixelRatio = env.pixelRatio;
const viewLineCount = env.viewLineCount;
const wordWrapOverride2 = options.get(121 /* wordWrapOverride2 */);
const wordWrapOverride1 = (wordWrapOverride2 === 'inherit' ? options.get(120 /* wordWrapOverride1 */) : wordWrapOverride2);
const wordWrap = (wordWrapOverride1 === 'inherit' ? options.get(116 /* wordWrap */) : wordWrapOverride1);
const wordWrapColumn = options.get(119 /* wordWrapColumn */);
const accessibilitySupport = options.get(2 /* accessibilitySupport */);
const isDominatedByLongLines = env.isDominatedByLongLines;
const showGlyphMargin = options.get(49 /* glyphMargin */);
const showLineNumbers = (options.get(59 /* lineNumbers */).renderType !== 0 /* Off */);
const lineNumbersMinChars = options.get(60 /* lineNumbersMinChars */);
const scrollBeyondLastLine = options.get(93 /* scrollBeyondLastLine */);
const minimap = options.get(64 /* minimap */);
const scrollbar = options.get(91 /* scrollbar */);
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize;
const verticalScrollbarHasArrows = scrollbar.verticalHasArrows;
const scrollbarArrowSize = scrollbar.arrowSize;
const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize;
const rawLineDecorationsWidth = options.get(57 /* lineDecorationsWidth */);
const folding = options.get(37 /* folding */);
let lineDecorationsWidth;
if (typeof rawLineDecorationsWidth === 'string' && /^\d+(\.\d+)?ch$/.test(rawLineDecorationsWidth)) {
const multiple = parseFloat(rawLineDecorationsWidth.substr(0, rawLineDecorationsWidth.length - 2));
lineDecorationsWidth = EditorIntOption.clampedInt(multiple * typicalHalfwidthCharacterWidth, 0, 0, 1000);
}
else {
lineDecorationsWidth = EditorIntOption.clampedInt(rawLineDecorationsWidth, 0, 0, 1000);
}
if (folding) {
lineDecorationsWidth += 16;
}
let lineNumbersWidth = 0;
if (showLineNumbers) {
const digitCount = Math.max(lineNumbersDigitCount, lineNumbersMinChars);
lineNumbersWidth = Math.round(digitCount * maxDigitWidth);
}
let glyphMarginWidth = 0;
if (showGlyphMargin) {
glyphMarginWidth = lineHeight;
}
let glyphMarginLeft = 0;
let lineNumbersLeft = glyphMarginLeft + glyphMarginWidth;
let decorationsLeft = lineNumbersLeft + lineNumbersWidth;
let contentLeft = decorationsLeft + lineDecorationsWidth;
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
let isWordWrapMinified = false;
let isViewportWrapping = false;
let wrappingColumn = -1;
if (accessibilitySupport !== 2 /* Enabled */) {
// See https://github.com/microsoft/vscode/issues/27766
// Never enable wrapping when a screen reader is attached
// because arrow down etc. will not move the cursor in the way
// a screen reader expects.
if (wordWrapOverride1 === 'inherit' && isDominatedByLongLines) {
// Force viewport width wrapping if model is dominated by long lines
isWordWrapMinified = true;
isViewportWrapping = true;
}
else if (wordWrap === 'on' || wordWrap === 'bounded') {
isViewportWrapping = true;
}
else if (wordWrap === 'wordWrapColumn') {
wrappingColumn = wordWrapColumn;
}
}
const minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({
outerWidth: outerWidth,
outerHeight: outerHeight,
lineHeight: lineHeight,
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,
pixelRatio: pixelRatio,
scrollBeyondLastLine: scrollBeyondLastLine,
minimap: minimap,
verticalScrollbarWidth: verticalScrollbarWidth,
viewLineCount: viewLineCount,
remainingWidth: remainingWidth,
isViewportWrapping: isViewportWrapping,
}, env.memory || new ComputeOptionsMemory());
if (minimapLayout.renderMinimap !== 0 /* None */ && minimapLayout.minimapLeft === 0) {
// the minimap is rendered to the left, so move everything to the right
glyphMarginLeft += minimapLayout.minimapWidth;
lineNumbersLeft += minimapLayout.minimapWidth;
decorationsLeft += minimapLayout.minimapWidth;
contentLeft += minimapLayout.minimapWidth;
}
const contentWidth = remainingWidth - minimapLayout.minimapWidth;
// (leaving 2px for the cursor to have space after the last character)
const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth));
const verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0);
if (isViewportWrapping) {
// compute the actual wrappingColumn
wrappingColumn = Math.max(1, viewportColumn);
if (wordWrap === 'bounded') {
wrappingColumn = Math.min(wrappingColumn, wordWrapColumn);
}
}
return {
width: outerWidth,
height: outerHeight,
glyphMarginLeft: glyphMarginLeft,
glyphMarginWidth: glyphMarginWidth,
lineNumbersLeft: lineNumbersLeft,
lineNumbersWidth: lineNumbersWidth,
decorationsLeft: decorationsLeft,
decorationsWidth: lineDecorationsWidth,
contentLeft: contentLeft,
contentWidth: contentWidth,
minimap: minimapLayout,
viewportColumn: viewportColumn,
isWordWrapMinified: isWordWrapMinified,
isViewportWrapping: isViewportWrapping,
wrappingColumn