Merge from vscode 9bc92b48d945144abb405b9e8df05e18accb9148

This commit is contained in:
ADS Merger
2020-02-19 03:11:35 +00:00
parent 98584d32a7
commit 1e308639e5
253 changed files with 6414 additions and 2296 deletions

View File

@@ -1614,7 +1614,7 @@ export namespace CoreEditingCommands {
constructor() {
super({
id: 'deleteLeft',
precondition: EditorContextKeys.writable,
precondition: undefined,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textInputFocus,
@@ -1639,7 +1639,7 @@ export namespace CoreEditingCommands {
constructor() {
super({
id: 'deleteRight',
precondition: EditorContextKeys.writable,
precondition: undefined,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textInputFocus,

View File

@@ -149,6 +149,10 @@ function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: numbe
return result;
}
const enum Constants {
SPAN_MODULO_LIMIT = 16384
}
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder): [number[], number[]] {
sb.appendASCIIString('<div style="width:');
sb.appendASCIIString(String(width));
@@ -164,7 +168,11 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
let visibleColumns: number[] = [];
let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);
sb.appendASCIIString('<span>');
for (let charIndex = 0; charIndex < len; charIndex++) {
if (charIndex !== 0 && charIndex % Constants.SPAN_MODULO_LIMIT === 0) {
sb.appendASCIIString('</span><span>');
}
charOffsets[charIndex] = charOffset;
visibleColumns[charIndex] = visibleColumn;
const charCode = nextCharCode;
@@ -227,6 +235,7 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
charOffset += producedCharacters;
visibleColumn += charWidth;
}
sb.appendASCIIString('</span>');
charOffsets[lineContent.length] = charOffset;
visibleColumns[lineContent.length] = visibleColumn;
@@ -240,10 +249,15 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
if (lineContent.length <= 1) {
return null;
}
const textContentNode = lineDomNode.firstChild!;
const spans = <HTMLSpanElement[]>Array.prototype.slice.call(lineDomNode.children, 0);
const breakOffsets: number[] = [];
discoverBreaks(range, textContentNode, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
try {
discoverBreaks(range, spans, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
} catch (err) {
console.log(err);
return null;
}
if (breakOffsets.length === 0) {
return null;
@@ -255,13 +269,13 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
type MaybeRects = ClientRectList | DOMRectList | null;
function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
function discoverBreaks(range: Range, spans: HTMLSpanElement[], charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
if (low === high) {
return;
}
lowRects = lowRects || readClientRect(range, textContentNode, charOffsets[low], charOffsets[low + 1]);
highRects = highRects || readClientRect(range, textContentNode, charOffsets[high], charOffsets[high + 1]);
lowRects = lowRects || readClientRect(range, spans, charOffsets[low], charOffsets[low + 1]);
highRects = highRects || readClientRect(range, spans, charOffsets[high], charOffsets[high + 1]);
if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {
// same line
@@ -276,13 +290,13 @@ function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number
}
const mid = low + ((high - low) / 2) | 0;
const midRects = readClientRect(range, textContentNode, charOffsets[mid], charOffsets[mid + 1]);
discoverBreaks(range, textContentNode, charOffsets, low, lowRects, mid, midRects, result);
discoverBreaks(range, textContentNode, charOffsets, mid, midRects, high, highRects, result);
const midRects = readClientRect(range, spans, charOffsets[mid], charOffsets[mid + 1]);
discoverBreaks(range, spans, charOffsets, low, lowRects, mid, midRects, result);
discoverBreaks(range, spans, charOffsets, mid, midRects, high, highRects, result);
}
function readClientRect(range: Range, textContentNode: Node, startOffset: number, endOffset: number): ClientRectList | DOMRectList {
range.setStart(textContentNode, startOffset);
range.setEnd(textContentNode, endOffset);
function readClientRect(range: Range, spans: HTMLSpanElement[], startOffset: number, endOffset: number): ClientRectList | DOMRectList {
range.setStart(spans[(startOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, startOffset % Constants.SPAN_MODULO_LIMIT);
range.setEnd(spans[(endOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, endOffset % Constants.SPAN_MODULO_LIMIT);
return range.getClientRects();
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,11 +34,13 @@ export class MinimapCharRenderer {
color: RGBA8,
backgroundColor: RGBA8,
fontScale: number,
useLighterFont: boolean
useLighterFont: boolean,
force1pxHeight: boolean
): void {
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
if (dx + charWidth > target.width || dy + charHeight > target.height) {
const renderHeight = (force1pxHeight ? 1 : charHeight);
if (dx + charWidth > target.width || dy + renderHeight > target.height) {
console.warn('bad render request outside image data');
return;
}
@@ -60,7 +62,7 @@ export class MinimapCharRenderer {
let sourceOffset = charIndex * charWidth * charHeight;
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
for (let y = 0; y < charHeight; y++) {
for (let y = 0; y < renderHeight; y++) {
let column = row;
for (let x = 0; x < charWidth; x++) {
const c = charData[sourceOffset++] / 255;
@@ -80,11 +82,13 @@ export class MinimapCharRenderer {
dy: number,
color: RGBA8,
backgroundColor: RGBA8,
useLighterFont: boolean
useLighterFont: boolean,
force1pxHeight: boolean
): void {
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
if (dx + charWidth > target.width || dy + charHeight > target.height) {
const renderHeight = (force1pxHeight ? 1 : charHeight);
if (dx + charWidth > target.width || dy + renderHeight > target.height) {
console.warn('bad render request outside image data');
return;
}
@@ -108,7 +112,7 @@ export class MinimapCharRenderer {
const dest = target.data;
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
for (let y = 0; y < charHeight; y++) {
for (let y = 0; y < renderHeight; y++) {
let column = row;
for (let x = 0; x < charWidth; x++) {
dest[column++] = colorR;

View File

@@ -276,7 +276,10 @@ export class DecorationsOverviewRuler extends ViewPart {
return true;
}
public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {
return true;
if (e.affectsOverviewRuler) {
return true;
}
return false;
}
public onFlushed(e: viewEvents.ViewFlushedEvent): boolean {
return true;

View File

@@ -287,6 +287,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
public options!: ComputedEditorOptions;
private _isDominatedByLongLines: boolean;
private _maxLineNumber: number;
private _lineNumbersDigitCount: number;
private _rawOptions: IEditorOptions;
@@ -298,6 +299,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
this.isSimpleWidget = isSimpleWidget;
this._isDominatedByLongLines = false;
this._maxLineNumber = 1;
this._lineNumbersDigitCount = 1;
this._rawOptions = deepCloneAndMigrateOptions(_options);
@@ -347,6 +349,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
fontInfo: this.readConfiguration(bareFontInfo),
extraEditorClassName: partialEnv.extraEditorClassName,
isDominatedByLongLines: this._isDominatedByLongLines,
maxLineNumber: this._maxLineNumber,
lineNumbersDigitCount: this._lineNumbersDigitCount,
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
pixelRatio: partialEnv.pixelRatio,
@@ -405,11 +408,11 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
}
public setMaxLineNumber(maxLineNumber: number): void {
let digitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
if (this._lineNumbersDigitCount === digitCount) {
if (this._maxLineNumber === maxLineNumber) {
return;
}
this._lineNumbersDigitCount = digitCount;
this._maxLineNumber = maxLineNumber;
this._lineNumbersDigitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
this._recomputeOptions();
}

View File

@@ -678,6 +678,7 @@ export interface IEnvironmentalOptions {
readonly fontInfo: FontInfo;
readonly extraEditorClassName: string;
readonly isDominatedByLongLines: boolean;
readonly maxLineNumber: number;
readonly lineNumbersDigitCount: number;
readonly emptySelectionClipboard: boolean;
readonly pixelRatio: number;
@@ -1691,6 +1692,14 @@ export interface EditorLayoutInfo {
* The width of the minimap
*/
readonly minimapWidth: number;
readonly minimapHeightIsEditorHeight: boolean;
readonly minimapIsSampling: boolean;
readonly minimapScale: number;
readonly minimapLineHeight: number;
readonly minimapCanvasInnerWidth: number;
readonly minimapCanvasInnerHeight: number;
readonly minimapCanvasOuterWidth: number;
readonly minimapCanvasOuterHeight: number;
/**
* Minimap render type
@@ -1724,6 +1733,7 @@ export interface EditorLayoutInfoComputerEnv {
outerWidth: number;
outerHeight: number;
lineHeight: number;
maxLineNumber: number;
lineNumbersDigitCount: number;
typicalHalfwidthCharacterWidth: number;
maxDigitWidth: number;
@@ -1747,6 +1757,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
outerWidth: env.outerWidth,
outerHeight: env.outerHeight,
lineHeight: env.fontInfo.lineHeight,
maxLineNumber: env.maxLineNumber,
lineNumbersDigitCount: env.lineNumbersDigitCount,
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
maxDigitWidth: env.fontInfo.maxDigitWidth,
@@ -1754,6 +1765,20 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
});
}
public static computeContainedMinimapLineCount(input: {
modelLineCount: number;
scrollBeyondLastLine: boolean;
height: number;
lineHeight: number;
pixelRatio: number;
}): { typicalViewportLineCount: number; extraLinesBeyondLastLine: number; desiredRatio: number; minimapLineCount: number; } {
const typicalViewportLineCount = input.height / input.lineHeight;
const extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;
const desiredRatio = (input.modelLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);
const minimapLineCount = Math.floor(input.modelLineCount / desiredRatio);
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
}
public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
const outerWidth = env.outerWidth | 0;
const outerHeight = env.outerHeight | 0;
@@ -1766,12 +1791,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
const showGlyphMargin = options.get(EditorOption.glyphMargin);
const showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars) | 0;
const scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
const minimap = options.get(EditorOption.minimap);
const minimapEnabled = minimap.enabled;
const minimapSide = minimap.side;
const minimapRenderCharacters = minimap.renderCharacters;
const minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
const minimapMaxColumn = minimap.maxColumn | 0;
const minimapMode = minimap.mode;
const scrollbar = options.get(EditorOption.scrollbar);
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
@@ -1811,19 +1838,65 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
let renderMinimap: RenderMinimap;
let minimapLeft: number;
let minimapWidth: number;
let minimapCanvasInnerWidth: number;
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
let minimapCanvasOuterWidth: number;
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
let minimapHeightIsEditorHeight = false;
let minimapIsSampling = false;
let minimapLineHeight = baseCharHeight * minimapScale;
let contentWidth: number;
if (!minimapEnabled) {
minimapLeft = 0;
minimapWidth = 0;
minimapCanvasInnerWidth = 0;
minimapCanvasOuterWidth = 0;
minimapLineHeight = 1;
renderMinimap = RenderMinimap.None;
contentWidth = remainingWidth;
} else {
// The minimapScale is also the pixel width of each character. Adjust
// for the pixel ratio of the screen.
const minimapCharWidth = minimapScale / pixelRatio;
let minimapCharWidth = minimapScale / pixelRatio;
let minimapWidthMultiplier: number = 1;
if (minimapMode === 'cover' || minimapMode === 'contain') {
const modelLineCount = env.maxLineNumber;
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
modelLineCount: modelLineCount,
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 = modelLineCount / minimapLineCount;
if (ratio > 1) {
minimapHeightIsEditorHeight = true;
minimapIsSampling = true;
minimapScale = 1;
minimapLineHeight = 1;
minimapCharWidth = minimapScale / pixelRatio;
} else {
const effectiveMinimapHeight = Math.ceil((modelLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
if (minimapMode === 'cover' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
minimapHeightIsEditorHeight = true;
const configuredFontScale = minimapScale;
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
minimapScale = Math.min(configuredFontScale + 1, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
if (minimapScale > configuredFontScale) {
minimapWidthMultiplier = Math.min(2, minimapScale / configuredFontScale);
}
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, modelLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
}
}
}
renderMinimap = minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks;
// Given:
@@ -1855,6 +1928,10 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
} else {
minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth;
}
minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
}
// (leaving 2px for the cursor to have space after the last character)
@@ -1881,6 +1958,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
renderMinimap: renderMinimap,
minimapLeft: minimapLeft,
minimapWidth: minimapWidth,
minimapHeightIsEditorHeight: minimapHeightIsEditorHeight,
minimapIsSampling: minimapIsSampling,
minimapScale: minimapScale,
minimapLineHeight: minimapLineHeight,
minimapCanvasInnerWidth: minimapCanvasInnerWidth,
minimapCanvasInnerHeight: minimapCanvasInnerHeight,
minimapCanvasOuterWidth: minimapCanvasOuterWidth,
minimapCanvasOuterHeight: minimapCanvasOuterHeight,
viewportColumn: viewportColumn,
@@ -1981,6 +2066,11 @@ export interface IEditorMinimapOptions {
* Defaults to 'right'.
*/
side?: 'right' | 'left';
/**
* Control the minimap rendering mode.
* Defaults to 'actual'.
*/
mode?: 'actual' | 'cover' | 'contain';
/**
* Control the rendering of the minimap slider.
* Defaults to 'mouseover'.
@@ -1996,7 +2086,6 @@ export interface IEditorMinimapOptions {
* Defaults to 120.
*/
maxColumn?: number;
/**
* Relative size of the font in the minimap. Defaults to 1.
*/
@@ -2010,6 +2099,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
constructor() {
const defaults: EditorMinimapOptions = {
enabled: false, // {{SQL CARBON EDIT}} disable minimap by default
mode: 'actual',
side: 'right',
showSlider: 'mouseover',
renderCharacters: true,
@@ -2024,6 +2114,17 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
default: defaults.enabled,
description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
},
'editor.minimap.mode': {
type: 'string',
enum: ['actual', 'cover', 'contain'],
enumDescriptions: [
nls.localize('minimap.mode.actual', "The minimap will be displayed in its original size, so it might be higher than the editor."),
nls.localize('minimap.mode.cover', "The minimap will always have the height of the editor and will stretch or shrink as necessary."),
nls.localize('minimap.mode.contain', "The minimap will shrink as necessary to never be higher than the editor."),
],
default: defaults.mode,
description: nls.localize('minimap.mode', "Controls the rendering mode of the minimap.")
},
'editor.minimap.side': {
type: 'string',
enum: ['left', 'right'],
@@ -2052,7 +2153,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
type: 'number',
default: defaults.maxColumn,
description: nls.localize('minimap.maxColumn', "Limit the width of the minimap to render at most a certain number of columns.")
},
}
}
);
}
@@ -2064,6 +2165,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
const input = _input as IEditorMinimapOptions;
return {
enabled: EditorBooleanOption.boolean(input.enabled, this.defaultValue.enabled),
mode: EditorStringEnumOption.stringSet<'actual' | 'cover' | 'contain'>(input.mode, this.defaultValue.mode, ['actual', 'cover', 'contain']),
side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),
showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),
renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters),

View File

@@ -1423,19 +1423,15 @@ export class TextModel extends Disposable implements model.ITextModel {
private _changeDecorations<T>(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T | null {
let changeAccessor: model.IModelDecorationsChangeAccessor = {
addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => {
this._onDidChangeDecorations.fire();
return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];
},
changeDecoration: (id: string, newRange: IRange): void => {
this._onDidChangeDecorations.fire();
this._changeDecorationImpl(id, newRange);
},
changeDecorationOptions: (id: string, options: model.IModelDecorationOptions) => {
this._onDidChangeDecorations.fire();
this._changeDecorationOptionsImpl(id, _normalizeOptions(options));
},
removeDecoration: (id: string): void => {
this._onDidChangeDecorations.fire();
this._deltaDecorationsImpl(ownerId, [id], []);
},
deltaDecorations: (oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] => {
@@ -1443,7 +1439,6 @@ export class TextModel extends Disposable implements model.ITextModel {
// nothing to do
return [];
}
this._onDidChangeDecorations.fire();
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
}
};
@@ -1474,7 +1469,6 @@ export class TextModel extends Disposable implements model.ITextModel {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._onDidChangeDecorations.fire();
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
} finally {
this._onDidChangeDecorations.endDeferredEmit();
@@ -1622,6 +1616,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this._decorationsTree.delete(node);
node.reset(this.getVersionId(), startOffset, endOffset, range);
this._decorationsTree.insert(node);
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
}
private _changeDecorationOptionsImpl(decorationId: string, options: ModelDecorationOptions): void {
@@ -1633,6 +1628,9 @@ export class TextModel extends Disposable implements model.ITextModel {
const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
this._onDidChangeDecorations.checkAffectedAndFire(options);
if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {
// Delete + Insert due to an overview ruler status change
this._decorationsTree.delete(node);
@@ -1666,6 +1664,7 @@ export class TextModel extends Disposable implements model.ITextModel {
// (2) remove the node from the tree (if it exists)
if (node) {
this._decorationsTree.delete(node);
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
}
}
@@ -1688,6 +1687,7 @@ export class TextModel extends Disposable implements model.ITextModel {
node.ownerId = ownerId;
node.reset(versionId, startOffset, endOffset, range);
node.setOptions(options);
this._onDidChangeDecorations.checkAffectedAndFire(options);
this._decorationsTree.insert(node);
@@ -1713,7 +1713,7 @@ export class TextModel extends Disposable implements model.ITextModel {
throw new Error('Illegal value for lineNumber');
}
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens);
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens, false);
}
public setTokens(tokens: MultilineTokens[]): void {
@@ -1725,16 +1725,34 @@ export class TextModel extends Disposable implements model.ITextModel {
for (let i = 0, len = tokens.length; i < len; i++) {
const element = tokens[i];
ranges.push({ fromLineNumber: element.startLineNumber, toLineNumber: element.startLineNumber + element.tokens.length - 1 });
let minChangedLineNumber = 0;
let maxChangedLineNumber = 0;
let hasChange = false;
for (let j = 0, lenJ = element.tokens.length; j < lenJ; j++) {
this.setLineTokens(element.startLineNumber + j, element.tokens[j]);
const lineNumber = element.startLineNumber + j;
if (hasChange) {
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], false);
maxChangedLineNumber = lineNumber;
} else {
const lineHasChange = this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], true);
if (lineHasChange) {
hasChange = true;
minChangedLineNumber = lineNumber;
maxChangedLineNumber = lineNumber;
}
}
}
if (hasChange) {
ranges.push({ fromLineNumber: minChangedLineNumber, toLineNumber: maxChangedLineNumber });
}
}
this._emitModelTokensChangedEvent({
tokenizationSupportChanged: false,
ranges: ranges
});
if (ranges.length > 0) {
this._emitModelTokensChangedEvent({
tokenizationSupportChanged: false,
ranges: ranges
});
}
}
public setSemanticTokens(tokens: MultilineTokens2[] | null): void {
@@ -3083,11 +3101,15 @@ export class DidChangeDecorationsEmitter extends Disposable {
private _deferredCnt: number;
private _shouldFire: boolean;
private _affectsMinimap: boolean;
private _affectsOverviewRuler: boolean;
constructor() {
super();
this._deferredCnt = 0;
this._shouldFire = false;
this._affectsMinimap = false;
this._affectsOverviewRuler = false;
}
public beginDeferredEmit(): void {
@@ -3098,13 +3120,31 @@ export class DidChangeDecorationsEmitter extends Disposable {
this._deferredCnt--;
if (this._deferredCnt === 0) {
if (this._shouldFire) {
const event: IModelDecorationsChangedEvent = {
affectsMinimap: this._affectsMinimap,
affectsOverviewRuler: this._affectsOverviewRuler,
};
this._shouldFire = false;
this._actual.fire({});
this._affectsMinimap = false;
this._affectsOverviewRuler = false;
this._actual.fire(event);
}
}
}
public checkAffectedAndFire(options: ModelDecorationOptions): void {
if (!this._affectsMinimap) {
this._affectsMinimap = options.minimap && options.minimap.position ? true : false;
}
if (!this._affectsOverviewRuler) {
this._affectsOverviewRuler = options.overviewRuler && options.overviewRuler.color ? true : false;
}
this._shouldFire = true;
}
public fire(): void {
this._affectsMinimap = true;
this._affectsOverviewRuler = true;
this._shouldFire = true;
}
}

View File

@@ -76,6 +76,8 @@ export interface IModelContentChangedEvent {
* An event describing that model decorations have changed.
*/
export interface IModelDecorationsChangedEvent {
readonly affectsMinimap: boolean;
readonly affectsOverviewRuler: boolean;
}
/**

View File

@@ -964,10 +964,35 @@ export class TokensStore {
this._len += insertCount;
}
public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null): void {
public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null, checkEquality: boolean): boolean {
const tokens = TokensStore._massageTokens(topLevelLanguageId, lineTextLength, _tokens);
this._ensureLine(lineIndex);
const oldTokens = this._lineTokens[lineIndex];
this._lineTokens[lineIndex] = tokens;
if (checkEquality) {
return !TokensStore._equals(oldTokens, tokens);
}
return false;
}
private static _equals(_a: Uint32Array | ArrayBuffer | null, _b: Uint32Array | ArrayBuffer | null) {
if (!_a || !_b) {
return !_a && !_b;
}
const a = toUint32Array(_a);
const b = toUint32Array(_b);
if (a.length !== b.length) {
return false;
}
for (let i = 0, len = a.length; i < len; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
//#region Editing

View File

@@ -274,6 +274,16 @@ export class LanguageConfigurationRegistryImpl {
return ensureValidWordDefinition(value.wordDefinition || null);
}
public getWordDefinitions(): [LanguageId, RegExp][] {
let result: [LanguageId, RegExp][] = [];
this._entries.forEach((value, language) => {
if (value) {
result.push([language, value.wordDefinition]);
}
});
return result;
}
public getFoldingRules(languageId: LanguageId): FoldingRules {
let value = this._getRichEditSupport(languageId);
if (!value) {

View File

@@ -10,6 +10,7 @@ import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ScrollType, IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
export const enum ViewEventType {
ViewConfigurationChanged = 1,
@@ -82,8 +83,17 @@ export class ViewDecorationsChangedEvent {
public readonly type = ViewEventType.ViewDecorationsChanged;
constructor() {
// Nothing to do
readonly affectsMinimap: boolean;
readonly affectsOverviewRuler: boolean;
constructor(source: IModelDecorationsChangedEvent | null) {
if (source) {
this.affectsMinimap = source.affectsMinimap;
this.affectsOverviewRuler = source.affectsOverviewRuler;
} else {
this.affectsMinimap = true;
this.affectsOverviewRuler = true;
}
}
}

View File

@@ -172,7 +172,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
if (this.lines.setWrappingSettings(fontInfo, wrappingStrategy, wrappingInfo.wrappingColumn, wrappingIndent)) {
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
this.decorations.onLineMappingChanged();
this.viewLayout.onFlushed(this.getLineCount());
@@ -185,7 +185,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
if (e.hasChanged(EditorOption.readOnly)) {
// Must read again all decorations due to readOnly filtering
this.decorations.reset();
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
}
eventsCollector.emit(new viewEvents.ViewConfigurationChangedEvent(e));
@@ -291,7 +291,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
this.decorations.onLineMappingChanged();
}
} finally {
@@ -354,7 +354,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
const eventsCollector = this._beginEmit();
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
} finally {
this._endEmit();
}
@@ -365,7 +365,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.decorations.onModelDecorationsChanged();
try {
const eventsCollector = this._beginEmit();
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(e));
} finally {
this._endEmit();
}
@@ -379,7 +379,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
if (lineMappingChanged) {
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
this.decorations.onLineMappingChanged();
this.viewLayout.onFlushed(this.getLineCount());
this.viewLayout.onHeightMaybeChanged();

View File

@@ -419,8 +419,9 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
if (currentMatch) {
const ariaLabel = nls.localize('ariaSearchNoResultWithLineNum', "{0} found for '{1}', at {2}", label, searchString, currentMatch.startLineNumber + ':' + currentMatch.startColumn);
const lineContent = this._codeEditor.getModel()?.getLineContent(currentMatch.startLineNumber);
if (lineContent) {
const model = this._codeEditor.getModel();
if (model && (currentMatch.startLineNumber <= model.getLineCount()) && (currentMatch.startLineNumber >= 1)) {
const lineContent = model.getLineContent(currentMatch.startLineNumber);
return `${lineContent}, ${ariaLabel}`;
}

View File

@@ -180,9 +180,11 @@ suite('SmartSelect', () => {
// -- bracket selections
async function assertRanges(provider: SelectionRangeProvider, value: string, ...expected: IRange[]): Promise<void> {
let index = value.indexOf('|');
value = value.replace('|', '');
let model = modelService.createModel(value, new StaticLanguageSelector(mode.getLanguageIdentifier()), URI.parse('fake:lang'));
let pos = model.getPositionAt(value.indexOf('|'));
let pos = model.getPositionAt(index);
let all = await provider.provideSelectionRanges(model, [pos], CancellationToken.None);
let ranges = all![0];
@@ -197,18 +199,18 @@ suite('SmartSelect', () => {
test('bracket selection', async () => {
await assertRanges(new BracketSelectionRangeProvider(), '(|)',
new Range(1, 2, 1, 3), new Range(1, 1, 1, 4)
new Range(1, 2, 1, 2), new Range(1, 1, 1, 3)
);
await assertRanges(new BracketSelectionRangeProvider(), '[[[](|)]]',
new Range(1, 6, 1, 7), new Range(1, 5, 1, 8), // ()
new Range(1, 3, 1, 8), new Range(1, 2, 1, 9), // [[]()]
new Range(1, 2, 1, 9), new Range(1, 1, 1, 10), // [[[]()]]
new Range(1, 6, 1, 6), new Range(1, 5, 1, 7), // ()
new Range(1, 3, 1, 7), new Range(1, 2, 1, 8), // [[]()]
new Range(1, 2, 1, 8), new Range(1, 1, 1, 9), // [[[]()]]
);
await assertRanges(new BracketSelectionRangeProvider(), '[a[](|)a]',
new Range(1, 6, 1, 7), new Range(1, 5, 1, 8),
new Range(1, 2, 1, 9), new Range(1, 1, 1, 10),
new Range(1, 6, 1, 6), new Range(1, 5, 1, 7),
new Range(1, 2, 1, 8), new Range(1, 1, 1, 9),
);
// no bracket
@@ -219,23 +221,23 @@ suite('SmartSelect', () => {
await assertRanges(new BracketSelectionRangeProvider(), '|[[[]()]]');
// edge
await assertRanges(new BracketSelectionRangeProvider(), '[|[[]()]]', new Range(1, 2, 1, 9), new Range(1, 1, 1, 10));
await assertRanges(new BracketSelectionRangeProvider(), '[[[]()]|]', new Range(1, 2, 1, 9), new Range(1, 1, 1, 10));
await assertRanges(new BracketSelectionRangeProvider(), '[|[[]()]]', new Range(1, 2, 1, 8), new Range(1, 1, 1, 9));
await assertRanges(new BracketSelectionRangeProvider(), '[[[]()]|]', new Range(1, 2, 1, 8), new Range(1, 1, 1, 9));
await assertRanges(new BracketSelectionRangeProvider(), 'aaa(aaa)bbb(b|b)ccc(ccc)', new Range(1, 13, 1, 16), new Range(1, 12, 1, 17));
await assertRanges(new BracketSelectionRangeProvider(), '(aaa(aaa)bbb(b|b)ccc(ccc))', new Range(1, 14, 1, 17), new Range(1, 13, 1, 18), new Range(1, 2, 1, 26), new Range(1, 1, 1, 27));
await assertRanges(new BracketSelectionRangeProvider(), 'aaa(aaa)bbb(b|b)ccc(ccc)', new Range(1, 13, 1, 15), new Range(1, 12, 1, 16));
await assertRanges(new BracketSelectionRangeProvider(), '(aaa(aaa)bbb(b|b)ccc(ccc))', new Range(1, 14, 1, 16), new Range(1, 13, 1, 17), new Range(1, 2, 1, 25), new Range(1, 1, 1, 26));
});
test('bracket with leading/trailing', async () => {
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b){\n foo(|);\n}',
new Range(2, 7, 2, 8), new Range(2, 6, 2, 9),
new Range(2, 7, 2, 7), new Range(2, 6, 2, 8),
new Range(1, 13, 3, 1), new Range(1, 12, 3, 2),
new Range(1, 1, 3, 2), new Range(1, 1, 3, 2),
);
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b)\n{\n foo(|);\n}',
new Range(3, 7, 3, 8), new Range(3, 6, 3, 9),
new Range(3, 7, 3, 7), new Range(3, 6, 3, 8),
new Range(2, 2, 4, 1), new Range(2, 1, 4, 2),
new Range(1, 1, 4, 2), new Range(1, 1, 4, 2),
);
@@ -244,60 +246,60 @@ suite('SmartSelect', () => {
test('in-word ranges', async () => {
await assertRanges(new WordSelectionRangeProvider(), 'f|ooBar',
new Range(1, 1, 1, 5), // foo
new Range(1, 1, 1, 8), // fooBar
new Range(1, 1, 1, 8), // doc
new Range(1, 1, 1, 4), // foo
new Range(1, 1, 1, 7), // fooBar
new Range(1, 1, 1, 7), // doc
);
await assertRanges(new WordSelectionRangeProvider(), 'f|oo_Ba',
new Range(1, 1, 1, 5),
new Range(1, 1, 1, 8),
new Range(1, 1, 1, 8),
new Range(1, 1, 1, 4),
new Range(1, 1, 1, 7),
new Range(1, 1, 1, 7),
);
await assertRanges(new WordSelectionRangeProvider(), 'f|oo-Ba',
new Range(1, 1, 1, 5),
new Range(1, 1, 1, 8),
new Range(1, 1, 1, 8),
new Range(1, 1, 1, 4),
new Range(1, 1, 1, 7),
new Range(1, 1, 1, 7),
);
});
test('Default selection should select current word/hump first in camelCase #67493', async function () {
await assertRanges(new WordSelectionRangeProvider(), 'Abs|tractSmartSelect',
new Range(1, 1, 1, 10),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 9),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
await assertRanges(new WordSelectionRangeProvider(), 'AbstractSma|rtSelect',
new Range(1, 9, 1, 15),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 9, 1, 14),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac-Sma|rt-elect',
new Range(1, 9, 1, 15),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 9, 1, 14),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt_elect',
new Range(1, 9, 1, 15),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 9, 1, 14),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt-elect',
new Range(1, 9, 1, 15),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 9, 1, 14),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rtSelect',
new Range(1, 9, 1, 15),
new Range(1, 1, 1, 21),
new Range(1, 1, 1, 21),
new Range(1, 9, 1, 14),
new Range(1, 1, 1, 20),
new Range(1, 1, 1, 20),
);
});
@@ -321,4 +323,49 @@ suite('SmartSelect', () => {
reg.dispose();
});
test('Expand selection in words with underscores is inconsistent #90589', async function () {
await assertRanges(new WordSelectionRangeProvider(), 'Hel|lo_World',
new Range(1, 1, 1, 6),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello_Wo|rld',
new Range(1, 7, 1, 12),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello|_World',
new Range(1, 1, 1, 6),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello_|World',
new Range(1, 7, 1, 12),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello|-World',
new Range(1, 1, 1, 6),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello-|World',
new Range(1, 7, 1, 12),
new Range(1, 1, 1, 12),
new Range(1, 1, 1, 12),
);
await assertRanges(new WordSelectionRangeProvider(), 'Hello|World',
new Range(1, 6, 1, 11),
new Range(1, 1, 1, 11),
new Range(1, 1, 1, 11),
);
});
});

View File

@@ -40,7 +40,7 @@ export class WordSelectionRangeProvider implements SelectionRangeProvider {
// LEFT anchor (start)
for (; start >= 0; start--) {
let ch = word.charCodeAt(start);
if (ch === CharCode.Underline || ch === CharCode.Dash) {
if ((start !== offset) && (ch === CharCode.Underline || ch === CharCode.Dash)) {
// foo-bar OR foo_bar
break;
} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {

View File

@@ -11,6 +11,8 @@ import { Selection } from 'vs/editor/common/core/selection';
import { deserializePipePositions, serializePipePositions, testRepeatedActionAndExtractPositions } from 'vs/editor/contrib/wordOperations/test/wordTestUtils';
import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight, CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect } from 'vs/editor/contrib/wordOperations/wordOperations';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { Handler } from 'vs/editor/common/editorCommon';
import { Cursor } from 'vs/editor/common/controller/cursor';
suite('WordOperations', () => {
@@ -193,6 +195,32 @@ suite('WordOperations', () => {
assert.deepEqual(actual, EXPECTED);
});
test('issue #51275 - cursorWordStartLeft does not push undo/redo stack element', () => {
function cursorCommand(cursor: Cursor, command: string, extraData?: any, overwriteSource?: string) {
cursor.trigger(overwriteSource || 'tests', command, extraData);
}
function type(cursor: Cursor, text: string) {
for (let i = 0; i < text.length; i++) {
cursorCommand(cursor, Handler.Type, { text: text.charAt(i) }, 'keyboard');
}
}
withTestCodeEditor('', {}, (editor, cursor) => {
type(cursor, 'foo bar baz');
assert.equal(editor.getValue(), 'foo bar baz');
cursorWordStartLeft(editor);
cursorWordStartLeft(editor);
type(cursor, 'q');
assert.equal(editor.getValue(), 'foo qbar baz');
cursorCommand(cursor, Handler.Undo, {});
assert.equal(editor.getValue(), 'foo bar baz');
});
});
test('cursorWordEndLeft', () => {
const EXPECTED = ['| /*| Just| some| more| text| a|+=| 3| +|5|-|3| +| 7| */| '].join('\n');
const [text,] = deserializePipePositions(EXPECTED);

View File

@@ -52,6 +52,7 @@ export abstract class MoveWordCommand extends EditorCommand {
return this._moveTo(sel, outPosition, this._inSelectionMode);
});
model.pushStackElement();
editor._getCursors().setStates('moveWordCommand', CursorChangeReason.NotSet, result.map(r => CursorState.fromModelSelection(r)));
if (result.length === 1) {
const pos = new Position(result[0].positionLineNumber, result[0].positionColumn);

View File

@@ -6,6 +6,7 @@
import 'vs/css!./inspectTokens';
import { CharCode } from 'vs/base/common/charCode';
import { Color } from 'vs/base/common/color';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import { escape } from 'vs/base/common/strings';
import { ContentWidgetPositionPreference, IActiveCodeEditor, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
@@ -48,6 +49,7 @@ class InspectTokensController extends Disposable implements IEditorContribution
this._register(this._editor.onDidChangeModel((e) => this.stop()));
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
this._register(TokenizationRegistry.onDidChange((e) => this.stop()));
this._register(this._editor.onKeyUp((e) => e.keyCode === KeyCode.Escape && this.stop()));
}
public dispose(): void {
@@ -222,13 +224,13 @@ class InspectTokensWidget extends Disposable implements IContentWidget {
result += `<hr class="tokens-inspect-separator" style="clear:both"/>`;
let metadata = this._decodeMetadata(data.tokens2[(token2Index << 1) + 1]);
let metadata = (token2Index << 1) + 1 < data.tokens2.length ? this._decodeMetadata(data.tokens2[(token2Index << 1) + 1]) : null;
result += `<table class="tm-metadata-table"><tbody>`;
result += `<tr><td class="tm-metadata-key">language</td><td class="tm-metadata-value">${escape(metadata.languageIdentifier.language)}</td>`;
result += `<tr><td class="tm-metadata-key">token type</td><td class="tm-metadata-value">${this._tokenTypeToString(metadata.tokenType)}</td>`;
result += `<tr><td class="tm-metadata-key">font style</td><td class="tm-metadata-value">${this._fontStyleToString(metadata.fontStyle)}</td>`;
result += `<tr><td class="tm-metadata-key">foreground</td><td class="tm-metadata-value">${Color.Format.CSS.formatHex(metadata.foreground)}</td>`;
result += `<tr><td class="tm-metadata-key">background</td><td class="tm-metadata-value">${Color.Format.CSS.formatHex(metadata.background)}</td>`;
result += `<tr><td class="tm-metadata-key">language</td><td class="tm-metadata-value">${metadata ? escape(metadata.languageIdentifier.language) : '-?-'}</td>`;
result += `<tr><td class="tm-metadata-key">token type</td><td class="tm-metadata-value">${metadata ? this._tokenTypeToString(metadata.tokenType) : '-?-'}</td>`;
result += `<tr><td class="tm-metadata-key">font style</td><td class="tm-metadata-value">${metadata ? this._fontStyleToString(metadata.fontStyle) : '-?-'}</td>`;
result += `<tr><td class="tm-metadata-key">foreground</td><td class="tm-metadata-value">${metadata ? Color.Format.CSS.formatHex(metadata.foreground) : '-?-'}</td>`;
result += `<tr><td class="tm-metadata-key">background</td><td class="tm-metadata-value">${metadata ? Color.Format.CSS.formatHex(metadata.background) : '-?-'}</td>`;
result += `</tbody></table>`;
result += `<hr class="tokens-inspect-separator"/>`;

View File

@@ -124,6 +124,13 @@ export interface IGlobalEditorOptions {
* Defaults to 20000.
*/
maxTokenizationLineLength?: number;
/**
* Theme to be used for rendering.
* The current out-of-the-box available themes are: 'vs' (default), 'vs-dark', 'hc-black'.
* You can create custom themes via `monaco.editor.defineTheme`.
* To switch a theme, use `monaco.editor.setTheme`
*/
theme?: string;
}
/**
@@ -334,6 +341,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
private readonly _contextViewService: ContextViewService;
private readonly _configurationService: IConfigurationService;
private readonly _standaloneThemeService: IStandaloneThemeService;
private _ownsModel: boolean;
constructor(
@@ -363,6 +371,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
this._contextViewService = <ContextViewService>contextViewService;
this._configurationService = configurationService;
this._standaloneThemeService = themeService;
this._register(toDispose);
this._register(themeDomRegistration);
@@ -391,6 +400,9 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
public updateOptions(newOptions: IEditorOptions & IGlobalEditorOptions): void {
applyConfigurationValues(this._configurationService, newOptions, false);
if (typeof newOptions.theme === 'string') {
this._standaloneThemeService.setTheme(newOptions.theme);
}
super.updateOptions(newOptions);
}
@@ -414,6 +426,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
private readonly _contextViewService: ContextViewService;
private readonly _configurationService: IConfigurationService;
private readonly _standaloneThemeService: IStandaloneThemeService;
constructor(
domElement: HTMLElement,
@@ -443,6 +456,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
this._contextViewService = <ContextViewService>contextViewService;
this._configurationService = configurationService;
this._standaloneThemeService = themeService;
this._register(toDispose);
this._register(themeDomRegistration);
@@ -454,8 +468,11 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
super.dispose();
}
public updateOptions(newOptions: IDiffEditorOptions): void {
public updateOptions(newOptions: IDiffEditorOptions & IGlobalEditorOptions): void {
applyConfigurationValues(this._configurationService, newOptions, true);
if (typeof newOptions.theme === 'string') {
this._standaloneThemeService.setTheme(newOptions.theme);
}
super.updateOptions(newOptions);
}

View File

@@ -78,7 +78,7 @@ suite('MinimapCharRenderer', () => {
imageData.data[4 * i + 2] = background.b;
imageData.data[4 * i + 3] = 255;
}
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 2, false);
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 2, false, false);
let actual: number[] = [];
for (let i = 0; i < imageData.data.length; i++) {
@@ -108,7 +108,7 @@ suite('MinimapCharRenderer', () => {
imageData.data[4 * i + 3] = 255;
}
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 1, false);
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 1, false, false);
let actual: number[] = [];
for (let i = 0; i < imageData.data.length; i++) {

View File

@@ -17,6 +17,7 @@ interface IEditorLayoutProviderOpts {
readonly showLineNumbers: boolean;
readonly lineNumbersMinChars: number;
readonly lineNumbersDigitCount: number;
maxLineNumber?: number;
readonly lineDecorationsWidth: number;
@@ -32,6 +33,7 @@ interface IEditorLayoutProviderOpts {
readonly minimapSide: 'left' | 'right';
readonly minimapRenderCharacters: boolean;
readonly minimapMaxColumn: number;
minimapMode?: 'actual' | 'cover' | 'contain';
readonly pixelRatio: number;
}
@@ -45,6 +47,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
options._write(EditorOption.folding, false);
const minimapOptions: EditorMinimapOptions = {
enabled: input.minimap,
mode: input.minimapMode || 'actual',
side: input.minimapSide,
renderCharacters: input.minimapRenderCharacters,
maxColumn: input.minimapMaxColumn,
@@ -77,6 +80,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
outerWidth: input.outerWidth,
outerHeight: input.outerHeight,
lineHeight: input.lineHeight,
maxLineNumber: input.maxLineNumber || Math.pow(10, input.lineNumbersDigitCount) - 1,
lineNumbersDigitCount: input.lineNumbersDigitCount,
typicalHalfwidthCharacterWidth: input.typicalHalfwidthCharacterWidth,
maxDigitWidth: input.maxDigitWidth,
@@ -125,6 +129,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
viewportColumn: 98,
verticalScrollbarWidth: 0,
@@ -179,6 +191,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
viewportColumn: 97,
verticalScrollbarWidth: 11,
@@ -233,6 +253,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
viewportColumn: 88,
verticalScrollbarWidth: 0,
@@ -287,6 +315,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 88,
verticalScrollbarWidth: 0,
@@ -341,6 +377,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 88,
verticalScrollbarWidth: 0,
@@ -395,6 +439,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 83,
verticalScrollbarWidth: 0,
@@ -449,6 +501,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 83,
verticalScrollbarWidth: 0,
@@ -503,6 +563,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 82,
verticalScrollbarWidth: 0,
@@ -557,6 +625,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 171,
verticalScrollbarWidth: 0,
@@ -611,6 +687,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
viewportColumn: 169,
verticalScrollbarWidth: 0,
@@ -665,6 +749,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 2,
minimapCanvasInnerWidth: 97,
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
viewportColumn: 89,
verticalScrollbarWidth: 0,
@@ -719,6 +811,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 2,
minimapLineHeight: 4,
minimapCanvasInnerWidth: 194,
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
viewportColumn: 89,
verticalScrollbarWidth: 0,
@@ -773,6 +873,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 2,
minimapLineHeight: 4,
minimapCanvasInnerWidth: 220,
minimapCanvasInnerHeight: 3200,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
viewportColumn: 93,
verticalScrollbarWidth: 0,
@@ -827,6 +935,270 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.Text,
minimapLeft: 0,
minimapWidth: 55,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 2,
minimapLineHeight: 4,
minimapCanvasInnerWidth: 220,
minimapCanvasInnerHeight: 3200,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
viewportColumn: 93,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
overviewRuler: {
top: 0,
width: 0,
height: 800,
right: 0
}
});
});
test('EditorLayoutProvider 11 - minimap mode cover without sampling', () => {
doTest({
outerWidth: 1000,
outerHeight: 800,
showGlyphMargin: false,
lineHeight: 16,
showLineNumbers: false,
lineNumbersMinChars: 0,
lineNumbersDigitCount: 3,
maxLineNumber: 120,
lineDecorationsWidth: 10,
typicalHalfwidthCharacterWidth: 10,
maxDigitWidth: 10,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
scrollbarArrowSize: 0,
verticalScrollbarHasArrows: false,
minimap: true,
minimapSide: 'right',
minimapRenderCharacters: true,
minimapMaxColumn: 150,
minimapMode: 'cover',
pixelRatio: 2,
}, {
width: 1000,
height: 800,
glyphMarginLeft: 0,
glyphMarginWidth: 0,
lineNumbersLeft: 0,
lineNumbersWidth: 0,
decorationsLeft: 0,
decorationsWidth: 10,
contentLeft: 10,
contentWidth: 893,
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
minimapHeightIsEditorHeight: true,
minimapIsSampling: false,
minimapScale: 3,
minimapLineHeight: 13,
minimapCanvasInnerWidth: 291,
minimapCanvasInnerHeight: 1560,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
viewportColumn: 89,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
overviewRuler: {
top: 0,
width: 0,
height: 800,
right: 0
}
});
});
test('EditorLayoutProvider 12 - minimap mode cover with sampling', () => {
doTest({
outerWidth: 1000,
outerHeight: 800,
showGlyphMargin: false,
lineHeight: 16,
showLineNumbers: false,
lineNumbersMinChars: 0,
lineNumbersDigitCount: 4,
maxLineNumber: 2500,
lineDecorationsWidth: 10,
typicalHalfwidthCharacterWidth: 10,
maxDigitWidth: 10,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
scrollbarArrowSize: 0,
verticalScrollbarHasArrows: false,
minimap: true,
minimapSide: 'right',
minimapRenderCharacters: true,
minimapMaxColumn: 150,
minimapMode: 'cover',
pixelRatio: 2,
}, {
width: 1000,
height: 800,
glyphMarginLeft: 0,
glyphMarginWidth: 0,
lineNumbersLeft: 0,
lineNumbersWidth: 0,
decorationsLeft: 0,
decorationsWidth: 10,
contentLeft: 10,
contentWidth: 935,
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
minimapHeightIsEditorHeight: true,
minimapIsSampling: true,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 110,
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
viewportColumn: 93,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
overviewRuler: {
top: 0,
width: 0,
height: 800,
right: 0
}
});
});
test('EditorLayoutProvider 13 - minimap mode contain without sampling', () => {
doTest({
outerWidth: 1000,
outerHeight: 800,
showGlyphMargin: false,
lineHeight: 16,
showLineNumbers: false,
lineNumbersMinChars: 0,
lineNumbersDigitCount: 3,
maxLineNumber: 120,
lineDecorationsWidth: 10,
typicalHalfwidthCharacterWidth: 10,
maxDigitWidth: 10,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
scrollbarArrowSize: 0,
verticalScrollbarHasArrows: false,
minimap: true,
minimapSide: 'right',
minimapRenderCharacters: true,
minimapMaxColumn: 150,
minimapMode: 'contain',
pixelRatio: 2,
}, {
width: 1000,
height: 800,
glyphMarginLeft: 0,
glyphMarginWidth: 0,
lineNumbersLeft: 0,
lineNumbersWidth: 0,
decorationsLeft: 0,
decorationsWidth: 10,
contentLeft: 10,
contentWidth: 893,
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 2,
minimapLineHeight: 4,
minimapCanvasInnerWidth: 194,
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
viewportColumn: 89,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
overviewRuler: {
top: 0,
width: 0,
height: 800,
right: 0
}
});
});
test('EditorLayoutProvider 14 - minimap mode contain with sampling', () => {
doTest({
outerWidth: 1000,
outerHeight: 800,
showGlyphMargin: false,
lineHeight: 16,
showLineNumbers: false,
lineNumbersMinChars: 0,
lineNumbersDigitCount: 4,
maxLineNumber: 2500,
lineDecorationsWidth: 10,
typicalHalfwidthCharacterWidth: 10,
maxDigitWidth: 10,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
scrollbarArrowSize: 0,
verticalScrollbarHasArrows: false,
minimap: true,
minimapSide: 'right',
minimapRenderCharacters: true,
minimapMaxColumn: 150,
minimapMode: 'contain',
pixelRatio: 2,
}, {
width: 1000,
height: 800,
glyphMarginLeft: 0,
glyphMarginWidth: 0,
lineNumbersLeft: 0,
lineNumbersWidth: 0,
decorationsLeft: 0,
decorationsWidth: 10,
contentLeft: 10,
contentWidth: 935,
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
minimapHeightIsEditorHeight: true,
minimapIsSampling: true,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 110,
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
viewportColumn: 93,
verticalScrollbarWidth: 0,
@@ -881,6 +1253,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
renderMinimap: RenderMinimap.Text,
minimapLeft: 1096,
minimapWidth: 91,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 2,
minimapLineHeight: 4,
minimapCanvasInnerWidth: 182,
minimapCanvasInnerHeight: 844,
minimapCanvasOuterWidth: 91,
minimapCanvasOuterHeight: 422,
viewportColumn: 83,
verticalScrollbarWidth: 14,