Merge from vscode 91e99652cd5fcfc072387c64e151b435e39e8dcf (#6962)

This commit is contained in:
Anthony Dresser
2019-08-26 15:58:42 -07:00
committed by GitHub
parent edf470c8fa
commit 507bae90b7
103 changed files with 1743 additions and 1543 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
renderer
};
const allowedSchemes = ['http', 'https', 'mailto'];
const allowedSchemes = ['http', 'https', 'mailto', 'data'];
if (markdown.isTrusted) {
allowedSchemes.push('command');
}
-7
View File
@@ -109,13 +109,6 @@ export class Dialog extends Disposable {
return;
}
if (this.modal) {
this._register(domEvent(this.modal, 'mousedown')(e => {
// Used to stop focusing of modal with mouse
EventHelper.stop(e, true);
}));
}
clearNode(this.buttonsContainer);
let focusedButton = 0;
+18 -93
View File
@@ -7,7 +7,7 @@ import 'vs/css!./gridview';
import { Orientation } from 'vs/base/browser/ui/sash/sash';
import { Disposable } from 'vs/base/common/lifecycle';
import { tail2 as tail, equals } from 'vs/base/common/arrays';
import { orthogonal, IView as IGridViewView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles, IViewSize, LayoutController, IGridViewOptions } from './gridview';
import { orthogonal, IView as IGridViewView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles, IViewSize, IGridViewOptions } from './gridview';
import { Event } from 'vs/base/common/event';
import { InvisibleSizing } from 'vs/base/browser/ui/splitview/splitview';
@@ -217,9 +217,17 @@ export class Grid<T extends IView = IView> extends Disposable {
private didLayout = false;
constructor(view: T, options: IGridOptions = {}) {
constructor(gridview: GridView, options?: IGridOptions);
constructor(view: T, options?: IGridOptions);
constructor(view: T | GridView, options: IGridOptions = {}) {
super();
this.gridview = new GridView(options);
if (view instanceof GridView) {
this.gridview = view;
this.gridview.getViewMap(this.views);
} else {
this.gridview = new GridView(options);
}
this._register(this.gridview);
this._register(this.gridview.onDidSashReset(this.onDidSashReset, this));
@@ -228,7 +236,9 @@ export class Grid<T extends IView = IView> extends Disposable {
? GridViewSizing.Invisible(options.firstViewVisibleCachedSize)
: 0;
this._addView(view, size, [0]);
if (!(view instanceof GridView)) {
this._addView(view, size, [0]);
}
}
style(styles: IGridStyles): void {
@@ -469,12 +479,6 @@ export interface IViewDeserializer<T extends ISerializableView> {
fromJSON(json: any): T;
}
interface InitialLayoutContext<T extends ISerializableView> {
width: number;
height: number;
root: GridBranchNode<T>;
}
export interface ISerializedLeafNode {
type: 'leaf';
data: any;
@@ -567,31 +571,9 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
throw new Error('Invalid JSON: \'height\' property must be a number.');
}
const orientation = json.orientation;
const width = json.width;
const height = json.height;
const box: Box = { top: 0, left: 0, width, height };
const gridview = GridView.deserialize(json, deserializer, options);
const result = new SerializableGrid<T>(gridview, options);
const root = SerializableGrid.deserializeNode(json.root, orientation, box, deserializer) as GridBranchNode<T>;
const firstLeaf = SerializableGrid.getFirstLeaf(root);
if (!firstLeaf) {
throw new Error('Invalid serialized state, first leaf not found');
}
const layoutController = new LayoutController(false);
options = { ...options, layoutController };
if (typeof firstLeaf.cachedVisibleSize === 'number') {
options = { ...options, firstViewVisibleCachedSize: firstLeaf.cachedVisibleSize };
}
const result = new SerializableGrid<T>(firstLeaf.view, options);
result.orientation = orientation;
result.restoreViews(firstLeaf.view, orientation, root);
result.initialLayoutContext = { width, height, root };
layoutController.isLayoutEnabled = true;
return result;
}
@@ -599,7 +581,7 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
* Useful information in order to proportionally restore view sizes
* upon the very first layout call.
*/
private initialLayoutContext: InitialLayoutContext<T> | undefined;
private initialLayoutContext: boolean = true;
serialize(): ISerializedGrid {
return {
@@ -614,65 +596,8 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
super.layout(width, height);
if (this.initialLayoutContext) {
const widthScale = width / this.initialLayoutContext.width;
const heightScale = height / this.initialLayoutContext.height;
this.restoreViewsSize([], this.initialLayoutContext.root, this.orientation, widthScale, heightScale);
this.initialLayoutContext = undefined;
this.gridview.trySet2x2();
}
}
/**
* Recursively restores views which were just deserialized.
*/
private restoreViews(referenceView: T, orientation: Orientation, node: GridNode<T>): void {
if (!isGridBranchNode(node)) {
return;
}
const direction = orientation === Orientation.VERTICAL ? Direction.Down : Direction.Right;
const firstLeaves = node.children.map(c => SerializableGrid.getFirstLeaf(c));
for (let i = 1; i < firstLeaves.length; i++) {
const node = firstLeaves[i];
const size: number | InvisibleSizing = typeof node.cachedVisibleSize === 'number'
? GridViewSizing.Invisible(node.cachedVisibleSize)
: (orientation === Orientation.VERTICAL ? node.box.height : node.box.width);
this.addView(node.view, size, referenceView, direction);
referenceView = node.view;
}
for (let i = 0; i < node.children.length; i++) {
this.restoreViews(firstLeaves[i].view, orthogonal(orientation), node.children[i]);
}
}
/**
* Recursively restores view sizes.
* This should be called only after the very first layout call.
*/
private restoreViewsSize(location: number[], node: GridNode<T>, orientation: Orientation, widthScale: number, heightScale: number): void {
if (!isGridBranchNode(node)) {
return;
}
const scale = orientation === Orientation.VERTICAL ? heightScale : widthScale;
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const childLocation = [...location, i];
if (i < node.children.length - 1) {
const size = orientation === Orientation.VERTICAL
? { height: Math.floor(child.box.height * scale) }
: { width: Math.floor(child.box.width * scale) };
this.gridview.resizeView(childLocation, size);
}
this.restoreViewsSize(childLocation, child, orthogonal(orientation), widthScale, heightScale);
this.initialLayoutContext = false;
}
}
}
+126 -5
View File
@@ -34,6 +34,36 @@ export interface IView {
setVisible?(visible: boolean): void;
}
export interface ISerializableView extends IView {
toJSON(): object;
}
export interface IViewDeserializer<T extends ISerializableView> {
fromJSON(json: any): T;
}
export interface ISerializedLeafNode {
type: 'leaf';
data: any;
size: number;
visible?: boolean;
}
export interface ISerializedBranchNode {
type: 'branch';
data: ISerializedNode[];
size: number;
}
export type ISerializedNode = ISerializedLeafNode | ISerializedBranchNode;
export interface ISerializedGridView {
root: ISerializedNode;
orientation: Orientation;
width: number;
height: number;
}
export function orthogonal(orientation: Orientation): Orientation {
return orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
}
@@ -179,18 +209,49 @@ class BranchNode implements ISplitView, IDisposable {
styles: IGridViewStyles,
readonly proportionalLayout: boolean,
size: number = 0,
orthogonalSize: number = 0
orthogonalSize: number = 0,
childDescriptors?: INodeDescriptor[]
) {
this._styles = styles;
this._size = size;
this._orthogonalSize = orthogonalSize;
this.element = $('.monaco-grid-branch-node');
this.splitview = new SplitView(this.element, { orientation, styles, proportionalLayout });
this.splitview.layout(size, orthogonalSize);
if (!childDescriptors) {
// Normal behavior, we have no children yet, just set up the splitview
this.splitview = new SplitView(this.element, { orientation, styles, proportionalLayout });
this.splitview.layout(size, orthogonalSize);
} else {
// Reconstruction behavior, we want to reconstruct a splitview
const descriptor = {
views: childDescriptors.map(childDescriptor => {
return {
view: childDescriptor.node,
size: childDescriptor.node.size,
visible: childDescriptor.node instanceof LeafNode && childDescriptor.visible !== undefined ? childDescriptor.visible : true
};
}),
size: this.orthogonalSize
};
const options = { proportionalLayout, orientation, styles };
this.children = childDescriptors.map(c => c.node);
this.splitview = new SplitView(this.element, { ...options, descriptor });
this.children.forEach((node, index) => {
// Set up orthogonal sashes for children
node.orthogonalStartSash = this.splitview.sashes[index - 1];
node.orthogonalEndSash = this.splitview.sashes[index];
});
}
const onDidSashReset = Event.map(this.splitview.onDidSashReset, i => [i]);
this.splitviewSashResetDisposable = onDidSashReset(this._onDidSashReset.fire, this._onDidSashReset);
const onDidChildrenSashReset = Event.any(...this.children.map((c, i) => Event.map(c.onDidSashReset, location => [i, ...location])));
this.childrenSashResetDisposable = onDidChildrenSashReset(this._onDidSashReset.fire, this._onDidSashReset);
}
style(styles: IGridViewStyles): void {
@@ -226,7 +287,7 @@ class BranchNode implements ISplitView, IDisposable {
}
}
addChild(node: Node, size: number | Sizing, index: number): void {
addChild(node: Node, size: number | Sizing, index: number, skipLayout?: boolean): void {
if (index < 0 || index > this.children.length) {
throw new Error('Invalid index');
}
@@ -484,9 +545,11 @@ class LeafNode implements ISplitView, IDisposable {
readonly view: IView,
readonly orientation: Orientation,
readonly layoutController: ILayoutController,
orthogonalSize: number
orthogonalSize: number,
size: number = 0
) {
this._orthogonalSize = orthogonalSize;
this._size = size;
this._onDidViewChange = Event.map(this.view.onDidChange, e => e && (this.orientation === Orientation.VERTICAL ? e.width : e.height));
this.onDidChange = Event.any(this._onDidViewChange, this._onDidSetLinkedNode.event, this._onDidLinkedWidthNodeChange.event, this._onDidLinkedHeightNodeChange.event);
@@ -577,6 +640,11 @@ class LeafNode implements ISplitView, IDisposable {
type Node = BranchNode | LeafNode;
export interface INodeDescriptor {
node: Node;
visible?: boolean;
}
function flipNode<T extends Node>(node: T, size: number, orthogonalSize: number): T {
if (node instanceof BranchNode) {
const result = new BranchNode(orthogonal(node.orientation), node.layoutController, node.styles, node.proportionalLayout, size, orthogonalSize);
@@ -680,6 +748,18 @@ export class GridView implements IDisposable {
this.root = new BranchNode(Orientation.VERTICAL, this.layoutController, this.styles, this.proportionalLayout);
}
getViewMap(map: Map<IView, HTMLElement>, node?: Node): void {
if (!node) {
node = this.root;
}
if (node instanceof BranchNode) {
node.children.forEach(child => this.getViewMap(map, child));
} else {
map.set(node.view, node.element);
}
}
style(styles: IGridViewStyles): void {
this.styles = styles;
this.root.style(styles);
@@ -953,6 +1033,47 @@ export class GridView implements IDisposable {
return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height });
}
static deserialize<T extends ISerializableView>(json: ISerializedGridView, deserializer: IViewDeserializer<T>, options: IGridViewOptions = {}): GridView {
if (typeof json.orientation !== 'number') {
throw new Error('Invalid JSON: \'orientation\' property must be a number.');
} else if (typeof json.width !== 'number') {
throw new Error('Invalid JSON: \'width\' property must be a number.');
} else if (typeof json.height !== 'number') {
throw new Error('Invalid JSON: \'height\' property must be a number.');
}
const orientation = json.orientation;
const height = json.height;
const result = new GridView(options);
result._deserialize(json.root as ISerializedBranchNode, orientation, deserializer, height);
return result;
}
private _deserialize(root: ISerializedBranchNode, orientation: Orientation, deserializer: IViewDeserializer<ISerializableView>, orthogonalSize: number): void {
this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize) as BranchNode;
}
private _deserializeNode(node: ISerializedNode, orientation: Orientation, deserializer: IViewDeserializer<ISerializableView>, orthogonalSize: number): Node {
let result: Node;
if (node.type === 'branch') {
const serializedChildren = node.data as ISerializedNode[];
const children = serializedChildren.map(serializedChild => {
return {
node: this._deserializeNode(serializedChild, orthogonal(orientation), deserializer, node.size),
visible: (serializedChild as { visible?: boolean }).visible
} as INodeDescriptor;
});
result = new BranchNode(orientation, this.layoutController, this.styles, this.proportionalLayout, node.size, orthogonalSize, children);
} else {
result = new LeafNode(deserializer.fromJSON(node.data), orientation, this.layoutController, orthogonalSize, node.size);
}
return result;
}
private _getViews(node: Node, orientation: Orientation, box: Box, cachedVisibleSize?: number): GridNode {
if (node instanceof LeafNode) {
return { view: node.view, box, cachedVisibleSize };
@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./octicons/octicons';
import 'vs/css!./octicons/octicons2';
import 'vs/css!./octicons/octicons-main';
import 'vs/css!./octicons/octicons-animations';
import { escape } from 'vs/base/common/strings';
@@ -30,4 +32,4 @@ export class OcticonLabel {
set title(title: string) {
this._container.title = title;
}
}
}
+17 -14
View File
@@ -1,7 +1,7 @@
@font-face {
font-family: "octicons";
src: url("./octicons.ttf?1b0f2a9535896866c74dd24eedeb4374") format("truetype"),
url("./octicons.svg?1b0f2a9535896866c74dd24eedeb4374#octicons") format("svg");
src: url("./octicons.ttf?759e9adce5213a11e27cd79af7448e2e") format("truetype"),
url("./octicons.svg?759e9adce5213a11e27cd79af7448e2e#octicons") format("svg");
}
.octicon, .mega-octicon {
@@ -169,7 +169,7 @@ url("./octicons.svg?1b0f2a9535896866c74dd24eedeb4374#octicons") format("svg");
.octicon-person-outline:before { content: "\f018" }
.octicon-pin:before { content: "\f041" }
.octicon-plug:before { content: "\f0d4" }
.octicon-plus-small:before { content: "\f28a" }
.octicon-plus-small:before { content: "\f05d" }
.octicon-plus:before { content: "\f05d" }
.octicon-primitive-dot:before { content: "\f052" }
.octicon-primitive-square:before { content: "\f053" }
@@ -233,16 +233,19 @@ url("./octicons.svg?1b0f2a9535896866c74dd24eedeb4374#octicons") format("svg");
.octicon-watch:before { content: "\f0e0" }
.octicon-x:before { content: "\f081" }
.octicon-zap:before { content: "\26a1" }
.octicon-error:before { content: "\26b1" }
.octicon-eye-closed:before { content: "\26b0" }
.octicon-fold-down:before { content: "\26a4" }
.octicon-fold-up:before { content: "\26a5" }
.octicon-github-action:before { content: "\26a6" }
.octicon-info-outline:before { content: "\26a7" }
.octicon-play:before { content: "\26a8" }
.octicon-remote:before { content: "\26a9" }
.octicon-request-changes:before { content: "\26aa" }
.octicon-smiley-outline:before { content: "\f27d" }
.octicon-warning:before { content: "\f02d" }
.octicon-controls:before { content: "\26ad" }
.octicon-event:before { content: "\26ae" }
.octicon-record-keys:before { content: "\26af" }
.octicon-archive:before { content: "\f101" }
.octicon-arrow-both:before { content: "\f102" }
.octicon-error:before { content: "\f103" }
.octicon-eye-closed:before { content: "\f104" }
.octicon-fold-down:before { content: "\f105" }
.octicon-fold-up:before { content: "\f106" }
.octicon-github-action:before { content: "\f107" }
.octicon-info-outline:before { content: "\f108" }
.octicon-play:before { content: "\f109" }
.octicon-remote:before { content: "\f10a" }
.octicon-request-changes:before { content: "\f10b" }
.octicon-smiley-outline:before { content: "\f10c" }
.octicon-warning:before { content: "\f10d" }
@@ -167,10 +167,10 @@
unicode="&#xF09A;"
horiz-adv-x="750" d=" M687.5 507.5H62.5C28.125 507.5 0 479.375 0 445V195C0 160.625 28.125 132.5 62.5 132.5H687.5C721.875 132.5 750 160.625 750 195V445C750 479.375 721.875 507.5 687.5 507.5zM250 257.5H125V382.5H250V257.5zM437.5 257.5H312.5V382.5H437.5V257.5zM625 257.5H500V382.5H625V257.5z" />
<glyph glyph-name="error"
unicode="&#xF103;"
unicode="&#x26B1;"
horiz-adv-x="1000" d=" M500 757.5C258.365625 757.5 62.5 561.6343750000001 62.5 320C62.5 78.3625000000001 258.365625 -117.5 500 -117.5C741.6374999999999 -117.5 937.5 78.3625000000001 937.5 320C937.5 561.6343750000001 741.6374999999999 757.5 500 757.5zM762.5 145L675 57.5L500 232.5L325 57.5L237.5 145L412.5 322.355625L237.5 495L325 582.5L500 407.5L675 582.5L762.5 495L587.5 322.355625L762.5 145z" />
<glyph glyph-name="eye-closed"
unicode="&#xF104;"
unicode="&#x26B0;"
horiz-adv-x="1142.857142857143" d=" M1057.142857142857 812.8571428571429C1042.857142857143 827.1428571428571 1021.4285714285716 827.1428571428571 1007.1428571428572 812.8571428571429L857.1428571428573 655.7142857142857C778.5714285714288 712.8571428571429 685.7142857142858 748.5714285714286 578.5714285714287 748.5714285714286C214.2857142857144 755.7142857142857 1e-13 327.1428571428571 1e-13 327.1428571428571S85.7142857142858 162.8571428571429 235.7142857142859 34.2857142857142L85.7142857142858 -115.7142857142857C71.4285714285716 -130 71.4285714285716 -151.4285714285714 85.7142857142858 -165.7142857142857S121.4285714285716 -179.9999999999999 135.7142857142858 -165.7142857142857L1057.1428571428573 755.7142857142858C1071.4285714285716 770.0000000000001 1071.4285714285716 798.5714285714287 1057.1428571428573 812.857142857143zM642.8571428571429 448.5714285714286C621.4285714285714 462.8571428571429 600 470 571.4285714285714 470C492.8571428571429 470 428.5714285714286 405.7142857142857 428.5714285714286 327.1428571428572C428.5714285714286 298.5714285714286 435.7142857142857 277.1428571428571 450 255.7142857142858L350.0000000000001 148.5714285714287C307.1428571428572 198.5714285714286 285.7142857142857 255.7142857142858 285.7142857142857 327.1428571428572C285.7142857142857 484.2857142857144 414.2857142857143 612.8571428571429 571.4285714285714 612.8571428571429C635.7142857142858 612.8571428571429 700.0000000000001 591.4285714285716 750 548.5714285714287z M992.8571428571428 541.4285714285714L850 398.5714285714286C857.1428571428571 377.1428571428571 857.1428571428571 348.5714285714285 857.1428571428571 327.1428571428571C857.1428571428571 169.9999999999999 728.5714285714286 41.4285714285713 571.4285714285714 41.4285714285713C542.8571428571429 41.4285714285713 521.4285714285714 41.4285714285713 500 48.5714285714286L385.7142857142857 -65.7142857142858C442.8571428571429 -94.2857142857143 507.1428571428572 -108.5714285714285 578.5714285714287 -108.5714285714285C928.5714285714286 -108.5714285714285 1142.857142857143 320 1142.857142857143 320C1100 405.7142857142857 1050 477.1428571428572 992.8571428571428 541.4285714285714z" />
<glyph glyph-name="eye"
unicode="&#xF04E;"
@@ -209,10 +209,10 @@
unicode="&#xF0D2;"
horiz-adv-x="750" d=" M315.625 800.625C366.25 665 341.25 589.375 283.125 531.25C221.875 465.625 123.75 416.875 56.25 321.25C-34.375 193.1249999999999 -50 -86.8750000000001 276.875 -160C139.375 -87.5 110 122.5 258.125 253.125C220 126.25 291.25 45 379.375 74.375C466.25 103.7500000000001 523.1250000000001 41.2500000000001 521.25 -30C520 -78.7499999999999 501.8749999999999 -120 450.625 -143.125C664.3749999999999 -106.25 749.375 70.625 749.375 204.3749999999999C749.375 381.8749999999999 591.25 405.625 671.25 555C576.25 546.875 544.375 484.3749999999999 553.125 383.125C558.75 315.625 489.375 270.6249999999999 436.875 300C395 325.625 395.625 374.375 433.125 411.25C511.25 488.125 542.5 666.875 315.625 800L314.375 801.25L315.625 800.625z" />
<glyph glyph-name="fold-down"
unicode="&#xF105;"
unicode="&#x26A4;"
horiz-adv-x="875" d=" M250 132.5L437.5 -55L625 132.5H500V507.5H375V132.5H250zM0 132.5C0 98.125 28.125 70 62.5 70H218.75L156.25 132.5H93.75L218.75 257.5H312.5V320H218.75L93.75 445H312.5V507.5H62.5C28.125 507.5 0 479.375 0 445L156.25 288.75L0 132.5zM656.25 257.5H562.5V320H656.25L781.25 445H562.5V507.5H812.5C846.875 507.5 875 479.375 875 445L718.75 288.75L875 132.5C875 98.125 846.875 70 812.5 70H656.25L718.75 132.5H781.25L656.25 257.5z" />
<glyph glyph-name="fold-up"
unicode="&#xF106;"
unicode="&#x26A5;"
horiz-adv-x="875" d=" M625 445L437.5 632.5L250 445H375V70H500V445H625zM875 445C875 479.375 846.875 507.5 812.5 507.5H656.25L718.75 445H781.25L656.25 320H562.5V257.5H656.25L781.25 132.5H562.5V70H812.5C846.875 70 875 98.125 875 132.5L718.75 288.75L875 445zM218.75 320H312.5V257.5H218.75L93.75 132.5H312.5V70H62.5C28.125 70 0 98.125 0 132.5L156.25 288.75L0 445C0 479.375 28.125 507.5 62.5 507.5H218.75L156.25 445H93.75L218.75 320z" />
<glyph glyph-name="fold"
unicode="&#xF0CC;"
@@ -245,7 +245,7 @@
unicode="&#xF009;"
horiz-adv-x="750" d=" M687.5 115V507.5C685.625 556.25 666.25 599.375 628.75 636.25C591.25 673.125 548.75 693.125 500 695H437.5V820L250 632.5L437.5 445V570H500C516.875 568.75 530 563.125 543.125 550.625C556.25 538.125 561.875 524.375 562.5 507.5V114.9999999999999A124.56250000000001 124.56250000000001 0 0 1 625 -117.5A124.56250000000001 124.56250000000001 0 0 1 687.5 115zM625 -67.5C583.75 -67.5 550 -33.1249999999999 550 7.5C550 48.125 584.3750000000001 82.5 625 82.5C665.625 82.5 700 48.1249999999999 700 7.5C700 -33.125 665.6249999999999 -67.5 625 -67.5zM250 632.5C250 701.875 194.375 757.5 125 757.5A124.56250000000001 124.56250000000001 0 0 1 62.5 525V114.9999999999999A124.56250000000001 124.56250000000001 0 0 1 125 -117.5A124.56250000000001 124.56250000000001 0 0 1 187.5 115V525C224.375 546.25 250 586.25 250 632.5zM200 7.5C200 -33.75 165.625 -67.5 125 -67.5C84.375 -67.5 50 -33.1249999999999 50 7.5C50 48.125 84.375 82.5 125 82.5C165.625 82.5 200 48.1249999999999 200 7.5zM125 557.5C83.75 557.5 50 591.875 50 632.5C50 673.125 84.375 707.5 125 707.5C165.625 707.5 200 673.125 200 632.5C200 591.875 165.625 557.5 125 557.5z" />
<glyph glyph-name="github-action"
unicode="&#xF107;"
unicode="&#x26A6;"
horiz-adv-x="1000" d=" M687.5 476.25C687.5 424.4733047033631 729.4733047033632 382.5 781.25 382.5C833.0266952966368 382.5 875 424.4733047033631 875 476.25C875 528.026695296637 833.0266952966368 570 781.25 570C729.4733047033632 570 687.5 528.026695296637 687.5 476.25z M937.5 695H562.5C562.5 732.5 537.5 757.5 500 757.5S437.5 732.5 437.5 695H62.5C31.25 695 0 663.75 0 632.5V7.5C0 -23.75 31.25 -55 62.5 -55H437.5C437.5 -92.5 462.5 -117.5 500 -117.5S562.5 -92.5 562.5 -55H937.5C968.75 -55 1000 -23.75 1000 7.5V632.5C1000 663.75 968.75 695 937.5 695zM937.5 7.5H62.5V632.5H937.5z" />
<glyph glyph-name="globe"
unicode="&#xF0B6;"
@@ -275,7 +275,7 @@
unicode="&#xF0CF;"
horiz-adv-x="875" d=" M875 257.5L804.3750000000001 703.75C799.3750000000001 733.75 773.1250000000001 757.5 741.8750000000001 757.5H133.125C101.875 757.5 75.625 733.75 70.625 703.75L0 257.5V-55C0 -89.375 28.125 -117.5 62.5 -117.5H812.5C846.875 -117.5 875 -89.375 875 -55V257.5zM670 223.125L642.5000000000001 167.4999999999999C631.8750000000001 146.2499999999999 610.0000000000001 132.4999999999999 585.6250000000001 132.4999999999999H288.125C264.375 132.4999999999999 243.1250000000001 146.2499999999999 232.5 166.8749999999999L205 223.7499999999999C194.375 244.375 172.5 258.125 149.375 258.125H62.5L125 695.625H750L812.5 258.125H726.2500000000001C701.875 258.125 680.625 244.375 669.375 223.7499999999999L670 223.125z" />
<glyph glyph-name="info-outline"
unicode="&#xF108;"
unicode="&#x26A7;"
horiz-adv-x="875" d=" M393.75 464.37625C381.875 476.25125 376.25 490.62625 376.25 508.12625C376.25 525.62625 381.875 540.62625 393.75 551.87625C405.625 563.12625 420 569.37625 437.5 569.37625C455 569.37625 470 563.75125 481.25 551.87625C492.5 540.00125 498.75 525.62625 498.75 508.12625C498.75 490.62625 493.125 475.62625 481.25 464.37625C469.375 453.12625 455 445.62625 437.5 445.62625C420 445.62625 405 452.50125 393.75 464.37625zM500 320.6268750000001C498.75 336.2518750000001 493.125 350.626875 480.625 363.751875C468.125 375.6268750000001 454.375 382.5012500000001 437.5 383.1268750000001H375C358.125 381.876875 345 375.0012500000001 331.875 363.751875C319.375 351.2512500000001 313.125 336.2518750000001 312.5 320.6268750000001H375V133.125C376.25 116.25 381.875 101.875 394.375 90C406.875 77.5 420.625 70.625 437.5 70.625H500C516.875 70.625 530 77.5 543.125 90C555.625 101.875 561.875 116.25 562.5 133.125H500V321.2518750000001V320.6268750000001zM437.5 676.25125C241.25 676.25125 81.25 517.50125 81.25 321.25125C81.25 125 241.25 -35 437.5 -35C633.75 -35 793.75 124.375 793.75 321.25125C793.75 518.12625 633.75 676.87625 437.5 676.87625V676.25125zM437.5 758.75125C678.75 758.75125 875 562.50125 875 321.25125C875 80 678.75 -116.25 437.5 -116.25C196.25 -116.25 0 78.75 0 321.25125C0 563.75125 196.25 758.75125 437.5 758.75125z" />
<glyph glyph-name="info"
unicode="&#xF059;"
@@ -398,7 +398,7 @@
unicode="&#xF041;"
horiz-adv-x="1000" d=" M625 745V695L656.25 632.5L375 445H137.5C110 445 95.625 411.875 116.25 391.25L312.5 195L62.5 -117.5L375 132.5L571.25 -63.75A31.25 31.25 0 0 1 625 -42.5V195L812.5 476.25L875 445H925C952.5 445 966.875 478.125 946.25 498.75L678.75 766.25A31.25 31.25 0 0 1 625 745z" />
<glyph glyph-name="play"
unicode="&#xF109;"
unicode="&#x26A8;"
horiz-adv-x="875" d=" M875 320A437.49999999999994 437.49999999999994 0 1 0 0 320A437.49999999999994 437.49999999999994 0 0 0 875 320zM361.0625 102.375L648.5 294A31.25 31.25 0 0 1 648.5 346L361.0625 537.625A31.25 31.25 0 0 1 312.5 511.625V128.3750000000001A31.25 31.25 0 0 1 361.0625 102.375z" />
<glyph glyph-name="plug"
unicode="&#xF0D4;"
@@ -428,7 +428,7 @@
unicode="&#xF030;"
horiz-adv-x="1000" d=" M299.375 438.125C315 453.75 315 480 299.375 495.625C279.375 516.25 269.3750000000001 543.125 269.3750000000001 570C269.3750000000001 596.875 279.3750000000001 623.75 299.3750000000001 644.375C315.0000000000001 660.625 315.0000000000001 686.25 299.3750000000001 701.875A38.3125 38.3125 0 0 1 271.2500000000001 713.75C261.2500000000001 713.75 250.6250000000001 710 243.1250000000001 701.875C207.5000000000001 665.625 190 617.5 190 570C190 522.5 208.125 474.375 243.1250000000001 438.1250000000001C258.7500000000001 422.5000000000001 284.3750000000001 422.5000000000001 299.3750000000001 438.1250000000001zM145.625 787.5A40.6875 40.6875 0 0 1 88.125 787.5C30 727.5 0.625 648.75 0.625 570.625C0.625 491.875 30 413.125 88.125 353.125C103.75 336.875 129.375 336.875 145 353.125S160.625 395.625 145 411.875C102.5 455.6249999999999 81.25 513.125 81.25 570.625C81.25 628.1249999999999 102.5 685.6249999999999 145 729.3749999999999A41.25 41.25 0 0 1 145.625 787.4999999999999zM501.25 468.7500000000001A101.25 101.25 0 1 1 400 570C399.3750000000001 514.375 445 468.75 501.25 468.75zM911.875 786.875A39.25 39.25 0 0 1 855 786.875C839.375 770.625 839.375 744.375 855 728.125C897.5 684.375 918.75 626.875 918.75 569.375C918.75 511.875 897.5 455 855 410.625C839.375 394.375 839.375 368.1250000000001 855 351.875A40.6875 40.6875 0 0 1 912.5 351.875C970.625 411.875 1000 490.625 1000 569.375A315.5 315.5 0 0 1 911.875 786.875zM501.25 387.5C475.6249999999999 387.5 449.375 393.75 426.25 406.25L229.375 -116.8749999999999H322.5L376.25 -54.3749999999999H626.25L678.75 -116.8749999999999H771.875L575.625 406.25C551.875 393.75 526.8750000000001 387.5 501.2500000000001 387.5zM500.625 357.5L563.75 132.5H438.75L500.625 357.5zM376.25 8.125L438.75 70.625H563.75L626.25 8.125H376.25zM700.625 701.875C685 686.25 685 660 700.625 644.375C720.6250000000001 623.75 730.6250000000001 596.875 730.6250000000001 570C730.6250000000001 543.125 720.6250000000001 516.25 700.625 495.6250000000001C685 479.3750000000001 685 453.7500000000001 700.625 438.1250000000001A39.375 39.375 0 0 1 756.8750000000001 438.1250000000001C792.5000000000001 474.3750000000001 810 522.5 810 570C810 617.5 792.5000000000001 665.625 756.8750000000001 701.875A39.625 39.625 0 0 1 700.625 701.875z" />
<glyph glyph-name="remote"
unicode="&#xF10A;"
unicode="&#x26A9;"
horiz-adv-x="1000" d=" M524.97125 425.9231250000001L794.09375 156.8L875 237.615625L686.69375 425.9231250000001L875 614.184375L794.09375 695L524.97125 425.9231250000001zM313.3075 225.89875L125 414.20625L205.9075 495.02125L474.984375 225.89875L205.9075 -43.2687500000001L125 37.59375L313.3075 225.89875z" />
<glyph glyph-name="reply"
unicode="&#xF28C;"
@@ -455,7 +455,7 @@
unicode="&#xF28D;"
horiz-adv-x="1000" d=" M437.5 320H562.5V195H437.5z M437.5 632.5H562.5V382.5H437.5z M937.5 757.5H62.5C25 757.5 0 732.5 0 695V132.5C0 95 25 70 62.5 70H187.5V-180L437.5 70H937.5C975 70 1000 95 1000 132.5V695C1000 732.5 975 757.5 937.5 757.5zM937.5 132.5H406.25L250 -23.75V132.5H62.5V695H937.5z" />
<glyph glyph-name="request-changes"
unicode="&#xF10B;"
unicode="&#x26AA;"
horiz-adv-x="1000" d=" M0 757.5A62.5 62.5 0 0 0 62.5 820H937.5A62.5 62.5 0 0 0 1000 757.5V132.5A62.5 62.5 0 0 0 937.5 70H468.75L250 -148.75V70H62.5A62.5 62.5 0 0 0 0 132.5V757.5zM62.5 757.5V132.5H312.5V7.5L437.5 132.5H937.5V757.5H62.5zM531.25 570H656.25V507.5H531.25V382.5H468.75V507.5H343.75V570H468.75V695H531.25V570zM656.25 257.5H343.75V320H656.25V257.5z" />
<glyph glyph-name="rocket"
unicode="&#xF033;"
@@ -491,7 +491,7 @@
unicode="&#xF032;"
horiz-adv-x="941.1764705882352" d=" M705.8823529411765 290.5882352941177V408.2352941176471H470.5882352941176V525.8823529411765H705.8823529411765V643.5294117647059L941.1764705882352 467.0588235294118L705.8823529411765 290.5882352941177zM588.2352941176471 114.1176470588235H352.9411764705883V643.5294117647059L117.6470588235294 761.1764705882352H588.2352941176471V584.7058823529412H647.0588235294117V761.1764705882352C647.0588235294117 793.5294117647059 620.5882352941177 820 588.2352941176471 820H58.8235294117647C26.4705882352941 820 0 793.5294117647059 0 761.1764705882352V91.7647058823529C0 68.8235294117646 12.9411764705882 48.8235294117646 32.3529411764706 38.2352941176471L352.9411764705883 -121.764705882353V55.2941176470589H588.2352941176471C620.5882352941177 55.2941176470589 647.0588235294117 81.7647058823529 647.0588235294117 114.1176470588235V349.4117647058824H588.2352941176471V114.1176470588235z" />
<glyph glyph-name="smiley-outline"
unicode="&#xF10C;"
unicode="&#xF27D;"
horiz-adv-x="1000" d=" M500 820C223.75 820 0 596.25 0 320C0 43.75 223.75 -180 500 -180C776.25 -180 1000 43.75 1000 320C1000 596.25 776.25 820 500 820zM800.625 19.375C761.25 -20 715.625 -50 665 -71.25C613.125 -93.75 557.5 -104.375 500 -104.375C442.5 -104.375 386.875 -93.75 335 -71.25C284.375 -50 238.125 -19.375 199.375 19.375C160.625 58.125 130 104.375 108.75 155C86.25 206.875 75.625 262.5 75.625 320C75.625 377.5 86.25 433.125 108.75 485C130 535.625 160.625 581.875 199.375 620.625C238.125 659.375 284.375 690 335 711.25C386.875 733.75 442.5 744.375 500 744.375C557.5 744.375 613.125 733.75 665 711.25C715.625 690 761.875 659.375 800.625 620.625C839.375 581.875 870 535.625 891.25 485C913.75 433.125 924.375 377.5 924.375 320C924.375 262.5 913.75 206.875 891.25 155C870 104.375 839.375 58.125 800.625 19.375zM250 395V431.875C250 473.125 283.125 506.25 325 506.25H361.875C403.125 506.25 436.25 473.125 436.25 431.875V395C436.25 353.125 403.125 320 361.875 320H325C283.125 320 250 353.125 250 395zM562.5 395V431.875C562.5 473.125 595.625 506.25 637.5 506.25H674.375C715.625 506.25 748.75 473.125 748.75 431.875V395C748.75 353.125 715.625 320 674.375 320H637.5C595.625 320 562.5 353.125 562.5 395zM812.5 195C767.5 77.5 630.625 7.5 500 7.5C369.375 7.5 232.5 78.125 187.5 195C178.75 219.375 201.875 257.5 228.75 257.5H765.625C791.25 257.5 821.25 219.375 812.5 195z" />
<glyph glyph-name="smiley"
unicode="&#xF27D;"
@@ -566,7 +566,7 @@
unicode="&#xF064;"
horiz-adv-x="875" d=" M812.5 632.5H437.5C403.125 632.5 375 604.375 375 570V70C375 35.625 403.125 7.5 437.5 7.5H812.5C846.875 7.5 875 35.625 875 70V570C875 604.375 846.875 632.5 812.5 632.5zM750 132.5H500V507.5H750V132.5zM250 570H312.5V507.5H250V132.5H312.5V70H250C215.625 70 187.5 98.125 187.5 132.5V507.5C187.5 541.875 215.625 570 250 570zM62.5 507.5H125V445H62.5V195H125V132.5H62.5C28.125 132.5 0 160.625 0 195V445C0 479.375 28.125 507.5 62.5 507.5z" />
<glyph glyph-name="warning"
unicode="&#xF10D;"
unicode="&#xF02D;"
horiz-adv-x="1000" d=" M543.75 757.5H456.25L62.5 -30L150 -117.5H850L937.5 -30L543.75 757.5zM543.75 -30H456.25V57.5H543.75V-30zM543.75 145H456.25V495H543.75V145z" />
<glyph glyph-name="watch"
unicode="&#xF0E0;"

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

@@ -1,7 +1,7 @@
@font-face {
font-family: "octicons2";
src: url("./octicons2.ttf?dee9935d8deb764a470d194d9f0d07f7") format("truetype"),
url("./octicons2.svg?dee9935d8deb764a470d194d9f0d07f7#octicons2") format("svg");
src: url("./octicons2.ttf?e9cbaa049a291f47ea2a38815e18222e") format("truetype"),
url("./octicons2.svg?e9cbaa049a291f47ea2a38815e18222e#octicons2") format("svg");
}
.octicon, .mega-octicon {
@@ -157,7 +157,7 @@ url("./octicons2.svg?dee9935d8deb764a470d194d9f0d07f7#octicons2") format("svg");
.octicon-note:before { content: "\f289" }
.octicon-octoface:before { content: "\f008" }
.octicon-organization:before { content: "\f037" }
.octicon-organization-filled:before { content: "\26a2" }
.octicon-organization-filled:before { content: "\f037" }
.octicon-organization-outline:before { content: "\f037" }
.octicon-package:before { content: "\f0c4" }
.octicon-paintcan:before { content: "\f0d1" }
@@ -165,7 +165,7 @@ url("./octicons2.svg?dee9935d8deb764a470d194d9f0d07f7#octicons2") format("svg");
.octicon-person-add:before { content: "\f018" }
.octicon-person-follow:before { content: "\f018" }
.octicon-person:before { content: "\f018" }
.octicon-person-filled:before { content: "\26a3" }
.octicon-person-filled:before { content: "\f018" }
.octicon-person-outline:before { content: "\f018" }
.octicon-pin:before { content: "\f041" }
.octicon-plug:before { content: "\f0d4" }
+134 -99
View File
@@ -29,7 +29,8 @@ export interface ISplitViewOptions {
readonly orthogonalStartSash?: Sash;
readonly orthogonalEndSash?: Sash;
readonly inverseAltBehavior?: boolean;
readonly proportionalLayout?: boolean; // default true
readonly proportionalLayout?: boolean; // default true,
readonly descriptor?: ISplitViewDescriptor;
}
/**
@@ -197,6 +198,15 @@ export namespace Sizing {
export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; }
}
export interface ISplitViewDescriptor {
size: number;
views: {
visible?: boolean;
size: number;
view: IView;
}[];
}
export class SplitView extends Disposable {
readonly orientation: Orientation;
@@ -272,6 +282,21 @@ export class SplitView extends Disposable {
this.viewContainer = dom.append(this.el, dom.$('.split-view-container'));
this.style(options.styles || defaultStyles);
// We have an existing set of view, add them now
if (options.descriptor) {
this.size = options.descriptor.size;
options.descriptor.views.forEach((viewDescriptor, index) => {
const sizing = types.isUndefined(viewDescriptor.visible) || viewDescriptor.visible ? viewDescriptor.size : { type: 'invisible', cachedVisibleSize: viewDescriptor.size } as InvisibleSizing;
const view = viewDescriptor.view;
this.doAddView(view, sizing, index, true);
});
// Initialize content size and proportions for first layout
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
this.saveProportions();
}
}
style(styles: ISplitViewStyles): void {
@@ -285,102 +310,7 @@ export class SplitView extends Disposable {
}
addView(view: IView, size: number | Sizing, index = this.viewItems.length): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
// Add view
const container = dom.$('.split-view-view');
if (index === this.viewItems.length) {
this.viewContainer.appendChild(container);
} else {
this.viewContainer.insertBefore(container, this.viewContainer.children.item(index));
}
const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));
const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container));
const disposable = combinedDisposable(onChangeDisposable, containerDisposable);
let viewSize: ViewItemSize;
if (typeof size === 'number') {
viewSize = size;
} else if (size.type === 'split') {
viewSize = this.getViewSize(size.index) / 2;
} else if (size.type === 'invisible') {
viewSize = { cachedVisibleSize: size.cachedVisibleSize };
} else {
viewSize = view.minimumSize;
}
const item = this.orientation === Orientation.VERTICAL
? new VerticalViewItem(container, view, viewSize, disposable)
: new HorizontalViewItem(container, view, viewSize, disposable);
this.viewItems.splice(index, 0, item);
// Add sash
if (this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) } : { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) };
const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
});
const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey })
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey });
const onStart = Event.map(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this);
const onChange = Event.map(sash.onDidChange, sashEventMapper);
const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = Event.map(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidResetDisposable = sash.onDidReset(() => {
const index = firstIndex(this.sashItems, item => item.sash === sash);
const upIndexes = range(index, -1);
const downIndexes = range(index + 1, this.viewItems.length);
const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
if (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) {
return;
}
if (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) {
return;
}
this._onDidSashReset.fire(index);
});
const disposable = combinedDisposable(onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash);
const sashItem: ISashItem = { sash, disposable };
this.sashItems.splice(index - 1, 0, sashItem);
}
container.appendChild(view.element);
let highPriorityIndexes: number[] | undefined;
if (typeof size !== 'number' && size.type === 'split') {
highPriorityIndexes = [size.index];
}
this.relayout([index], highPriorityIndexes);
this.state = State.Idle;
if (typeof size !== 'number' && size.type === 'distribute') {
this.distributeViewSizes();
}
this.doAddView(view, size, index, false);
}
removeView(index: number, sizing?: Sizing): IView {
@@ -689,6 +619,108 @@ export class SplitView extends Disposable {
return this.viewItems[index].size;
}
private doAddView(view: IView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
// Add view
const container = dom.$('.split-view-view');
if (index === this.viewItems.length) {
this.viewContainer.appendChild(container);
} else {
this.viewContainer.insertBefore(container, this.viewContainer.children.item(index));
}
const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));
const containerDisposable = toDisposable(() => this.viewContainer.removeChild(container));
const disposable = combinedDisposable(onChangeDisposable, containerDisposable);
let viewSize: ViewItemSize;
if (typeof size === 'number') {
viewSize = size;
} else if (size.type === 'split') {
viewSize = this.getViewSize(size.index) / 2;
} else if (size.type === 'invisible') {
viewSize = { cachedVisibleSize: size.cachedVisibleSize };
} else {
viewSize = view.minimumSize;
}
const item = this.orientation === Orientation.VERTICAL
? new VerticalViewItem(container, view, viewSize, disposable)
: new HorizontalViewItem(container, view, viewSize, disposable);
this.viewItems.splice(index, 0, item);
// Add sash
if (this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) } : { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) };
const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
});
const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey })
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey });
const onStart = Event.map(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this);
const onChange = Event.map(sash.onDidChange, sashEventMapper);
const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = Event.map(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidResetDisposable = sash.onDidReset(() => {
const index = firstIndex(this.sashItems, item => item.sash === sash);
const upIndexes = range(index, -1);
const downIndexes = range(index + 1, this.viewItems.length);
const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
if (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) {
return;
}
if (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) {
return;
}
this._onDidSashReset.fire(index);
});
const disposable = combinedDisposable(onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash);
const sashItem: ISashItem = { sash, disposable };
this.sashItems.splice(index - 1, 0, sashItem);
}
container.appendChild(view.element);
let highPriorityIndexes: number[] | undefined;
if (typeof size !== 'number' && size.type === 'split') {
highPriorityIndexes = [size.index];
}
if (!skipLayout) {
this.relayout([index], highPriorityIndexes);
}
this.state = State.Idle;
if (!skipLayout && typeof size !== 'number' && size.type === 'distribute') {
this.distributeViewSizes();
}
}
private relayout(lowPriorityIndexes?: number[], highPriorityIndexes?: number[]): void {
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
@@ -850,9 +882,12 @@ export class SplitView extends Disposable {
const snapBeforeIndex = this.findFirstSnapIndex(upIndexes);
const snapAfterIndex = this.findFirstSnapIndex(downIndexes);
if (typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible) {
const snappedBefore = typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible;
const snappedAfter = typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible;
if (snappedBefore && collapsesUp[index]) {
sash.state = SashState.Minimum;
} else if (typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible) {
} else if (snappedAfter && collapsesDown[index]) {
sash.state = SashState.Maximum;
} else {
sash.state = SashState.Disabled;
+6
View File
@@ -532,6 +532,12 @@ export interface FuzzyScorer {
export function fuzzyScore(pattern: string, patternLow: string, patternPos: number, word: string, wordLow: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined {
if (patternPos > 0) {
pattern = pattern.substr(patternPos);
patternLow = patternLow.substr(patternPos);
patternPos = 0;
}
const patternLen = pattern.length > _maxLen ? _maxLen : pattern.length;
const wordLen = word.length > _maxLen ? _maxLen : word.length;
+6 -2
View File
@@ -420,7 +420,7 @@ export class BufferedEmitter<T> {
// it is important to deliver these messages after this call, but before
// other messages have a chance to be received (to guarantee in order delivery)
// that's why we're using here nextTick and not other types of timeouts
process.nextTick(() => this._deliverMessages);
process.nextTick(() => this._deliverMessages());
},
onLastListenerRemove: () => {
this._hasListeners = false;
@@ -443,7 +443,11 @@ export class BufferedEmitter<T> {
public fire(event: T): void {
if (this._hasListeners) {
this._emitter.fire(event);
if (this._bufferedMessages.length > 0) {
this._bufferedMessages.push(event);
} else {
this._emitter.fire(event);
}
} else {
this._bufferedMessages.push(event);
}
@@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CancellationToken } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
import { assign } from 'vs/base/common/objects';
import { VSBuffer, bufferToStream } from 'vs/base/common/buffer';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
export function request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
if (options.proxyAuthorization) {
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': options.proxyAuthorization });
}
const xhr = new XMLHttpRequest();
return new Promise<IRequestContext>((resolve, reject) => {
xhr.open(options.type || 'GET', options.url || '', true, options.user, options.password);
setRequestHeaders(xhr, options);
xhr.responseType = 'arraybuffer';
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText)));
xhr.onload = (e) => {
resolve({
res: {
statusCode: xhr.status,
headers: getResponseHeaders(xhr)
},
stream: bufferToStream(VSBuffer.wrap(new Uint8Array(xhr.response)))
});
};
xhr.ontimeout = e => reject(new Error(`XHR timeout: ${options.timeout}ms`));
if (options.timeout) {
xhr.timeout = options.timeout;
}
xhr.send(options.data);
// cancel
token.onCancellationRequested(() => {
xhr.abort();
reject(canceled());
});
});
}
function setRequestHeaders(xhr: XMLHttpRequest, options: IRequestOptions): void {
if (options.headers) {
outer: for (let k in options.headers) {
switch (k) {
case 'User-Agent':
case 'Accept-Encoding':
case 'Content-Length':
// unsafe headers
continue outer;
}
xhr.setRequestHeader(k, options.headers[k]);
}
}
}
function getResponseHeaders(xhr: XMLHttpRequest): { [name: string]: string } {
const headers: { [name: string]: string } = Object.create(null);
for (const line of xhr.getAllResponseHeaders().split(/\r\n|\n|\r/g)) {
if (line) {
const idx = line.indexOf(':');
headers[line.substr(0, idx).trim().toLowerCase()] = line.substr(idx + 1).trim();
}
}
return headers;
}
@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { VSBufferReadableStream } from 'vs/base/common/buffer';
export interface IHeaders {
[header: string]: string;
}
export interface IRequestOptions {
type?: string;
url?: string;
user?: string;
password?: string;
headers?: IHeaders;
timeout?: number;
data?: string;
followRedirects?: number;
proxyAuthorization?: string;
}
export interface IRequestContext {
res: {
headers: IHeaders;
statusCode?: number;
};
stream: VSBufferReadableStream;
}
+5
View File
@@ -389,6 +389,11 @@ suite('Filters', () => {
assertMatches('g', 'zzGroup', 'zz^Group', fuzzyScore);
});
test('patternPos isn\'t working correctly #79815', function () {
assertMatches(':p'.substr(1), 'prop', '^prop', fuzzyScore, { patternPos: 0 });
assertMatches(':p', 'prop', '^prop', fuzzyScore, { patternPos: 1 });
});
function assertTopScore(filter: typeof fuzzyScore, pattern: string, expected: number, ...words: string[]) {
let topScore = -(100 * 10);
let topIdx = 0;
+4 -4
View File
@@ -10,18 +10,18 @@
<!-- Content Security Policy -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; img-src 'self' https: data: blob:; media-src 'none'; frame-src 'self' {{WEBVIEW_ENDPOINT}} https://*.vscode-webview-test.com; script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss: https:; font-src 'self' blob:;"
content="default-src 'none'; img-src 'self' https: data: blob:; media-src 'none'; frame-src 'self' {{WEBVIEW_ENDPOINT}} https://*.vscode-webview-test.com; script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss: https:; font-src 'self' blob:; manifest-src 'self';"
>
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}">
<!-- Workarounds/Hacks (remote user data uri, product configuration ) -->
<!-- Workarounds/Hacks (remote user data uri) -->
<meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}">
<meta id="vscode-remote-product-configuration" data-settings="{{PRODUCT_CONFIGURATION}}">
<!-- Workbench Icon/CSS -->
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="/manifest.json">
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.api.css">
</head>
@@ -132,7 +132,7 @@ class VisualEditorState {
this._zonesMap[String(zoneId)] = true;
if (newDecorations.zones[i].diff && viewZone.marginDomNode) {
this.inlineDiffMargins.push(new InlineDiffMargin(viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
this.inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
}
}
});
@@ -9,6 +9,7 @@ import { Action } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { Range } from 'vs/editor/common/core/range';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
@@ -21,10 +22,29 @@ export interface IDiffLinesChange {
}
export class InlineDiffMargin extends Disposable {
private readonly _lightBulb: HTMLElement;
private readonly _diffActions: HTMLElement;
private _visibility: boolean = false;
get visibility(): boolean {
return this._visibility;
}
set visibility(_visibility: boolean) {
if (this._visibility !== _visibility) {
this._visibility = _visibility;
if (_visibility) {
this._diffActions.style.visibility = 'visible';
} else {
this._diffActions.style.visibility = 'hidden';
}
}
}
constructor(
marginDomNode: HTMLElement,
private _viewZoneId: string,
private _marginDomNode: HTMLElement,
public editor: CodeEditorWidget,
public diff: IDiffLinesChange,
private _contextMenuService: IContextMenuService,
@@ -33,17 +53,18 @@ export class InlineDiffMargin extends Disposable {
super();
// make sure the diff margin shows above overlay.
marginDomNode.style.zIndex = '10';
this._marginDomNode.style.zIndex = '10';
this._lightBulb = document.createElement('div');
this._lightBulb.className = 'lightbulb-glyph';
this._lightBulb.style.position = 'absolute';
this._diffActions = document.createElement('div');
this._diffActions.className = 'lightbulb-glyph';
this._diffActions.style.position = 'absolute';
const lineHeight = editor.getConfiguration().lineHeight;
const lineFeed = editor.getModel()!.getEOL();
this._lightBulb.style.right = '0px';
this._lightBulb.style.visibility = 'hidden';
this._lightBulb.style.height = `${lineHeight}px`;
marginDomNode.appendChild(this._lightBulb);
this._diffActions.style.right = '0px';
this._diffActions.style.visibility = 'hidden';
this._diffActions.style.height = `${lineHeight}px`;
this._diffActions.style.lineHeight = `${lineHeight}px`;
this._marginDomNode.appendChild(this._diffActions);
const actions = [
new Action(
@@ -59,17 +80,21 @@ export class InlineDiffMargin extends Disposable {
let currentLineNumberOffset = 0;
const copyLineAction = new Action(
'diff.clipboard.copyDeletedLineContent',
nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber),
undefined,
true,
async () => {
await this._clipboardService.writeText(diff.originalContent[currentLineNumberOffset]);
}
);
let copyLineAction: Action | undefined = undefined;
actions.push(copyLineAction);
if (diff.originalEndLineNumber > diff.modifiedStartLineNumber) {
copyLineAction = new Action(
'diff.clipboard.copyDeletedLineContent',
nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber),
undefined,
true,
async () => {
await this._clipboardService.writeText(diff.originalContent[currentLineNumberOffset]);
}
);
actions.push(copyLineAction);
}
const readOnly = editor.getConfiguration().readOnly;
if (!readOnly) {
@@ -96,21 +121,8 @@ export class InlineDiffMargin extends Disposable {
}));
}
this._register(dom.addStandardDisposableListener(marginDomNode, 'mouseenter', e => {
this._lightBulb.style.visibility = 'visible';
currentLineNumberOffset = this._updateLightBulbPosition(marginDomNode, e.y, lineHeight);
}));
this._register(dom.addStandardDisposableListener(marginDomNode, 'mouseleave', e => {
this._lightBulb.style.visibility = 'hidden';
}));
this._register(dom.addStandardDisposableListener(marginDomNode, 'mousemove', e => {
currentLineNumberOffset = this._updateLightBulbPosition(marginDomNode, e.y, lineHeight);
}));
this._register(dom.addStandardDisposableListener(this._lightBulb, 'mousedown', e => {
const { top, height } = dom.getDomNodePagePosition(this._lightBulb);
this._register(dom.addStandardDisposableListener(this._diffActions, 'mousedown', e => {
const { top, height } = dom.getDomNodePagePosition(this._diffActions);
let pad = Math.floor(lineHeight / 3) + lineHeight;
this._contextMenuService.showContextMenu({
getAnchor: () => {
@@ -120,12 +132,29 @@ export class InlineDiffMargin extends Disposable {
};
},
getActions: () => {
copyLineAction.label = nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber + currentLineNumberOffset);
if (copyLineAction) {
copyLineAction.label = nls.localize('diff.clipboard.copyDeletedLineContent.label', "Copy deleted line {0} content to clipboard", diff.originalStartLineNumber + currentLineNumberOffset);
}
return actions;
},
autoSelectFirstItem: true
});
}));
this._register(editor.onMouseMove((e: editorBrowser.IEditorMouseEvent) => {
if (e.target.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE) {
const viewZoneId = e.target.detail.viewZoneId;
if (viewZoneId === this._viewZoneId) {
this.visibility = true;
currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight);
} else {
this.visibility = false;
}
} else {
this.visibility = false;
}
}));
}
private _updateLightBulbPosition(marginDomNode: HTMLElement, y: number, lineHeight: number): number {
@@ -133,7 +162,7 @@ export class InlineDiffMargin extends Disposable {
const offset = y - top;
const lineNumberOffset = Math.floor(offset / lineHeight);
const newTop = lineNumberOffset * lineHeight;
this._lightBulb.style.top = `${newTop}px`;
this._diffActions.style.top = `${newTop}px`;
return lineNumberOffset;
}
}
@@ -93,3 +93,16 @@
.monaco-editor .view-zones .view-lines .view-line span {
display: inline-block;
}
.monaco-editor .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph {
background: url('lightbulb-light.svg') center center no-repeat;
}
.monaco-editor.vs-dark .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph,
.monaco-editor.hc-dark .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph {
background: url('lightbulb-dark.svg') center center no-repeat;
}
.monaco-editor .margin-view-zones .lightbulb-glyph:hover {
cursor: pointer;
}
@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#C2C2C2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#424242"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6708 8.65806C11.3319 8.9916 11.0716 9.36278 10.8886 9.77172C10.7105 10.1792 10.621 10.6219 10.621 11.1009V12.7012C10.621 12.8807 10.5872 13.0503 10.5189 13.2091C10.4513 13.3661 10.3586 13.5038 10.2407 13.6213C10.1228 13.7388 9.98464 13.8311 9.82723 13.8984C9.66806 13.9663 9.49806 14 9.31823 14H7.71205C7.53223 14 7.36223 13.9663 7.20306 13.8984C7.04564 13.8311 6.90753 13.7388 6.78961 13.6213C6.67168 13.5038 6.57895 13.3661 6.51141 13.2091C6.44311 13.0503 6.40927 12.8807 6.40927 12.7012V11.1009C6.40927 10.622 6.31772 10.1795 6.13553 9.77209C5.95683 9.36336 5.69832 8.99156 5.35953 8.65806C4.92468 8.22903 4.58896 7.75003 4.35361 7.22134C4.11756 6.69107 4 6.11672 4 5.49953C4 5.08664 4.05342 4.68802 4.16048 4.30397C4.26728 3.92089 4.41907 3.56286 4.61595 3.23018C4.81257 2.89377 5.04777 2.58911 5.32146 2.31641C5.59503 2.04383 5.89858 1.80953 6.23195 1.61364C6.56979 1.41764 6.93146 1.2662 7.31578 1.15983C7.70106 1.0532 8.10094 1 8.51514 1C8.92934 1 9.32923 1.0532 9.71451 1.15983C10.0988 1.2662 10.458 1.41739 10.7918 1.61351C11.1294 1.80938 11.4351 2.0437 11.7088 2.31641C11.9825 2.5891 12.2177 2.89376 12.4143 3.23016C12.6112 3.56285 12.763 3.92088 12.8698 4.30397C12.9769 4.68802 13.0303 5.08664 13.0303 5.49953C13.0303 6.11672 12.9127 6.69107 12.6767 7.22134C12.4413 7.75003 12.1056 8.22903 11.6708 8.65806ZM9.62162 10.5H7.40867V12.7012C7.40867 12.7823 7.4372 12.8512 7.49888 12.9127C7.56058 12.9741 7.63007 13.0028 7.71205 13.0028H9.31823C9.40022 13.0028 9.46971 12.9741 9.5314 12.9127C9.59309 12.8512 9.62162 12.7823 9.62162 12.7012V10.5Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -558,6 +558,17 @@ const editorConfiguration: IConfigurationNode = {
'default': EDITOR_DEFAULTS.autoClosingQuotes,
'description': nls.localize('autoClosingQuotes', "Controls whether the editor should automatically close quotes after the user adds an opening quote.")
},
'editor.autoClosingOvertype': {
type: 'string',
enum: ['always', 'auto', 'never'],
enumDescriptions: [
nls.localize('editor.autoClosingOvertype.always', "Always type over closing quotes or brackets."),
nls.localize('editor.autoClosingOvertype.auto', "Type over closing quotes or brackets only if they were automatically inserted."),
nls.localize('editor.autoClosingOvertype.never', "Never type over closing quotes or brackets."),
],
'default': EDITOR_DEFAULTS.autoClosingOvertype,
'description': nls.localize('autoClosingOvertype', "Controls whether the editor should type over closing quotes or brackets.")
},
'editor.autoSurround': {
type: 'string',
enum: ['languageDefined', 'brackets', 'quotes', 'never'],
+21 -2
View File
@@ -108,6 +108,11 @@ export type EditorAutoClosingStrategy = 'always' | 'languageDefined' | 'beforeWh
*/
export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'brackets' | 'never';
/**
* Configuration options for typing over closing quotes or brackets
*/
export type EditorAutoClosingOvertypeStrategy = 'always' | 'auto' | 'never';
/**
* Configuration options for editor minimap
*/
@@ -544,6 +549,10 @@ export interface IEditorOptions {
* Defaults to language defined behavior.
*/
autoClosingQuotes?: EditorAutoClosingStrategy;
/**
* Options for typing over closing quotes or brackets.
*/
autoClosingOvertype?: EditorAutoClosingOvertypeStrategy;
/**
* Options for auto surrounding.
* Defaults to always allowing auto surrounding.
@@ -1079,6 +1088,7 @@ export interface IValidatedEditorOptions {
readonly wordWrapBreakObtrusiveCharacters: string;
readonly autoClosingBrackets: EditorAutoClosingStrategy;
readonly autoClosingQuotes: EditorAutoClosingStrategy;
readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
readonly autoSurround: EditorAutoSurroundStrategy;
readonly autoIndent: boolean;
readonly dragAndDrop: boolean;
@@ -1117,6 +1127,7 @@ export class InternalEditorOptions {
readonly wordSeparators: string;
readonly autoClosingBrackets: EditorAutoClosingStrategy;
readonly autoClosingQuotes: EditorAutoClosingStrategy;
readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
readonly autoSurround: EditorAutoSurroundStrategy;
readonly autoIndent: boolean;
readonly useTabStops: boolean;
@@ -1147,6 +1158,7 @@ export class InternalEditorOptions {
wordSeparators: string;
autoClosingBrackets: EditorAutoClosingStrategy;
autoClosingQuotes: EditorAutoClosingStrategy;
autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
autoSurround: EditorAutoSurroundStrategy;
autoIndent: boolean;
useTabStops: boolean;
@@ -1172,6 +1184,7 @@ export class InternalEditorOptions {
this.wordSeparators = source.wordSeparators;
this.autoClosingBrackets = source.autoClosingBrackets;
this.autoClosingQuotes = source.autoClosingQuotes;
this.autoClosingOvertype = source.autoClosingOvertype;
this.autoSurround = source.autoSurround;
this.autoIndent = source.autoIndent;
this.useTabStops = source.useTabStops;
@@ -1203,6 +1216,7 @@ export class InternalEditorOptions {
&& this.wordSeparators === other.wordSeparators
&& this.autoClosingBrackets === other.autoClosingBrackets
&& this.autoClosingQuotes === other.autoClosingQuotes
&& this.autoClosingOvertype === other.autoClosingOvertype
&& this.autoSurround === other.autoSurround
&& this.autoIndent === other.autoIndent
&& this.useTabStops === other.useTabStops
@@ -1235,6 +1249,7 @@ export class InternalEditorOptions {
wordSeparators: (this.wordSeparators !== newOpts.wordSeparators),
autoClosingBrackets: (this.autoClosingBrackets !== newOpts.autoClosingBrackets),
autoClosingQuotes: (this.autoClosingQuotes !== newOpts.autoClosingQuotes),
autoClosingOvertype: (this.autoClosingOvertype !== newOpts.autoClosingOvertype),
autoSurround: (this.autoSurround !== newOpts.autoSurround),
autoIndent: (this.autoIndent !== newOpts.autoIndent),
useTabStops: (this.useTabStops !== newOpts.useTabStops),
@@ -1640,6 +1655,7 @@ export interface IConfigurationChangedEvent {
readonly wordSeparators: boolean;
readonly autoClosingBrackets: boolean;
readonly autoClosingQuotes: boolean;
readonly autoClosingOvertype: boolean;
readonly autoSurround: boolean;
readonly autoIndent: boolean;
readonly useTabStops: boolean;
@@ -1852,6 +1868,7 @@ export class EditorOptionsValidator {
wordWrapBreakObtrusiveCharacters: _string(opts.wordWrapBreakObtrusiveCharacters, defaults.wordWrapBreakObtrusiveCharacters),
autoClosingBrackets,
autoClosingQuotes,
autoClosingOvertype: _stringSet<EditorAutoClosingOvertypeStrategy>(opts.autoClosingOvertype, defaults.autoClosingOvertype, ['always', 'auto', 'never']),
autoSurround,
autoIndent: _boolean(opts.autoIndent, defaults.autoIndent),
dragAndDrop: _boolean(opts.dragAndDrop, defaults.dragAndDrop),
@@ -2148,7 +2165,6 @@ export class EditorOptionsValidator {
export class InternalEditorOptionsFactory {
private static _tweakValidatedOptions(opts: IValidatedEditorOptions, accessibilitySupport: AccessibilitySupport): IValidatedEditorOptions {
const accessibilityIsOn = (accessibilitySupport === AccessibilitySupport.Enabled);
const accessibilityIsOff = (accessibilitySupport === AccessibilitySupport.Disabled);
return {
inDiffEditor: opts.inDiffEditor,
@@ -2168,6 +2184,7 @@ export class InternalEditorOptionsFactory {
wordWrapBreakObtrusiveCharacters: opts.wordWrapBreakObtrusiveCharacters,
autoClosingBrackets: opts.autoClosingBrackets,
autoClosingQuotes: opts.autoClosingQuotes,
autoClosingOvertype: opts.autoClosingOvertype,
autoSurround: opts.autoSurround,
autoIndent: opts.autoIndent,
dragAndDrop: opts.dragAndDrop,
@@ -2244,7 +2261,7 @@ export class InternalEditorOptionsFactory {
selectionHighlight: opts.contribInfo.selectionHighlight,
occurrencesHighlight: opts.contribInfo.occurrencesHighlight,
codeLens: opts.contribInfo.codeLens,
folding: (accessibilityIsOn ? false : opts.contribInfo.folding), // DISABLED WHEN SCREEN READER IS ATTACHED
folding: opts.contribInfo.folding,
foldingStrategy: opts.contribInfo.foldingStrategy,
showFoldingControls: opts.contribInfo.showFoldingControls,
matchBrackets: opts.contribInfo.matchBrackets,
@@ -2396,6 +2413,7 @@ export class InternalEditorOptionsFactory {
wordSeparators: opts.wordSeparators,
autoClosingBrackets: opts.autoClosingBrackets,
autoClosingQuotes: opts.autoClosingQuotes,
autoClosingOvertype: opts.autoClosingOvertype,
autoSurround: opts.autoSurround,
autoIndent: opts.autoIndent,
useTabStops: opts.useTabStops,
@@ -2635,6 +2653,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
wordWrapBreakObtrusiveCharacters: '.',
autoClosingBrackets: 'languageDefined',
autoClosingQuotes: 'languageDefined',
autoClosingOvertype: 'auto',
autoSurround: 'languageDefined',
autoIndent: true,
dragAndDrop: true,
@@ -6,7 +6,7 @@
import { CharCode } from 'vs/base/common/charCode';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, IConfigurationChangedEvent, EditorAutoClosingOvertypeStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -99,6 +99,7 @@ export class CursorConfiguration {
public readonly multiCursorMergeOverlapping: boolean;
public readonly autoClosingBrackets: EditorAutoClosingStrategy;
public readonly autoClosingQuotes: EditorAutoClosingStrategy;
public readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
public readonly autoSurround: EditorAutoSurroundStrategy;
public readonly autoIndent: boolean;
public readonly autoClosingPairsOpen2: Map<string, StandardAutoClosingPairConditional[]>;
@@ -117,6 +118,7 @@ export class CursorConfiguration {
|| e.multiCursorMergeOverlapping
|| e.autoClosingBrackets
|| e.autoClosingQuotes
|| e.autoClosingOvertype
|| e.autoSurround
|| e.useTabStops
|| e.lineHeight
@@ -146,6 +148,7 @@ export class CursorConfiguration {
this.multiCursorMergeOverlapping = c.multiCursorMergeOverlapping;
this.autoClosingBrackets = c.autoClosingBrackets;
this.autoClosingQuotes = c.autoClosingQuotes;
this.autoClosingOvertype = c.autoClosingOvertype;
this.autoSurround = c.autoSurround;
this.autoIndent = c.autoIndent;
@@ -431,10 +431,8 @@ export class TypeOperations {
return null;
}
private static _isAutoClosingCloseCharType(config: CursorConfiguration, model: ITextModel, selections: Selection[], autoClosedCharacters: Range[], ch: string): boolean {
const autoCloseConfig = isQuote(ch) ? config.autoClosingQuotes : config.autoClosingBrackets;
if (autoCloseConfig === 'never') {
private static _isAutoClosingOvertype(config: CursorConfiguration, model: ITextModel, selections: Selection[], autoClosedCharacters: Range[], ch: string): boolean {
if (config.autoClosingOvertype === 'never') {
return false;
}
@@ -458,23 +456,25 @@ export class TypeOperations {
}
// Must over-type a closing character typed by the editor
let found = false;
for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
const autoClosedCharacter = autoClosedCharacters[j];
if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {
found = true;
break;
if (config.autoClosingOvertype === 'auto') {
let found = false;
for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
const autoClosedCharacter = autoClosedCharacters[j];
if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
if (!found) {
return false;
}
}
return true;
}
private static _runAutoClosingCloseCharType(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string): EditOperationResult {
private static _runAutoClosingOvertype(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], ch: string): EditOperationResult {
let commands: ICommand[] = [];
for (let i = 0, len = selections.length; i < len; i++) {
const selection = selections[i];
@@ -765,7 +765,7 @@ export class TypeOperations {
return null;
}
if (this._isAutoClosingCloseCharType(config, model, selections, autoClosedCharacters, ch)) {
if (this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {
// Unfortunately, the close character is at this point "doubled", so we need to delete it...
const commands = selections.map(s => new ReplaceCommand(new Range(s.positionLineNumber, s.positionColumn, s.positionLineNumber, s.positionColumn + 1), '', false));
return new EditOperationResult(EditOperationType.Typing, commands, {
@@ -813,8 +813,8 @@ export class TypeOperations {
}
}
if (this._isAutoClosingCloseCharType(config, model, selections, autoClosedCharacters, ch)) {
return this._runAutoClosingCloseCharType(prevEditOperationType, config, model, selections, ch);
if (this._isAutoClosingOvertype(config, model, selections, autoClosedCharacters, ch)) {
return this._runAutoClosingOvertype(prevEditOperationType, config, model, selections, ch);
}
const autoClosingPairOpenCharType = this._isAutoClosingOpenCharType(config, model, selections, ch, true);
@@ -39,7 +39,8 @@ const enum WordType {
export const enum WordNavigationType {
WordStart = 0,
WordStartFast = 1,
WordEnd = 2
WordEnd = 2,
WordAccessibility = 3 // Respect chrome defintion of a word
}
export class WordOperations {
@@ -202,6 +203,18 @@ export class WordOperations {
return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.start + 1 : 1);
}
if (wordNavigationType === WordNavigationType.WordAccessibility) {
while (
prevWordOnLine
&& prevWordOnLine.wordType === WordType.Separator
) {
// Skip over words made up of only separators
prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));
}
return new Position(lineNumber, prevWordOnLine ? prevWordOnLine.start + 1 : 1);
}
// We are stopping at the ending of words
if (prevWordOnLine && column <= prevWordOnLine.end + 1) {
@@ -270,6 +283,21 @@ export class WordOperations {
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
}
}
if (nextWordOnLine) {
column = nextWordOnLine.end + 1;
} else {
column = model.getLineMaxColumn(lineNumber);
}
} else if (wordNavigationType === WordNavigationType.WordAccessibility) {
while (
nextWordOnLine
&& nextWordOnLine.wordType === WordType.Separator
) {
// Skip over a word made up of one single separator
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
}
if (nextWordOnLine) {
column = nextWordOnLine.end + 1;
} else {
@@ -617,4 +645,4 @@ export class WordPartOperations extends WordOperations {
function enforceDefined<T>(arr: Array<T | undefined | null>): T[] {
return <T[]>arr.filter(el => Boolean(el));
}
}
@@ -78,7 +78,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
break;
case CharCode.Space:
partContent += '&nbsp';
partContent += '&nbsp;';
break;
default:
@@ -38,6 +38,7 @@
line-height: 19px;
transition: top 200ms linear;
padding: 0 4px;
box-sizing: border-box;
}
.monaco-editor .find-widget.hiddenEditor {
+34 -1
View File
@@ -57,7 +57,7 @@ const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "O
const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}");
const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results");
const FIND_WIDGET_INITIAL_WIDTH = 411;
const FIND_WIDGET_INITIAL_WIDTH = 419;
const PART_WIDTH = 275;
const FIND_INPUT_AREA_WIDTH = PART_WIDTH - 54;
@@ -1172,6 +1172,39 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._findInput.inputBox.layout();
this._tryUpdateHeight();
}));
this._register(this._resizeSash.onDidReset(() => {
// users double click on the sash
const currentWidth = dom.getTotalWidth(this._domNode);
if (currentWidth < FIND_WIDGET_INITIAL_WIDTH) {
// The editor is narrow and the width of the find widget is controlled fully by CSS.
return;
}
let width = FIND_WIDGET_INITIAL_WIDTH;
if (!this._resized || currentWidth === FIND_WIDGET_INITIAL_WIDTH) {
// 1. never resized before, double click should maximizes it
// 2. users resized it already but its width is the same as default
width = this._codeEditor.getConfiguration().layoutInfo.width - 28 - this._codeEditor.getConfiguration().layoutInfo.minimapWidth - 15;
this._resized = true;
} else {
/**
* no op, the find widget should be shrinked to its default size.
*/
}
const inputBoxWidth = width - FIND_ALL_CONTROLS_WIDTH;
this._domNode.style.width = `${width}px`;
this._findInput.inputBox.width = inputBoxWidth;
if (this._isReplaceVisible) {
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
}
this._findInput.inputBox.layout();
}));
}
private updateAccessibilitySupport(): void {
@@ -7,7 +7,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { onUnexpectedError } from 'vs/base/common/errors';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { dispose, IDisposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
@@ -33,9 +33,49 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ
import { IdleValue } from 'vs/base/common/async';
import { isObject } from 'vs/base/common/types';
import { CommitCharacterController } from './suggestCommitCharacters';
import { IPosition } from 'vs/editor/common/core/position';
import { TrackedRangeStickiness, ITextModel } from 'vs/editor/common/model';
const _sticky = false; // for development purposes only
class LineSuffix {
private readonly _marker: string[] | undefined;
constructor(private readonly _model: ITextModel, private readonly _position: IPosition) {
// spy on what's happening right of the cursor. two cases:
// 1. end of line -> check that it's still end of line
// 2. mid of line -> add a marker and compute the delta
const maxColumn = _model.getLineMaxColumn(_position.lineNumber);
if (maxColumn !== _position.column) {
const offset = _model.getOffsetAt(_position);
const end = _model.getPositionAt(offset + 1);
this._marker = _model.deltaDecorations([], [{
range: Range.fromPositions(_position, end),
options: { stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }
}]);
}
}
dispose(): void {
if (this._marker) {
this._model.deltaDecorations(this._marker, []);
}
}
delta(position: IPosition): number {
if (this._position.lineNumber !== position.lineNumber) {
return 0;
} else if (this._marker) {
const range = this._model.getDecorationRange(this._marker[0]);
const end = this._model.getOffsetAt(range!.getStartPosition());
return end - this._model.getOffsetAt(position);
} else {
return this._model.getLineMaxColumn(position.lineNumber) - position.column;
}
}
}
export class SuggestController implements IEditorContribution {
private static readonly ID: string = 'editor.contrib.suggestController';
@@ -47,9 +87,9 @@ export class SuggestController implements IEditorContribution {
private readonly _model: SuggestModel;
private readonly _widget: IdleValue<SuggestWidget>;
private readonly _alternatives: IdleValue<SuggestAlternatives>;
private readonly _lineSuffix = new MutableDisposable<LineSuffix>();
private readonly _toDispose = new DisposableStore();
constructor(
private _editor: ICodeEditor,
@IEditorWorkerService editorWorker: IEditorWorkerService,
@@ -115,6 +155,7 @@ export class SuggestController implements IEditorContribution {
this._toDispose.add(this._model.onDidTrigger(e => {
this._widget.getValue().showTriggered(e.auto, e.shy ? 250 : 50);
this._lineSuffix.value = new LineSuffix(this._editor.getModel()!, e.position);
}));
this._toDispose.add(this._model.onDidSuggest(e => {
if (!e.shy) {
@@ -123,7 +164,7 @@ export class SuggestController implements IEditorContribution {
}
}));
this._toDispose.add(this._model.onDidCancel(e => {
if (this._widget && !e.retrigger) {
if (!e.retrigger) {
this._widget.getValue().hideWidget();
}
}));
@@ -154,6 +195,7 @@ export class SuggestController implements IEditorContribution {
this._toDispose.dispose();
this._widget.dispose();
this._model.dispose();
this._lineSuffix.dispose();
}
protected _insertSuggestion(event: ISelectedSuggestion | undefined, keepAlternativeSuggestions: boolean, undoStops: boolean): void {
@@ -193,10 +235,11 @@ export class SuggestController implements IEditorContribution {
const overwriteBefore = position.column - suggestion.range.startColumn;
const overwriteAfter = suggestion.range.endColumn - position.column;
const suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0;
SnippetController2.get(this._editor).insert(insertText, {
overwriteBefore: overwriteBefore + columnDelta,
overwriteAfter,
overwriteAfter: overwriteAfter + suffixDelta,
undoStopBefore: false,
undoStopAfter: false,
adjustWhitespace: !(suggestion.insertTextRules! & CompletionItemInsertTextRule.KeepWhitespace)
@@ -10,7 +10,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose, DisposableStore, isDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextModel, IWordAtPosition } from 'vs/editor/common/model';
import { CompletionItemProvider, StandardTokenType, CompletionContext, CompletionProviderRegistry, CompletionTriggerKind, CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
@@ -28,6 +28,7 @@ export interface ICancelEvent {
export interface ITriggerEvent {
readonly auto: boolean;
readonly shy: boolean;
readonly position: IPosition;
}
export interface ISuggestEvent {
@@ -365,7 +366,7 @@ export class SuggestModel implements IDisposable {
// Cancel previous requests, change state & update UI
this.cancel(retrigger);
this._state = auto ? State.Auto : State.Manual;
this._onDidTrigger.fire({ auto, shy: context.shy });
this._onDidTrigger.fire({ auto, shy: context.shy, position: this._editor.getPosition() });
// Capture context when request was sent
this._context = ctx;
@@ -9,7 +9,7 @@ import { EditorCommand } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
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 } from 'vs/editor/contrib/wordOperations/wordOperations';
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';
suite('WordOperations', () => {
@@ -26,6 +26,10 @@ suite('WordOperations', () => {
const _cursorWordStartRightSelect = new CursorWordStartRightSelect();
const _cursorWordEndRightSelect = new CursorWordEndRightSelect();
const _cursorWordRightSelect = new CursorWordRightSelect();
const _cursorWordAccessibilityLeft = new CursorWordAccessibilityLeft();
const _cursorWordAccessibilityLeftSelect = new CursorWordAccessibilityLeftSelect();
const _cursorWordAccessibilityRight = new CursorWordAccessibilityRight();
const _cursorWordAccessibilityRightSelect = new CursorWordAccessibilityRightSelect();
const _deleteWordLeft = new DeleteWordLeft();
const _deleteWordStartLeft = new DeleteWordStartLeft();
const _deleteWordEndLeft = new DeleteWordEndLeft();
@@ -39,6 +43,12 @@ suite('WordOperations', () => {
function cursorWordLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void {
runEditorCommand(editor, inSelectionMode ? _cursorWordLeftSelect : _cursorWordLeft);
}
function cursorWordAccessibilityLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void {
runEditorCommand(editor, inSelectionMode ? _cursorWordAccessibilityLeft : _cursorWordAccessibilityLeftSelect);
}
function cursorWordAccessibilityRight(editor: ICodeEditor, inSelectionMode: boolean = false): void {
runEditorCommand(editor, inSelectionMode ? _cursorWordAccessibilityRightSelect : _cursorWordAccessibilityRight);
}
function cursorWordStartLeft(editor: ICodeEditor, inSelectionMode: boolean = false): void {
runEditorCommand(editor, inSelectionMode ? _cursorWordStartLeftSelect : _cursorWordStartLeft);
}
@@ -326,6 +336,34 @@ suite('WordOperations', () => {
assert.deepEqual(actual, EXPECTED);
});
test('cursorWordAccessibilityLeft', () => {
const EXPECTED = ['| /* |Just |some |more |text |a+= |3 +|5-|3 + |7 */ '].join('\n');
const [text,] = deserializePipePositions(EXPECTED);
const actualStops = testRepeatedActionAndExtractPositions(
text,
new Position(1000, 1000),
ed => cursorWordAccessibilityLeft(ed),
ed => ed.getPosition()!,
ed => ed.getPosition()!.equals(new Position(1, 1))
);
const actual = serializePipePositions(text, actualStops);
assert.deepEqual(actual, EXPECTED);
});
test('cursorWordAccessibilityRight', () => {
const EXPECTED = [' /* Just| some| more| text| a|+= 3| +5|-3| + 7| */ |'].join('\n');
const [text,] = deserializePipePositions(EXPECTED);
const actualStops = testRepeatedActionAndExtractPositions(
text,
new Position(1, 1),
ed => cursorWordAccessibilityRight(ed),
ed => ed.getPosition()!,
ed => ed.getPosition()!.equals(new Position(1, 50))
);
const actual = serializePipePositions(text, actualStops);
assert.deepEqual(actual, EXPECTED);
});
test('deleteWordLeft for non-empty selection', () => {
withTestCodeEditor([
' \tMy First Line\t ',
@@ -18,6 +18,9 @@ import { ScrollType } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ITextModel } from 'vs/editor/common/model';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { EDITOR_DEFAULTS } from 'vs/editor/common/config/editorOptions';
export interface MoveWordOptions extends ICommandOptions {
inSelectionMode: boolean;
@@ -170,6 +173,48 @@ export class CursorWordLeftSelect extends WordLeftCommand {
}
}
export class CursorWordAccessibilityLeft extends WordLeftCommand {
constructor() {
super({
inSelectionMode: false,
wordNavigationType: WordNavigationType.WordAccessibility,
id: 'cursorWordAccessibilityLeft',
precondition: undefined,
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
primary: KeyMod.CtrlCmd | KeyCode.LeftArrow,
mac: { primary: KeyMod.Alt | KeyCode.LeftArrow },
weight: KeybindingWeight.EditorContrib + 1
}
});
}
protected _move(_: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
return super._move(getMapForWordSeparators(EDITOR_DEFAULTS.wordSeparators), model, position, wordNavigationType);
}
}
export class CursorWordAccessibilityLeftSelect extends WordLeftCommand {
constructor() {
super({
inSelectionMode: true,
wordNavigationType: WordNavigationType.WordAccessibility,
id: 'cursorWordAccessibilitLeftSelecty',
precondition: undefined,
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow,
mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow },
weight: KeybindingWeight.EditorContrib + 1
}
});
}
protected _move(_: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
return super._move(getMapForWordSeparators(EDITOR_DEFAULTS.wordSeparators), model, position, wordNavigationType);
}
}
export class CursorWordStartRight extends WordRightCommand {
constructor() {
super({
@@ -248,6 +293,48 @@ export class CursorWordRightSelect extends WordRightCommand {
}
}
export class CursorWordAccessibilityRight extends WordRightCommand {
constructor() {
super({
inSelectionMode: false,
wordNavigationType: WordNavigationType.WordAccessibility,
id: 'cursorWordAccessibilityRight',
precondition: undefined,
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
primary: KeyMod.CtrlCmd | KeyCode.RightArrow,
mac: { primary: KeyMod.Alt | KeyCode.RightArrow },
weight: KeybindingWeight.EditorContrib + 1
}
});
}
protected _move(_: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
return super._move(getMapForWordSeparators(EDITOR_DEFAULTS.wordSeparators), model, position, wordNavigationType);
}
}
export class CursorWordAccessibilityRightSelect extends WordRightCommand {
constructor() {
super({
inSelectionMode: true,
wordNavigationType: WordNavigationType.WordAccessibility,
id: 'cursorWordAccessibilityRightSelect',
precondition: undefined,
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow,
mac: { primary: KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow },
weight: KeybindingWeight.EditorContrib + 1
}
});
}
protected _move(_: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
return super._move(getMapForWordSeparators(EDITOR_DEFAULTS.wordSeparators), model, position, wordNavigationType);
}
}
export interface DeleteWordOptions extends ICommandOptions {
whitespaceHeuristics: boolean;
wordNavigationType: WordNavigationType;
@@ -397,6 +484,10 @@ registerEditorCommand(new CursorWordRight());
registerEditorCommand(new CursorWordStartRightSelect());
registerEditorCommand(new CursorWordEndRightSelect());
registerEditorCommand(new CursorWordRightSelect());
registerEditorCommand(new CursorWordAccessibilityLeft());
registerEditorCommand(new CursorWordAccessibilityLeftSelect());
registerEditorCommand(new CursorWordAccessibilityRight());
registerEditorCommand(new CursorWordAccessibilityRightSelect());
registerEditorCommand(new DeleteWordStartLeft());
registerEditorCommand(new DeleteWordEndLeft());
registerEditorCommand(new DeleteWordLeft());
@@ -4740,6 +4740,37 @@ suite('autoClosingPairs', () => {
mode.dispose();
});
test('issue #78833 - Add config to use old brackets/quotes overtyping', () => {
let mode = new AutoClosingMode();
usingCursor({
text: [
'',
'y=();'
],
languageIdentifier: mode.getLanguageIdentifier(),
editorOpts: {
autoClosingOvertype: 'always'
}
}, (model, cursor) => {
assertCursor(cursor, new Position(1, 1));
cursorCommand(cursor, H.Type, { text: 'x=(' }, 'keyboard');
assert.strictEqual(model.getLineContent(1), 'x=()');
cursorCommand(cursor, H.Type, { text: ')' }, 'keyboard');
assert.strictEqual(model.getLineContent(1), 'x=()');
cursor.setSelections('test', [new Selection(1, 4, 1, 4)]);
cursorCommand(cursor, H.Type, { text: ')' }, 'keyboard');
assert.strictEqual(model.getLineContent(1), 'x=()');
cursor.setSelections('test', [new Selection(2, 4, 2, 4)]);
cursorCommand(cursor, H.Type, { text: ')' }, 'keyboard');
assert.strictEqual(model.getLineContent(2), 'y=();');
});
mode.dispose();
});
test('issue #15825: accents on mac US intl keyboard', () => {
let mode = new AutoClosingMode();
usingCursor({
@@ -109,9 +109,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
[
'<div>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">Ciao</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #0000ff;text-decoration: underline;">world!</span>',
'</div>'
].join('')
@@ -122,9 +122,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
[
'<div>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">Ciao</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #0000ff;text-decoration: underline;">w</span>',
'</div>'
].join('')
@@ -135,9 +135,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
[
'<div>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">Ciao</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'</div>'
].join('')
);
@@ -147,9 +147,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
[
'<div>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">iao</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'</div>'
].join('')
);
@@ -158,9 +158,9 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
tokenizeLineToHTML(text, lineTokens, colorMap, 4, 11, 4),
[
'<div>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'</div>'
].join('')
);
@@ -170,7 +170,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
[
'<div>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'</div>'
].join('')
);
@@ -241,11 +241,11 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
tokenizeLineToHTML(text, lineTokens, colorMap, 0, 21, 4),
[
'<div>',
'<span style="color: #000000;">&nbsp&nbsp</span>',
'<span style="color: #000000;">&nbsp;&nbsp;</span>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">Ciao</span>',
'<span style="color: #000000;">&nbsp&nbsp&nbsp</span>',
'<span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #0000ff;text-decoration: underline;">world!</span>',
'</div>'
].join('')
@@ -255,11 +255,11 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
tokenizeLineToHTML(text, lineTokens, colorMap, 0, 17, 4),
[
'<div>',
'<span style="color: #000000;">&nbsp&nbsp</span>',
'<span style="color: #000000;">&nbsp;&nbsp;</span>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">Ciao</span>',
'<span style="color: #000000;">&nbsp&nbsp&nbsp</span>',
'<span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span>',
'<span style="color: #00ff00;">hello</span>',
'<span style="color: #000000;">&nbsp</span>',
'<span style="color: #000000;">&nbsp;</span>',
'<span style="color: #0000ff;text-decoration: underline;">wo</span>',
'</div>'
].join('')
@@ -269,7 +269,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
tokenizeLineToHTML(text, lineTokens, colorMap, 0, 3, 4),
[
'<div>',
'<span style="color: #000000;">&nbsp&nbsp</span>',
'<span style="color: #000000;">&nbsp;&nbsp;</span>',
'<span style="color: #ff0000;font-style: italic;font-weight: bold;">C</span>',
'</div>'
].join('')
+11
View File
@@ -2494,6 +2494,11 @@ declare namespace monaco.editor {
*/
export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'brackets' | 'never';
/**
* Configuration options for typing over closing quotes or brackets
*/
export type EditorAutoClosingOvertypeStrategy = 'always' | 'auto' | 'never';
/**
* Configuration options for editor minimap
*/
@@ -2922,6 +2927,10 @@ declare namespace monaco.editor {
* Defaults to language defined behavior.
*/
autoClosingQuotes?: EditorAutoClosingStrategy;
/**
* Options for typing over closing quotes or brackets.
*/
autoClosingOvertype?: EditorAutoClosingOvertypeStrategy;
/**
* Options for auto surrounding.
* Defaults to always allowing auto surrounding.
@@ -3389,6 +3398,7 @@ declare namespace monaco.editor {
readonly wordSeparators: string;
readonly autoClosingBrackets: EditorAutoClosingStrategy;
readonly autoClosingQuotes: EditorAutoClosingStrategy;
readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
readonly autoSurround: EditorAutoSurroundStrategy;
readonly autoIndent: boolean;
readonly useTabStops: boolean;
@@ -3530,6 +3540,7 @@ declare namespace monaco.editor {
readonly wordSeparators: boolean;
readonly autoClosingBrackets: boolean;
readonly autoClosingQuotes: boolean;
readonly autoClosingOvertype: boolean;
readonly autoSurround: boolean;
readonly autoIndent: boolean;
readonly useTabStops: boolean;
@@ -14,14 +14,18 @@ import { attachDialogStyler } from 'vs/platform/theme/common/styler';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { EventHelper } from 'vs/base/browser/dom';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
export class DialogService implements IDialogService {
_serviceBrand: any;
private allowableCommands = ['copy', 'cut'];
constructor(
@ILogService private readonly logService: ILogService,
@ILayoutService private readonly layoutService: ILayoutService,
@IThemeService private readonly themeService: IThemeService
@IThemeService private readonly themeService: IThemeService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) { }
async confirm(confirmation: IConfirmation): Promise<IConfirmationResult> {
@@ -50,7 +54,12 @@ export class DialogService implements IDialogService {
cancelId: 1,
type: confirmation.type,
keyEventProcessor: (event: StandardKeyboardEvent) => {
EventHelper.stop(event, true);
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
if (resolved && resolved.commandId) {
if (this.allowableCommands.indexOf(resolved.commandId) === -1) {
EventHelper.stop(event, true);
}
}
},
checkboxChecked: confirmation.checkbox ? confirmation.checkbox.checked : undefined,
checkboxLabel: confirmation.checkbox ? confirmation.checkbox.label : undefined
@@ -82,7 +91,12 @@ export class DialogService implements IDialogService {
cancelId: options ? options.cancelId : undefined,
type: this.getDialogType(severity),
keyEventProcessor: (event: StandardKeyboardEvent) => {
EventHelper.stop(event, true);
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
if (resolved && resolved.commandId) {
if (this.allowableCommands.indexOf(resolved.commandId) === -1) {
EventHelper.stop(event, true);
}
}
}
});
+33 -3
View File
@@ -79,14 +79,41 @@ export interface IResourceInput extends IBaseResourceInput {
readonly mode?: string;
}
export enum EditorActivation {
/**
* Activate the editor after it opened.
*/
ACTIVATE,
/**
* Preserve the current active editor.
*
* Note: will only work in combination with the
* `preserveFocus: true` option.
*/
PRESERVE
}
export interface IEditorOptions {
/**
* Tells the editor to not receive keyboard focus when the editor is being opened. By default,
* the editor will receive keyboard focus on open.
* Tells the editor to not receive keyboard focus when the editor is being opened.
*
* Will also not activate the group the editor opens in unless the group is already
* the active one. This behaviour can be overridden via the `activation` option.
*/
readonly preserveFocus?: boolean;
/**
* This option is only relevant if an editor is opened into a group that is not active
* already and allows to control if the inactive group should become active or not.
*
* By default, the editor group will become active unless `preserveFocus` or `inactive`
* is specified.
*/
readonly activation?: EditorActivation;
/**
* Tells the editor to reload the editor input in the editor even if it is identical to the one
* already showing. By default, the editor will not reload the input if it is identical to the
@@ -123,7 +150,10 @@ export interface IEditorOptions {
/**
* An active editor that is opened will show its contents directly. Set to true to open an editor
* in the background.
* in the background without loading its contents.
*
* Will also not activate the group the editor opens in unless the group is already
* the active one. This behaviour can be overridden via the `activation` option.
*/
readonly inactive?: boolean;
@@ -148,24 +148,15 @@ export interface IEnvironmentService {
extensionTestsLocationURI?: URI;
debugExtensionHost: IExtensionHostDebugParams;
debugSearch: IDebugParams;
logExtensionHostCommunication: boolean;
isBuilt: boolean;
wait: boolean;
status: boolean;
// logging
log?: string;
logsPath: string;
verbose: boolean;
skipGettingStarted: boolean | undefined;
skipReleaseNotes: boolean | undefined;
skipAddToRecentlyOpened: boolean;
mainIPCHandle: string;
sharedIPCHandle: string;
@@ -178,9 +169,5 @@ export interface IEnvironmentService {
driverHandle?: string;
driverVerbose: boolean;
webviewEndpoint?: string;
readonly webviewResourceRoot: string;
readonly webviewCspSource: string;
readonly galleryMachineIdResource?: URI;
galleryMachineIdResource?: URI;
}
@@ -236,26 +236,15 @@ export class EnvironmentService implements IEnvironmentService {
return false;
}
get skipGettingStarted(): boolean { return !!this._args['skip-getting-started']; }
get skipReleaseNotes(): boolean { return !!this._args['skip-release-notes']; }
get skipAddToRecentlyOpened(): boolean { return !!this._args['skip-add-to-recently-opened']; }
@memoize
get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostPort(this._args, this.isBuilt); }
@memoize
get debugSearch(): IDebugParams { return parseSearchPort(this._args, this.isBuilt); }
get isBuilt(): boolean { return !process.env['VSCODE_DEV']; }
get verbose(): boolean { return !!this._args.verbose; }
get log(): string | undefined { return this._args.log; }
get wait(): boolean { return !!this._args.wait; }
get logExtensionHostCommunication(): boolean { return !!this._args.logExtensionHostCommunication; }
get status(): boolean { return !!this._args.status; }
@memoize
@@ -276,9 +265,6 @@ export class EnvironmentService implements IEnvironmentService {
get driverHandle(): string | undefined { return this._args['driver']; }
get driverVerbose(): boolean { return !!this._args['driver-verbose']; }
readonly webviewResourceRoot = 'vscode-resource:{{resource}}';
readonly webviewCspSource = 'vscode-resource:';
constructor(private _args: ParsedArgs, private _execPath: string) {
if (!process.env['VSCODE_LOGS']) {
const key = toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '');
@@ -9,7 +9,8 @@ import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGallery
import { assign, getOrDefault } from 'vs/base/common/objects';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IPager } from 'vs/base/common/paging';
import { IRequestService, IRequestOptions, IRequestContext, asJson, asText, IHeaders } from 'vs/platform/request/common/request';
import { IRequestService, asJson, asText } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { generateUuid, isUUID } from 'vs/base/common/uuid';
@@ -3,13 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { assign } from 'vs/base/common/objects';
import { VSBuffer, bufferToStream } from 'vs/base/common/buffer';
import { request } from 'vs/base/parts/request/browser/request';
/**
* This service exposes the `request` API, while using the global
@@ -28,69 +26,10 @@ export class RequestService {
request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
this.logService.trace('RequestService#request', options.url);
const authorization = this.configurationService.getValue<string>('http.proxyAuthorization');
if (authorization) {
options.headers = assign(options.headers || {}, { 'Proxy-Authorization': authorization });
if (!options.proxyAuthorization) {
options.proxyAuthorization = this.configurationService.getValue<string>('http.proxyAuthorization');
}
const xhr = new XMLHttpRequest();
return new Promise<IRequestContext>((resolve, reject) => {
xhr.open(options.type || 'GET', options.url || '', true, options.user, options.password);
this.setRequestHeaders(xhr, options);
xhr.responseType = 'arraybuffer';
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText)));
xhr.onload = (e) => {
resolve({
res: {
statusCode: xhr.status,
headers: this.getResponseHeaders(xhr)
},
stream: bufferToStream(VSBuffer.wrap(new Uint8Array(xhr.response)))
});
};
xhr.ontimeout = e => reject(new Error(`XHR timeout: ${options.timeout}ms`));
if (options.timeout) {
xhr.timeout = options.timeout;
}
xhr.send(options.data);
// cancel
token.onCancellationRequested(() => {
xhr.abort();
reject(canceled());
});
});
return request(options, token);
}
private setRequestHeaders(xhr: XMLHttpRequest, options: IRequestOptions): void {
if (options.headers) {
outer: for (let k in options.headers) {
switch (k) {
case 'User-Agent':
case 'Accept-Encoding':
case 'Content-Length':
// unsafe headers
continue outer;
}
xhr.setRequestHeader(k, options.headers[k]);
}
}
}
private getResponseHeaders(xhr: XMLHttpRequest): { [name: string]: string } {
const headers: { [name: string]: string } = Object.create(null);
for (const line of xhr.getAllResponseHeaders().split(/\r\n|\n|\r/g)) {
if (line) {
const idx = line.indexOf(':');
headers[line.substr(0, idx).trim().toLowerCase()] = line.substr(idx + 1).trim();
}
}
return headers;
}
}
}
+2 -24
View File
@@ -8,33 +8,11 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { VSBufferReadableStream, streamToBuffer } from 'vs/base/common/buffer';
import { streamToBuffer } from 'vs/base/common/buffer';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
export const IRequestService = createDecorator<IRequestService>('requestService');
export interface IHeaders {
[header: string]: string;
}
export interface IRequestOptions {
type?: string;
url?: string;
user?: string;
password?: string;
headers?: IHeaders;
timeout?: number;
data?: string;
followRedirects?: number;
}
export interface IRequestContext {
res: {
headers: IHeaders;
statusCode?: number;
};
stream: VSBufferReadableStream;
}
export interface IRequestService {
_serviceBrand: any;
+2 -1
View File
@@ -5,7 +5,8 @@
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { IRequestService, IRequestOptions, IRequestContext, IHeaders } from 'vs/platform/request/common/request';
import { IRequestService } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { VSBuffer, bufferToStream, streamToBuffer } from 'vs/base/common/buffer';
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { RequestService as NodeRequestService, IRawRequestFunction } from 'vs/platform/request/node/requestService';
import { assign } from 'vs/base/common/objects';
import { net } from 'electron';
@@ -13,7 +13,8 @@ import { assign } from 'vs/base/common/objects';
import { isBoolean, isNumber } from 'vs/base/common/types';
import { canceled } from 'vs/base/common/errors';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IRequestOptions, IRequestContext, IRequestService, IHTTPConfiguration } from 'vs/platform/request/common/request';
import { IRequestService, IHTTPConfiguration } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { getProxyAgent, Agent } from 'vs/platform/request/node/proxy';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
@@ -5,6 +5,7 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { isWeb } from 'vs/base/common/platform';
import { startsWith } from 'vs/base/common/strings';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
@@ -314,7 +315,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
if (MainThreadWebviews.standardSupportedLinkSchemes.has(link.scheme)) {
return true;
}
if (this._productService.urlProtocol === link.scheme) {
if (!isWeb && this._productService.urlProtocol === link.scheme) {
return true;
}
return !!webview.webview.contentOptions.enableCommandUris && link.scheme === 'command';
+2 -1
View File
@@ -1239,7 +1239,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const editorNode: ISerializedLeafNode = {
type: 'leaf',
data: { type: Parts.EDITOR_PART },
size: this.state.panel.position === Position.BOTTOM ? middleSectionHeight - (this.state.panel.hidden ? 0 : panelSize) : editorSectionWidth - (this.state.panel.hidden ? 0 : panelSize)
size: this.state.panel.position === Position.BOTTOM ? middleSectionHeight - (this.state.panel.hidden ? 0 : panelSize) : editorSectionWidth - (this.state.panel.hidden ? 0 : panelSize),
visible: true
};
const panelNode: ISerializedLeafNode = {
@@ -447,7 +447,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_RIGHT, title: nls.localize('splitRight', "Split Right") }, group: '5_split', order: 40 });
// Editor Title Menu
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.TOGGLE_DIFF_SIDE_BY_SIDE, title: nls.localize('toggleSideBySideView', "Toggle Side By Side View") }, group: '1_diff', order: 10, when: ContextKeyExpr.has('isInDiffEditor') });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.TOGGLE_DIFF_SIDE_BY_SIDE, title: nls.localize('toggleInlineView', "Toggle Inline View") }, group: '1_diff', order: 10, when: ContextKeyExpr.has('isInDiffEditor') });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.SHOW_EDITORS_IN_GROUP, title: nls.localize('showOpenedEditors', "Show Opened Editors") }, group: '3_open', order: 10, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '5_close', order: 10, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
@@ -94,6 +94,7 @@ export interface IEditorGroupsAccessor {
getGroups(order: GroupsOrder): IEditorGroupView[];
activateGroup(identifier: IEditorGroupView | GroupIdentifier): IEditorGroupView;
restoreGroup(identifier: IEditorGroupView | GroupIdentifier): IEditorGroupView;
addGroup(location: IEditorGroupView | GroupIdentifier, direction: GroupDirection, options?: IAddGroupOptions): IEditorGroupView;
mergeGroup(group: IEditorGroupView | GroupIdentifier, target: IEditorGroupView | GroupIdentifier, options?: IMergeGroupOptions): IEditorGroupView;
@@ -618,12 +618,24 @@ export abstract class BaseCloseAllAction extends Action {
async run(): Promise<any> {
// Just close all if there are no or one dirty editor
if (this.textFileService.getDirty().length < 2) {
// Just close all if there are no dirty editors
if (!this.textFileService.isDirty()) {
return this.doCloseAll();
}
// Otherwise ask for combined confirmation
// Otherwise ask for combined confirmation and make sure
// to bring each dirty editor to the front so that the user
// can review if the files should be changed or not.
await Promise.all(this.groupsToClose.map(async groupToClose => {
for (const editor of groupToClose.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) {
if (editor.isDirty()) {
return groupToClose.openEditor(editor);
}
}
return undefined;
}));
const confirm = await this.textFileService.confirmSave();
if (confirm === ConfirmResult.CANCEL) {
return;
@@ -112,7 +112,7 @@ export class EditorControl extends Disposable {
if (!control.getContainer()) {
const controlInstanceContainer = document.createElement('div');
addClass(controlInstanceContainer, 'editor-instance');
controlInstanceContainer.id = descriptor.getId();
controlInstanceContainer.setAttribute('data-editor-id', descriptor.getId());
control.create(controlInstanceContainer);
}
@@ -53,6 +53,7 @@ import { hash } from 'vs/base/common/hash';
import { guessMimeTypes } from 'vs/base/common/mime';
import { extname } from 'vs/base/common/resources';
import { Schemas } from 'vs/base/common/network';
import { EditorActivation } from 'vs/platform/editor/common/editor';
export class EditorGroupView extends Themable implements IEditorGroupView {
@@ -489,7 +490,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private onDidEditorOpen(editor: EditorInput): void {
// Telemetry
/* __GDPR__
"editorOpened" : {
"${include}": [
@@ -528,14 +528,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
});
// Telemetry
/* __GDPR__
"editorClosed" : {
"${include}": [
"${EditorTelemetryDescriptor}"
]
}
*/
"editorClosed" : {
"${include}": [
"${EditorTelemetryDescriptor}"
]
}
*/
this.telemetryService.publicLog('editorClosed', this.toEditorTelemetryDescriptor(event.editor));
// Update container
@@ -841,12 +840,31 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
openEditorOptions.active = true;
}
// Set group active unless we open inactive or preserve focus
let activateGroup = false;
let restoreGroup = false;
if (options && options.activation === EditorActivation.ACTIVATE) {
// Respect option to force activate an editor group.
activateGroup = true;
} else if (options && options.activation === EditorActivation.PRESERVE) {
// Respect option to preserve active editor group.
activateGroup = false;
} else if (openEditorOptions.active) {
// Finally, we only activate/restore an editor which is
// opening as active editor.
// If preserveFocus is enabled, we only restore but never
// activate the group.
activateGroup = !options || !options.preserveFocus;
restoreGroup = !activateGroup;
}
// Do this before we open the editor in the group to prevent a false
// active editor change event before the editor is loaded
// (see https://github.com/Microsoft/vscode/issues/51679)
if (openEditorOptions.active && (!options || !options.preserveFocus)) {
if (activateGroup) {
this.accessor.activateGroup(this);
} else if (restoreGroup) {
this.accessor.restoreGroup(this);
}
// Actually move the editor if a specific index is provided and we figure
@@ -325,6 +325,13 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
return groupView;
}
restoreGroup(group: IEditorGroupView | GroupIdentifier): IEditorGroupView {
const groupView = this.assertGroupView(group);
this.doRestoreGroup(groupView);
return groupView;
}
getSize(group: IEditorGroupView | GroupIdentifier): { width: number, height: number } {
const groupView = this.assertGroupView(group);
@@ -337,7 +344,7 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
this.gridWidget.resizeView(groupView, size);
}
arrangeGroups(arrangement: GroupsArrangement): void {
arrangeGroups(arrangement: GroupsArrangement, target = this.activeGroup): void {
if (this.count < 2) {
return; // require at least 2 groups to show
}
@@ -351,10 +358,10 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
this.gridWidget.distributeViewSizes();
break;
case GroupsArrangement.MINIMIZE_OTHERS:
this.gridWidget.maximizeViewSize(this.activeGroup);
this.gridWidget.maximizeViewSize(target);
break;
case GroupsArrangement.TOGGLE:
if (this.isGroupMaximized(this.activeGroup)) {
if (this.isGroupMaximized(target)) {
this.arrangeGroups(GroupsArrangement.EVEN);
} else {
this.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
@@ -576,17 +583,21 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
group.setActive(true);
// Maximize the group if it is currently minimized
if (this.gridWidget) {
const viewSize = this.gridWidget.getViewSize(group);
if (viewSize.width === group.minimumWidth || viewSize.height === group.minimumHeight) {
this.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
}
}
this.doRestoreGroup(group);
// Event
this._onDidActiveGroupChange.fire(group);
}
private doRestoreGroup(group: IEditorGroupView): void {
if (this.gridWidget) {
const viewSize = this.gridWidget.getViewSize(group);
if (viewSize.width === group.minimumWidth || viewSize.height === group.minimumHeight) {
this.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS, group);
}
}
}
private doUpdateMostRecentActive(group: IEditorGroupView, makeMostRecentlyActive?: boolean): void {
const index = this.mostRecentActiveGroups.indexOf(group.id);
@@ -31,6 +31,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { CancellationToken } from 'vs/base/common/cancellation';
import { EditorMemento } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { EditorActivation } from 'vs/platform/editor/common/editor';
/**
* The text editor that leverages the diff text editor for the editing experience.
@@ -184,6 +185,12 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
modifiedInput.setForceOpenAsBinary();
}
// Make sure to not steal away the currently active group
// because we are triggering another openEditor() call
// and do not control the initial intent that resulted
// in us now opening as binary.
options.overwrite({ activation: EditorActivation.PRESERVE });
this.editorService.openEditor(binaryDiffInput, options, this.group);
return true;
+52 -46
View File
@@ -18,7 +18,7 @@ import { RemoteAgentService } from 'vs/workbench/services/remote/browser/remoteA
import { RemoteAuthorityResolverService } from 'vs/platform/remote/browser/remoteAuthorityResolverService';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IFileService, IFileSystemProvider } from 'vs/platform/files/common/files';
import { IFileService } from 'vs/platform/files/common/files';
import { FileService } from 'vs/platform/files/common/fileService';
import { Schemas } from 'vs/base/common/network';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
@@ -124,7 +124,7 @@ class CodeRendererMain extends Disposable {
const logService = new BufferLogService();
serviceCollection.set(ILogService, logService);
const payload = await this.resolveWorkspaceInitializationPayload();
const payload = this.resolveWorkspaceInitializationPayload();
// Environment
const environmentService = new BrowserWorkbenchEnvironmentService({ workspaceId: payload.id, logsPath, ...this.configuration });
@@ -149,46 +149,7 @@ class CodeRendererMain extends Disposable {
// Files
const fileService = this._register(new FileService(logService));
serviceCollection.set(IFileService, fileService);
// Logger
const indexedDBLogProvider = new IndexedDBLogProvider(logsPath.scheme);
(async () => {
try {
await indexedDBLogProvider.database;
fileService.registerProvider(logsPath.scheme, indexedDBLogProvider);
} catch (error) {
(<ILogService>logService).info('Error while creating indexedDB log provider. Falling back to in-memory log provider.');
(<ILogService>logService).error(error);
fileService.registerProvider(logsPath.scheme, new InMemoryLogProvider(logsPath.scheme));
}
const consoleLogService = new ConsoleLogService(logService.getLevel());
const fileLogService = new FileLogService('window', environmentService.logFile, logService.getLevel(), fileService);
logService.logger = new MultiplexLogService([consoleLogService, fileLogService]);
})();
// User Data Provider
let userDataProvider: IFileSystemProvider | undefined = this.configuration.userDataProvider;
const connection = remoteAgentService.getConnection();
if (connection) {
const channel = connection.getChannel<IChannel>(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
const remoteFileSystemProvider = this._register(new RemoteExtensionsFileSystemProvider(channel, remoteAgentService.getEnvironment()));
fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider);
if (!userDataProvider) {
const remoteUserDataUri = this.getRemoteUserDataUri();
if (remoteUserDataUri) {
userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService));
}
}
}
if (!userDataProvider) {
userDataProvider = this._register(new InMemoryUserDataProvider());
}
fileService.registerProvider(Schemas.userData, userDataProvider);
this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, logService, logsPath);
// Long running services (workspace, config, storage)
const services = await Promise.all([
@@ -215,15 +176,59 @@ class CodeRendererMain extends Disposable {
return { serviceCollection, logService, storageService: services[1] };
}
private registerFileSystemProviders(environmentService: IWorkbenchEnvironmentService, fileService: IFileService, remoteAgentService: IRemoteAgentService, logService: BufferLogService, logsPath: URI): void {
// Logger
const indexedDBLogProvider = new IndexedDBLogProvider(logsPath.scheme);
(async () => {
try {
await indexedDBLogProvider.database;
fileService.registerProvider(logsPath.scheme, indexedDBLogProvider);
} catch (error) {
(<ILogService>logService).info('Error while creating indexedDB log provider. Falling back to in-memory log provider.');
(<ILogService>logService).error(error);
fileService.registerProvider(logsPath.scheme, new InMemoryLogProvider(logsPath.scheme));
}
const consoleLogService = new ConsoleLogService(logService.getLevel());
const fileLogService = new FileLogService('window', environmentService.logFile, logService.getLevel(), fileService);
logService.logger = new MultiplexLogService([consoleLogService, fileLogService]);
})();
const connection = remoteAgentService.getConnection();
if (connection) {
// Remote file system
const channel = connection.getChannel<IChannel>(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
const remoteFileSystemProvider = this._register(new RemoteExtensionsFileSystemProvider(channel, remoteAgentService.getEnvironment()));
fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider);
if (!this.configuration.userDataProvider) {
const remoteUserDataUri = this.getRemoteUserDataUri();
if (remoteUserDataUri) {
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService));
}
}
}
// User data
if (!this.configuration.userDataProvider) {
this.configuration.userDataProvider = this._register(new InMemoryUserDataProvider());
}
fileService.registerProvider(Schemas.userData, this.configuration.userDataProvider);
}
private createProductService(): IProductService {
const element = document.getElementById('vscode-remote-product-configuration');
const productConfiguration: IProductConfiguration = {
...element ? JSON.parse(element.getAttribute('data-settings')!) : {
const productConfiguration = {
...this.configuration.productConfiguration ? this.configuration.productConfiguration : {
version: '1.38.0-unknown',
nameLong: 'Unknown',
extensionAllowedProposedApi: [],
}, ...{ urlProtocol: '' }
};
} as IProductConfiguration;
return { _serviceBrand: undefined, ...productConfiguration };
}
@@ -280,6 +285,7 @@ class CodeRendererMain extends Disposable {
return joinPath(URI.revive(JSON.parse(remoteUserDataPath)), 'User');
}
}
return null;
}
}
@@ -242,7 +242,7 @@ import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform'
},
'workbench.octiconsUpdate.enabled': {
'type': 'boolean',
'default': true,
'default': false,
'description': nls.localize('workbench.octiconsUpdate.enabled', "Controls the visibility of the new Octicons style in the workbench.")
}
}
+77 -50
View File
@@ -9,7 +9,7 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { IEditor as ICodeEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon';
import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput, IResourceInput } from 'vs/platform/editor/common/editor';
import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput, IResourceInput, EditorActivation } from 'vs/platform/editor/common/editor';
import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -718,25 +718,28 @@ export class EditorOptions implements IEditorOptions {
*/
static create(settings: IEditorOptions): EditorOptions {
const options = new EditorOptions();
options.preserveFocus = settings.preserveFocus;
options.forceReload = settings.forceReload;
options.revealIfVisible = settings.revealIfVisible;
options.revealIfOpened = settings.revealIfOpened;
options.pinned = settings.pinned;
options.index = settings.index;
options.inactive = settings.inactive;
options.ignoreError = settings.ignoreError;
options.overwrite(settings);
return options;
}
/**
* Tells the editor to not receive keyboard focus when the editor is being opened. By default,
* the editor will receive keyboard focus on open.
* Tells the editor to not receive keyboard focus when the editor is being opened.
*
* Will also not activate the group the editor opens in unless the group is already
* the active one. This behaviour can be overridden via the `activation` option.
*/
preserveFocus: boolean | undefined;
/**
* This option is only relevant if an editor is opened into a group that is not active
* already and allows to control if the inactive group should become active or not.
*
* By default, the editor group will become active unless `preserveFocus` or `inactive`
* is specified.
*/
activation: EditorActivation | undefined;
/**
* Tells the editor to reload the editor input in the editor even if it is identical to the one
* already showing. By default, the editor will not reload the input if it is identical to the
@@ -767,7 +770,10 @@ export class EditorOptions implements IEditorOptions {
/**
* An active editor that is opened will show its contents directly. Set to true to open an editor
* in the background.
* in the background without loading its contents.
*
* Will also not activate the group the editor opens in unless the group is already
* the active one. This behaviour can be overridden via the `activation` option.
*/
inactive: boolean | undefined;
@@ -776,6 +782,49 @@ export class EditorOptions implements IEditorOptions {
* message as needed. By default, an error will be presented as notification if opening was not possible.
*/
ignoreError: boolean | undefined;
/**
* Overwrites option values from the provided bag.
*/
overwrite(options: IEditorOptions): EditorOptions {
if (typeof options.forceReload === 'boolean') {
this.forceReload = options.forceReload;
}
if (typeof options.revealIfVisible === 'boolean') {
this.revealIfVisible = options.revealIfVisible;
}
if (typeof options.revealIfOpened === 'boolean') {
this.revealIfOpened = options.revealIfOpened;
}
if (typeof options.preserveFocus === 'boolean') {
this.preserveFocus = options.preserveFocus;
}
if (typeof options.activation === 'number') {
this.activation = options.activation;
}
if (typeof options.pinned === 'boolean') {
this.pinned = options.pinned;
}
if (typeof options.inactive === 'boolean') {
this.inactive = options.inactive;
}
if (typeof options.ignoreError === 'boolean') {
this.ignoreError = options.ignoreError;
}
if (typeof options.index === 'number') {
this.index = options.index;
}
return this;
}
}
/**
@@ -803,53 +852,31 @@ export class TextEditorOptions extends EditorOptions {
*/
static create(options: ITextEditorOptions = Object.create(null)): TextEditorOptions {
const textEditorOptions = new TextEditorOptions();
textEditorOptions.overwrite(options);
return textEditorOptions;
}
/**
* Overwrites option values from the provided bag.
*/
overwrite(options: ITextEditorOptions): TextEditorOptions {
super.overwrite(options);
if (options.selection) {
const selection = options.selection;
textEditorOptions.selection(selection.startLineNumber, selection.startColumn, selection.endLineNumber, selection.endColumn);
this.selection(selection.startLineNumber, selection.startColumn, selection.endLineNumber, selection.endColumn);
}
if (options.viewState) {
textEditorOptions.editorViewState = options.viewState as IEditorViewState;
this.editorViewState = options.viewState as IEditorViewState;
}
if (options.forceReload) {
textEditorOptions.forceReload = true;
if (typeof options.revealInCenterIfOutsideViewport === 'boolean') {
this.revealInCenterIfOutsideViewport = options.revealInCenterIfOutsideViewport;
}
if (options.revealIfVisible) {
textEditorOptions.revealIfVisible = true;
}
if (options.revealIfOpened) {
textEditorOptions.revealIfOpened = true;
}
if (options.preserveFocus) {
textEditorOptions.preserveFocus = true;
}
if (options.revealInCenterIfOutsideViewport) {
textEditorOptions.revealInCenterIfOutsideViewport = true;
}
if (options.pinned) {
textEditorOptions.pinned = true;
}
if (options.inactive) {
textEditorOptions.inactive = true;
}
if (options.ignoreError) {
textEditorOptions.ignoreError = true;
}
if (typeof options.index === 'number') {
textEditorOptions.index = options.index;
}
return textEditorOptions;
return this;
}
/**
@@ -768,7 +768,7 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
return (nameRows + 1) * rowHeight;
}
let valueRows = countNumberOfLines(value) + Math.floor(value.length / 150);
let valueRows = value ? (countNumberOfLines(value) + Math.floor(value.length / 150)) : 0;
return rowHeight * (nameRows + valueRows);
}
@@ -27,6 +27,7 @@ import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor
import { ResourceQueue, timeout } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import { withNullAsUndefined } from 'vs/base/common/types';
import { EditorActivation } from 'vs/platform/editor/common/editor';
// {{SQL CARBON EDIT}}
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
@@ -334,7 +335,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
// Binary editor that should reload from event
if (resource && editor.input && isBinaryEditor && (e.contains(resource, FileChangeType.UPDATED) || e.contains(resource, FileChangeType.ADDED))) {
this.editorService.openEditor(editor.input, { forceReload: true, preserveFocus: true }, editor.group);
this.editorService.openEditor(editor.input, { forceReload: true, preserveFocus: true, activation: EditorActivation.PRESERVE }, editor.group);
}
});
}
@@ -32,6 +32,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { MutableDisposable } from 'vs/base/common/lifecycle';
import { EditorActivation } from 'vs/platform/editor/common/editor';
/**
* An implementation of editor for file system resources.
@@ -225,6 +226,13 @@ export class TextFileEditor extends BaseTextEditor {
private openAsBinary(input: FileEditorInput, options: EditorOptions): void {
input.setForceOpenAsBinary();
// Make sure to not steal away the currently active group
// because we are triggering another openEditor() call
// and do not control the initial intent that resulted
// in us now opening as binary.
options.overwrite({ activation: EditorActivation.PRESERVE });
this.editorService.openEditor(input, options, this.group);
}
@@ -26,10 +26,9 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { DelegatingEditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorInput, IEditor } from 'vs/workbench/common/editor';
import { IEditor } from 'vs/workbench/common/editor';
import { ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
import { KeyChord, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -158,7 +157,6 @@ export class ExplorerViewlet extends ViewContainerViewlet {
@ITelemetryService telemetryService: ITelemetryService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IStorageService protected storageService: IStorageService,
@IEditorService private readonly editorService: IEditorService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService protected instantiationService: IInstantiationService,
@@ -187,7 +185,7 @@ export class ExplorerViewlet extends ViewContainerViewlet {
// We try to be smart and only use the delay if we recognize that the user action is likely to cause
// a new entry in the opened editors view.
const delegatingEditorService = this.instantiationService.createInstance(DelegatingEditorService);
delegatingEditorService.setEditorOpenHandler(async (group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise<IEditor | null> => {
delegatingEditorService.setEditorOpenHandler(async (delegate, group, editor, options): Promise<IEditor | null> => {
let openEditorsView = this.getOpenEditorsView();
if (openEditorsView) {
let delay = 0;
@@ -205,7 +203,7 @@ export class ExplorerViewlet extends ViewContainerViewlet {
let openedEditor: IEditor | undefined;
try {
openedEditor = await this.editorService.openEditor(editor, options, group);
openedEditor = await delegate(group, editor, options);
} catch (error) {
// ignore
} finally {
@@ -244,23 +244,23 @@ async function saveAll(saveAllArguments: any, editorService: IEditorService, unt
// Store some properties per untitled file to restore later after save is completed
const groupIdToUntitledResourceInput = new Map<number, IResourceInput[]>();
editorGroupService.groups.forEach(g => {
const activeEditorResource = g.activeEditor && g.activeEditor.getResource();
g.editors.forEach(e => {
editorGroupService.groups.forEach(group => {
const activeEditorResource = group.activeEditor && group.activeEditor.getResource();
group.editors.forEach(e => {
const resource = e.getResource();
if (resource && untitledEditorService.isDirty(resource)) {
if (!groupIdToUntitledResourceInput.has(g.id)) {
groupIdToUntitledResourceInput.set(g.id, []);
if (!groupIdToUntitledResourceInput.has(group.id)) {
groupIdToUntitledResourceInput.set(group.id, []);
}
groupIdToUntitledResourceInput.get(g.id)!.push({
groupIdToUntitledResourceInput.get(group.id)!.push({
encoding: untitledEditorService.getEncoding(resource),
resource,
options: {
inactive: activeEditorResource ? activeEditorResource.toString() !== resource.toString() : true,
pinned: true,
preserveFocus: true,
index: g.getIndexOfEditor(e)
index: group.getIndexOfEditor(e)
}
});
}
@@ -241,8 +241,7 @@ export class ExplorerView extends ViewletPanel {
const activeFile = this.getActiveFile();
if (!activeFile && !focused[0].isDirectory) {
// Open the focused element in the editor if there is currently no file opened #67708
this.editorService.openEditor({ resource: focused[0].resource, options: { preserveFocus: true, revealIfVisible: true } })
.then(undefined, onUnexpectedError);
this.editorService.openEditor({ resource: focused[0].resource, options: { preserveFocus: true, revealIfVisible: true } });
}
}
}
@@ -28,7 +28,7 @@ import { IListVirtualDelegate, IListRenderer, IListContextMenuEvent, IListDragAn
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions';
@@ -263,15 +263,21 @@ export class OpenEditorsView extends ViewletPanel {
let openToSide = false;
let isSingleClick = false;
let isDoubleClick = false;
let isMiddleClick = false;
if (browserEvent instanceof MouseEvent) {
isSingleClick = browserEvent.detail === 1;
isDoubleClick = browserEvent.detail === 2;
isMiddleClick = browserEvent.button === 1;
openToSide = this.list.useAltAsMultipleSelectionModifier ? (browserEvent.ctrlKey || browserEvent.metaKey) : browserEvent.altKey;
}
const focused = this.list.getFocusedElements();
const element = focused.length ? focused[0] : undefined;
if (element instanceof OpenEditor) {
if (isMiddleClick) {
return; // already handled above: closes the editor
}
this.openEditor(element, { preserveFocus: isSingleClick, pinned: isDoubleClick, sideBySide: openToSide });
} else if (element) {
this.editorGroupService.activateGroup(element);
@@ -349,13 +355,9 @@ export class OpenEditorsView extends ViewletPanel {
const preserveActivateGroup = options.sideBySide && options.preserveFocus; // needed for https://github.com/Microsoft/vscode/issues/42399
if (!preserveActivateGroup) {
this.editorGroupService.activateGroup(element.groupId); // needed for https://github.com/Microsoft/vscode/issues/6672
this.editorGroupService.activateGroup(element.group); // needed for https://github.com/Microsoft/vscode/issues/6672
}
this.editorService.openEditor(element.editor, options, options.sideBySide ? SIDE_GROUP : ACTIVE_GROUP).then(editor => {
if (editor && !preserveActivateGroup && editor.group) {
this.editorGroupService.activateGroup(editor.group);
}
});
this.editorService.openEditor(element.editor, options, options.sideBySide ? SIDE_GROUP : element.group);
}
}
@@ -15,7 +15,7 @@ import { URI } from 'vs/base/common/uri';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import * as arrays from 'vs/base/common/arrays';
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
export class DirtyFilesTracker extends Disposable implements IWorkbenchContribution {
private isDocumentedEdited: boolean;
@@ -88,7 +88,6 @@ export class DirtyFilesTracker extends Disposable implements IWorkbenchContribut
}
private doOpenDirtyResources(resources: URI[]): void {
const activeEditor = this.editorService.activeControl;
// Open
this.editorService.openEditors(resources.map(resource => {
@@ -96,7 +95,7 @@ export class DirtyFilesTracker extends Disposable implements IWorkbenchContribut
resource,
options: { inactive: true, pinned: true, preserveFocus: true }
};
}), activeEditor ? activeEditor.group : ACTIVE_GROUP);
}));
}
private onTextFilesSaved(e: TextFileModelChangeEvent[]): void {
@@ -46,6 +46,7 @@ import { attachStylerCallback, attachInputBoxStyler } from 'vs/platform/theme/co
import { IStorageService } from 'vs/platform/storage/common/storage';
import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { Emitter, Event } from 'vs/base/common/event';
import { MenuRegistry, MenuId, isIMenuItem } from 'vs/platform/actions/common/actions';
const $ = DOM.$;
@@ -489,11 +490,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
if (this.input) {
const input: KeybindingsEditorInput = this.input as KeybindingsEditorInput;
this.keybindingsEditorModel = await input.resolve();
const editorActionsLabels: Map<string, string> = EditorExtensionsRegistry.getEditorActions().reduce((editorActions, editorAction) => {
editorActions.set(editorAction.id, editorAction.label);
return editorActions;
}, new Map<string, string>());
await this.keybindingsEditorModel.resolve(editorActionsLabels);
await this.keybindingsEditorModel.resolve(this.getActionsLabels());
this.renderKeybindingsEntries(false, preserveFocus);
if (input.searchOptions) {
this.recordKeysAction.checked = input.searchOptions.recordKeybindings;
@@ -505,6 +502,19 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
}
}
private getActionsLabels(): Map<string, string> {
const actionsLabels: Map<string, string> = new Map<string, string>();
EditorExtensionsRegistry.getEditorActions().forEach(editorAction => actionsLabels.set(editorAction.id, editorAction.label));
for (const menuItem of MenuRegistry.getMenuItems(MenuId.CommandPalette)) {
if (isIMenuItem(menuItem)) {
const title = typeof menuItem.command.title === 'string' ? menuItem.command.title : menuItem.command.title.value;
const category = menuItem.command.category ? typeof menuItem.command.category === 'string' ? menuItem.command.category : menuItem.command.category.value : undefined;
actionsLabels.set(menuItem.command.id, category ? `${category}: ${title}` : title);
}
}
return actionsLabels;
}
private filterKeybindings(): void {
this.renderKeybindingsEntries(this.searchWidget.hasFocus());
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(this.searchWidget.getValue()));
@@ -716,7 +726,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
private createCopyCommandAction(keybinding: IKeybindingItemEntry): IAction {
return <IAction>{
label: localize('copyCommandLabel', "Copy Command"),
label: localize('copyCommandLabel', "Copy Command ID"),
enabled: true,
id: KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND,
run: () => this.copyKeybindingCommand(keybinding)
@@ -87,8 +87,10 @@ class GotoLineEntry extends EditorQuickOpenEntry {
private parseInput(line: string) {
const numbers = line.split(/,|:|#/).map(part => parseInt(part, 10)).filter(part => !isNaN(part));
this.line = numbers[0];
const endLine = this.getMaxLineNumber() + 1;
this.column = numbers[1];
this.line = numbers[0] > 0 ? numbers[0] : endLine + numbers[0];
}
getLabel(): string {
@@ -113,7 +115,7 @@ class GotoLineEntry extends EditorQuickOpenEntry {
}
private invalidRange(maxLineNumber: number = this.getMaxLineNumber()): boolean {
return !this.line || !types.isNumber(this.line) || (maxLineNumber > 0 && types.isNumber(this.line) && this.line > maxLineNumber);
return !this.line || !types.isNumber(this.line) || (maxLineNumber > 0 && types.isNumber(this.line) && this.line > maxLineNumber) || this.line < 0;
}
private getMaxLineNumber(): number {
@@ -17,7 +17,7 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
import { DocumentSymbolProviderRegistry, DocumentSymbol, symbolKindToCssClass, SymbolKind, SymbolTag } from 'vs/editor/common/modes';
import { IRange } from 'vs/editor/common/core/range';
import { IRange, Range } from 'vs/editor/common/core/range';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { overviewRulerRangeHighlight } from 'vs/editor/common/view/editorColorRegistry';
import { GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
@@ -88,7 +88,7 @@ class OutlineModel extends QuickOpenModel {
// Filter by search
if (searchValue.length > searchValuePos) {
const score = filters.fuzzyScore(
searchValue.substr(searchValuePos), searchValueLow.substr(searchValuePos), 0,
searchValue, searchValueLow, searchValuePos,
entry.getLabel(), entry.getLabel().toLowerCase(), 0,
true
);
@@ -219,7 +219,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
getOptions(pinned?: boolean): ITextEditorOptions {
return {
selection: this.revealRange,
selection: Range.collapseToStart(this.revealRange),
pinned
};
}
@@ -242,7 +242,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
// Apply selection and focus
else {
const range = this.revealRange;
const range = Range.collapseToStart(this.revealRange);
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
if (activeTextEditorWidget) {
activeTextEditorWidget.setSelection(range);
@@ -256,7 +256,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
private runPreview(): boolean {
// Select Outline Position
const range = this.revealRange;
const range = Range.collapseToStart(this.revealRange);
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
if (activeTextEditorWidget) {
activeTextEditorWidget.revealRangeInCenter(range, ScrollType.Smooth);
@@ -52,7 +52,6 @@ import { IReplaceService } from 'vs/workbench/contrib/search/common/replace';
import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search';
import { FileMatch, FileMatchOrMatch, FolderMatch, IChangeEvent, ISearchWorkbenchService, Match, RenderableMatch, searchMatchComparer, SearchModel, SearchResult, BaseFolderMatch } from 'vs/workbench/contrib/search/common/searchModel';
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { relativePath } from 'vs/base/common/resources';
@@ -148,7 +147,6 @@ export class SearchView extends ViewletPanel {
@IPreferencesService private readonly preferencesService: IPreferencesService,
@IThemeService protected themeService: IThemeService,
@ISearchHistoryService private readonly searchHistoryService: ISearchHistoryService,
@IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService,
@IContextMenuService contextMenuService: IContextMenuService,
@IMenuService private readonly menuService: IMenuService,
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
@@ -1570,10 +1568,6 @@ export class SearchView extends ViewletPanel {
} else {
this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange();
}
if (editor) {
this.editorGroupsService.activateGroup(editor.group!);
}
}, errors.onUnexpectedError);
}
@@ -98,7 +98,7 @@ const presentation: IJSONSchema = {
showReuseMessage: true,
clear: false,
},
description: nls.localize('JsonSchema.tasks.presentation', 'Configures the panel that is used to present the task\'s ouput and reads its input.'),
description: nls.localize('JsonSchema.tasks.presentation', 'Configures the panel that is used to present the task\'s output and reads its input.'),
additionalProperties: false,
properties: {
echo: {
@@ -17,6 +17,10 @@ import { Emitter, Event } from 'vs/base/common/event';
import { basename } from 'vs/base/common/path';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IProductService } from 'vs/platform/product/common/product';
const MINIMUM_FONT_SIZE = 6;
const MAXIMUM_FONT_SIZE = 25;
@@ -40,7 +44,10 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService,
@INotificationService private readonly _notificationService: INotificationService,
@IStorageService private readonly _storageService: IStorageService
@IStorageService private readonly _storageService: IStorageService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IProductService private readonly productService: IProductService
) {
this._updateConfig();
this._configurationService.onDidChangeConfiguration(e => {
@@ -263,18 +270,42 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper {
this.recommendationsShown = true;
if (platform.isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') {
if (! await this.isExtensionInstalled('ms-vscode-remote.remote-wsl')) {
const exeBasedExtensionTips = this.productService.exeBasedExtensionTips;
if (!exeBasedExtensionTips || !exeBasedExtensionTips.wsl) {
return;
}
const extId = exeBasedExtensionTips.wsl.recommendations[0];
if (extId && ! await this.isExtensionInstalled(extId)) {
this._notificationService.prompt(
Severity.Info,
nls.localize(
'useWslExtension.title',
"Check out the 'Visual Studio Code Remote - WSL' extension for a great development experience in WSL. Click [here]({0}) to learn more.",
'https://go.microsoft.com/fwlink/?linkid=2097212'
),
[],
'useWslExtension.title', "The '{0}' extension is recommended for opening a terminal in WSL.", exeBasedExtensionTips.wsl.friendlyName),
[
{
label: nls.localize('install', 'Install'),
run: () => {
/* __GDPR__
"terminalLaunchRecommendation:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'install', extId });
this.instantiationService.createInstance(InstallRecommendedExtensionAction, extId).run();
}
}
],
{
sticky: true,
neverShowAgain: { id: 'terminalConfigHelper/launchRecommendationsIgnore', scope: NeverShowAgainScope.WORKSPACE }
neverShowAgain: { id: 'terminalConfigHelper/launchRecommendationsIgnore', scope: NeverShowAgainScope.WORKSPACE },
onCancel: () => {
/* __GDPR__
"terminalLaunchRecommendation:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'cancelled' });
}
}
);
}
@@ -29,7 +29,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
const configurationService = new TestConfigurationService();
configurationService.setUserConfiguration('editor', { fontFamily: 'foo' });
configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } });
const configHelper = new TerminalConfigHelper(LinuxDistro.Fedora, configurationService, null!, null!, null!);
const configHelper = new TerminalConfigHelper(LinuxDistro.Fedora, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set');
});
@@ -38,7 +38,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
const configurationService = new TestConfigurationService();
configurationService.setUserConfiguration('editor', { fontFamily: 'foo' });
configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } });
const configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!);
const configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set');
});
@@ -47,7 +47,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
const configurationService = new TestConfigurationService();
configurationService.setUserConfiguration('editor', { fontFamily: 'foo' });
configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } });
const configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
const configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set');
});
@@ -65,7 +65,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontSize: 10
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize');
@@ -78,11 +78,11 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontSize: 0
}
});
configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it');
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it');
@@ -95,7 +95,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontSize: 1500
}
});
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it');
@@ -108,11 +108,11 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontSize: null
}
});
configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set');
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set');
});
@@ -130,7 +130,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
lineHeight: 2
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight');
@@ -144,7 +144,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
lineHeight: 0
}
});
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set');
});
@@ -157,7 +157,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced');
});
@@ -169,7 +169,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontFamily: 'sans-serif'
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
@@ -181,7 +181,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
fontFamily: 'serif'
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced');
});
@@ -197,7 +197,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced');
});
@@ -213,7 +213,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced');
});
@@ -229,7 +229,7 @@ suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} sk
}
});
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!);
let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!, null!, null!, null!);
configHelper.panelContainer = fixture;
assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced');
});
@@ -122,7 +122,7 @@ export class ProductContribution implements IWorkbenchContribution {
@IStorageService storageService: IStorageService,
@IInstantiationService instantiationService: IInstantiationService,
@INotificationService notificationService: INotificationService,
@IEnvironmentService environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IOpenerService openerService: IOpenerService,
@IConfigurationService configurationService: IConfigurationService,
@IWindowService windowService: IWindowService,
@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IFileService } from 'vs/platform/files/common/files';
import { Disposable } from 'vs/base/common/lifecycle';
import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewEditorService';
@@ -40,14 +40,14 @@ export class IFrameWebview extends Disposable implements Webview {
contentOptions: WebviewContentOptions,
@IThemeService themeService: IThemeService,
@ITunnelService tunnelService: ITunnelService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IFileService private readonly fileService: IFileService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
) {
super();
const useExternalEndpoint = this._configurationService.getValue<string>('webview.experimental.useExternalEndpoint');
if (typeof environmentService.webviewEndpoint !== 'string' && !useExternalEndpoint) {
if (!useExternalEndpoint && (!environmentService.options || typeof environmentService.options.webviewEndpoint !== 'string')) {
throw new Error('To use iframe based webviews, you must configure `environmentService.webviewEndpoint`');
}
@@ -145,7 +145,7 @@ export class IFrameWebview extends Disposable implements Webview {
private get endpoint(): string {
const useExternalEndpoint = this._configurationService.getValue<string>('webview.experimental.useExternalEndpoint');
const baseEndpoint = useExternalEndpoint ? 'https://{{uuid}}.vscode-webview-test.com/8fa811108f0f0524c473020ef57b6620f6c201e1' : this.environmentService.webviewEndpoint!;
const baseEndpoint = useExternalEndpoint ? 'https://{{uuid}}.vscode-webview-test.com/8fa811108f0f0524c473020ef57b6620f6c201e1' : this.environmentService.options!.webviewEndpoint!;
const endpoint = baseEndpoint.replace('{{uuid}}', this.id);
if (endpoint[endpoint.length - 1] === '/') {
return endpoint.slice(0, endpoint.length - 1);
@@ -6,7 +6,7 @@
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import * as platform from 'vs/base/common/platform';
import product from 'vs/platform/product/node/product';
import { IOpenerService } from 'vs/platform/opener/common/opener';
@@ -21,7 +21,7 @@ export class GettingStarted implements IWorkbenchContribution {
constructor(
@IStorageService private readonly storageService: IStorageService,
@IEnvironmentService environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IOpenerService private readonly openerService: IOpenerService
) {
@@ -20,7 +20,6 @@ import * as Types from 'vs/base/common/types';
import { EditorType } from 'vs/editor/common/editorCommon';
import { Selection } from 'vs/editor/common/core/selection';
import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@@ -632,11 +631,7 @@ class MockInputsConfigurationService extends TestConfigurationService {
class MockWorkbenchEnvironmentService extends WorkbenchEnvironmentService {
constructor(private env: platform.IProcessEnvironment) {
super(parseArgs(process.argv) as IWindowConfiguration, process.execPath);
}
get configuration(): IWindowConfiguration {
return { userEnv: this.env } as IWindowConfiguration;
constructor(env: platform.IProcessEnvironment) {
super({ userEnv: env } as IWindowConfiguration, process.execPath);
}
}
@@ -18,6 +18,7 @@ import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
interface IMassagedMessageBoxOptions {
@@ -45,12 +46,13 @@ export class DialogService implements IDialogService {
@ILayoutService layoutService: ILayoutService,
@IThemeService themeService: IThemeService,
@IWindowService windowService: IWindowService,
@ISharedProcessService sharedProcessService: ISharedProcessService
@ISharedProcessService sharedProcessService: ISharedProcessService,
@IKeybindingService keybindingService: IKeybindingService
) {
// Use HTML based dialogs
if (configurationService.getValue('workbench.dialogs.customEnabled') === true) {
this.impl = new HTMLDialogService(logService, layoutService, themeService);
this.impl = new HTMLDialogService(logService, layoutService, themeService, keybindingService);
}
// Electron dialog service
else {
@@ -187,4 +189,4 @@ class NativeDialogService implements IDialogService {
}
}
registerSingleton(IDialogService, DialogService, true);
registerSingleton(IDialogService, DialogService, true);
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IInstantiationService, ServicesAccessor, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { IResourceInput, ITextEditorOptions, IEditorOptions } from 'vs/platform/editor/common/editor';
import { IResourceInput, ITextEditorOptions, IEditorOptions, EditorActivation } from 'vs/platform/editor/common/editor';
import { IEditorInput, IEditor, GroupIdentifier, IFileEditorInput, IUntitledResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInputFactoryRegistry, Extensions as EditorExtensions, IFileInputFactory, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditor, ITextDiffEditor, ITextSideBySideEditor, toResource, SideBySideEditor } from 'vs/workbench/common/editor';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { DataUriEditorInput } from 'vs/workbench/common/editor/dataUriEditorInput';
@@ -19,7 +19,7 @@ import { basename } from 'vs/base/common/resources';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { localize } from 'vs/nls';
import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IResourceEditor, ACTIVE_GROUP_TYPE, SIDE_GROUP_TYPE, SIDE_GROUP, IResourceEditorReplacement, IOpenEditorOverrideHandler, IVisibleEditor, IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IResourceEditor, SIDE_GROUP, IResourceEditorReplacement, IOpenEditorOverrideHandler, IVisibleEditor, IEditorService, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Disposable, IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { coalesce } from 'vs/base/common/arrays';
@@ -28,18 +28,16 @@ import { IEditorGroupView, IEditorOpeningEvent, EditorServiceImpl } from 'vs/wor
import { ILabelService } from 'vs/platform/label/common/label';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { withNullAsUndefined } from 'vs/base/common/types';
import { convertEditorInput, getFileMode } from 'sql/workbench/common/customInputConverter'; //{{SQL CARBON EDIT}}
//{{SQL CARBON EDIT}}
import { convertEditorInput, getFileMode } from 'sql/workbench/common/customInputConverter';
//{{SQL CARBON EDIT}} - End
type ICachedEditorInput = ResourceEditorInput | IFileEditorInput | DataUriEditorInput;
type CachedEditorInput = ResourceEditorInput | IFileEditorInput | DataUriEditorInput;
type OpenInEditorGroup = IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE;
export class EditorService extends Disposable implements EditorServiceImpl {
_serviceBrand!: ServiceIdentifier<any>;
private static CACHE: ResourceMap<ICachedEditorInput> = new ResourceMap<ICachedEditorInput>();
private static CACHE: ResourceMap<CachedEditorInput> = new ResourceMap<CachedEditorInput>();
//#region events
@@ -220,46 +218,78 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#region openEditor()
openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditor | undefined>;
openEditor(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextEditor | undefined>;
openEditor(editor: IResourceDiffInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextDiffEditor | undefined>;
openEditor(editor: IResourceSideBySideInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<ITextSideBySideEditor | undefined>;
openEditor(editor: IEditorInput | IResourceEditor, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: GroupIdentifier): Promise<IEditor | undefined> {
openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: OpenInEditorGroup): Promise<IEditor | undefined>;
openEditor(editor: IResourceInput | IUntitledResourceInput, group?: OpenInEditorGroup): Promise<ITextEditor | undefined>;
openEditor(editor: IResourceDiffInput, group?: OpenInEditorGroup): Promise<ITextDiffEditor | undefined>;
openEditor(editor: IResourceSideBySideInput, group?: OpenInEditorGroup): Promise<ITextSideBySideEditor | undefined>;
async openEditor(editor: IEditorInput | IResourceEditor, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): Promise<IEditor | undefined> {
let resolvedGroup: IEditorGroup | undefined;
let candidateGroup: OpenInEditorGroup | undefined;
let typedEditor: EditorInput | undefined;
let typedOptions: EditorOptions | undefined;
// Typed Editor Support
if (editor instanceof EditorInput) {
const editorOptions = this.toOptions(optionsOrGroup as IEditorOptions);
const targetGroup = this.findTargetGroup(editor, editorOptions, group);
typedEditor = editor;
typedOptions = this.toOptions(optionsOrGroup as IEditorOptions);
return this.doOpenEditor(targetGroup, editor, editorOptions);
candidateGroup = group;
resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup);
}
// Untyped Text Editor Support
const textInput = <IResourceEditor>editor;
const typedInput = this.createInput(textInput);
if (typedInput) {
const editorOptions = TextEditorOptions.from(textInput);
const targetGroup = this.findTargetGroup(typedInput, editorOptions, optionsOrGroup as IEditorGroup | GroupIdentifier);
return this.doOpenEditor(targetGroup, typedInput, editorOptions);
else {
const textInput = <IResourceEditor>editor;
typedEditor = this.createInput(textInput);
if (typedEditor) {
typedOptions = TextEditorOptions.from(textInput);
candidateGroup = optionsOrGroup as OpenInEditorGroup;
resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup);
}
}
return Promise.resolve(undefined);
if (typedEditor && resolvedGroup) {
if (
this.editorGroupService.activeGroup !== resolvedGroup && // only if target group is not already active
typedOptions && !typedOptions.inactive && // never for inactive editors
typedOptions.preserveFocus && // only if preserveFocus
typeof typedOptions.activation !== 'number' && // only if activation is not already defined (either true or false)
candidateGroup !== SIDE_GROUP // never for the SIDE_GROUP
) {
// If the resolved group is not the active one, we typically
// want the group to become active. There are a few cases
// where we stay away from encorcing this, e.g. if the caller
// is already providing `activation`.
//
// Specifically for historic reasons we do not activate a
// group is it is opened as `SIDE_GROUP` with `preserveFocus:true`.
// repeated Alt-clicking of files in the explorer always open
// into the same side group and not cause a group to be created each time.
typedOptions.overwrite({ activation: EditorActivation.ACTIVATE });
}
return this.doOpenEditor(resolvedGroup, typedEditor, typedOptions);
}
return undefined;
}
protected doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise<IEditor | undefined> {
return group.openEditor(editor, options).then(withNullAsUndefined);
protected async doOpenEditor(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions): Promise<IEditor | undefined> {
return withNullAsUndefined(await group.openEditor(editor, options));
}
private findTargetGroup(input: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): IEditorGroup {
private findTargetGroup(input: IEditorInput, options?: IEditorOptions, group?: OpenInEditorGroup): IEditorGroup {
let targetGroup: IEditorGroup | undefined;
// Group: Instance of Group
if (group && typeof group !== 'number') {
return group;
targetGroup = group;
}
// Group: Side by Side
if (group === SIDE_GROUP) {
else if (group === SIDE_GROUP) {
targetGroup = this.findSideBySideGroup();
}
@@ -347,9 +377,9 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#region openEditors()
openEditors(editors: IEditorInputWithOptions[], group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditor[]>;
openEditors(editors: IResourceEditor[], group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditor[]>;
async openEditors(editors: Array<IEditorInputWithOptions | IResourceEditor>, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise<IEditor[]> {
openEditors(editors: IEditorInputWithOptions[], group?: OpenInEditorGroup): Promise<IEditor[]>;
openEditors(editors: IResourceEditor[], group?: OpenInEditorGroup): Promise<IEditor[]>;
async openEditors(editors: Array<IEditorInputWithOptions | IResourceEditor>, group?: OpenInEditorGroup): Promise<IEditor[]> {
// Convert to typed editors and options
const typedEditors: IEditorInputWithOptions[] = [];
@@ -379,22 +409,20 @@ export class EditorService extends Disposable implements EditorServiceImpl {
});
}
// Open in targets
// Open in target groups
const result: Promise<IEditor | null>[] = [];
mapGroupToEditors.forEach((editorsWithOptions, group) => {
result.push(group.openEditors(editorsWithOptions));
});
const openedEditors = await Promise.all(result);
return coalesce(openedEditors);
return coalesce(await Promise.all(result));
}
//#endregion
//#region isOpen()
isOpen(editor: IEditorInput | IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): boolean {
isOpen(editor: IEditorInput | IResourceInput | IUntitledResourceInput): boolean {
return !!this.doGetOpened(editor);
}
@@ -402,11 +430,11 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#region getOpend()
getOpened(editor: IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput | undefined {
getOpened(editor: IResourceInput | IUntitledResourceInput): IEditorInput | undefined {
return this.doGetOpened(editor);
}
private doGetOpened(editor: IEditorInput | IResourceInput | IUntitledResourceInput, group?: IEditorGroup | GroupIdentifier): IEditorInput | undefined {
private doGetOpened(editor: IEditorInput | IResourceInput | IUntitledResourceInput): IEditorInput | undefined {
if (!(editor instanceof EditorInput)) {
const resourceInput = editor as IResourceInput | IUntitledResourceInput;
if (!resourceInput.resource) {
@@ -414,20 +442,8 @@ export class EditorService extends Disposable implements EditorServiceImpl {
}
}
let groups: IEditorGroup[] = [];
if (typeof group === 'number') {
const groupView = this.editorGroupService.getGroup(group);
if (groupView) {
groups.push(groupView);
}
} else if (group) {
groups.push(group);
} else {
groups = [...this.editorGroupService.groups];
}
// For each editor group
for (const group of groups) {
for (const group of this.editorGroupService.groups) {
// Typed editor
if (editor instanceof EditorInput) {
@@ -574,7 +590,7 @@ export class EditorService extends Disposable implements EditorServiceImpl {
throw new Error('Unknown input type');
}
private createOrGet(resource: URI, instantiationService: IInstantiationService, label: string | undefined, description: string | undefined, encoding: string | undefined, mode: string | undefined, forceFile: boolean | undefined): ICachedEditorInput {
private createOrGet(resource: URI, instantiationService: IInstantiationService, label: string | undefined, description: string | undefined, encoding: string | undefined, mode: string | undefined, forceFile: boolean | undefined): CachedEditorInput {
if (EditorService.CACHE.has(resource)) {
const input = EditorService.CACHE.get(resource)!;
if (input instanceof ResourceEditorInput) {
@@ -602,9 +618,8 @@ export class EditorService extends Disposable implements EditorServiceImpl {
return input;
}
let input: ICachedEditorInput;
// File
let input: CachedEditorInput;
if (forceFile /* fix for https://github.com/Microsoft/vscode/issues/48275 */ || this.fileService.canHandleResource(resource)) {
input = this.fileInputFactory.createFileInput(resource, encoding, mode, instantiationService);
}
@@ -645,7 +660,12 @@ export class EditorService extends Disposable implements EditorServiceImpl {
}
export interface IEditorOpenHandler {
(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions): Promise<IEditor | null>;
(
delegate: (group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions) => Promise<IEditor | undefined>,
group: IEditorGroup,
editor: IEditorInput,
options?: IEditorOptions | ITextEditorOptions
): Promise<IEditor | null>;
}
/**
@@ -682,7 +702,13 @@ export class DelegatingEditorService extends EditorService {
return super.doOpenEditor(group, editor, options);
}
const control = await this.editorOpenHandler(group, editor, options);
const control = await this.editorOpenHandler(
(group: IEditorGroup, editor: IEditorInput, options?: IEditorOptions) => super.doOpenEditor(group, editor, options),
group,
editor,
options
);
if (control) {
return control; // the opening was handled, so return early
}
@@ -330,7 +330,7 @@ suite.skip('EditorService', () => { // {{SQL CARBON EDIT}} skip suite
const inp = instantiationService.createInstance(ResourceEditorInput, 'name', 'description', URI.parse('my://resource-delegate'), undefined);
const delegate = instantiationService.createInstance(DelegatingEditorService);
delegate.setEditorOpenHandler((group: IEditorGroup, input: IEditorInput, options?: EditorOptions) => {
delegate.setEditorOpenHandler((delegate, group: IEditorGroup, input: IEditorInput, options?: EditorOptions) => {
assert.strictEqual(input, inp);
done();
@@ -96,11 +96,9 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
break: false
};
this.webviewEndpoint = options.webviewEndpoint;
this.untitledWorkspacesHome = URI.from({ scheme: Schemas.untitled, path: 'Workspaces' });
if (document && document.location && document.location.search) {
const map = new Map<string, string>();
const query = document.location.search.substring(1);
const vars = query.split('&');
@@ -170,7 +168,6 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
verbose: boolean;
skipGettingStarted: boolean;
skipReleaseNotes: boolean;
skipAddToRecentlyOpened: boolean;
mainIPCHandle: string;
sharedIPCHandle: string;
nodeCachedDataDir?: string;
@@ -179,16 +176,15 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
disableCrashReporter: boolean;
driverHandle?: string;
driverVerbose: boolean;
webviewEndpoint?: string;
galleryMachineIdResource?: URI;
readonly logFile: URI;
get webviewResourceRoot(): string {
return this.webviewEndpoint ? this.webviewEndpoint + '/vscode-resource{{resource}}' : 'vscode-resource:{{resource}}';
return this.options.webviewEndpoint ? `${this.options.webviewEndpoint}/vscode-resource{{resource}}` : 'vscode-resource:{{resource}}';
}
get webviewCspSource(): string {
return this.webviewEndpoint ? this.webviewEndpoint : 'vscode-resource:';
return this.options.webviewEndpoint ? this.options.webviewEndpoint : 'vscode-resource:';
}
}
@@ -5,7 +5,7 @@
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IEnvironmentService, IDebugParams } from 'vs/platform/environment/common/environment';
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
import { URI } from 'vs/base/common/uri';
@@ -17,7 +17,17 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService {
readonly configuration: IWindowConfiguration;
readonly logFile: URI;
readonly options?: IWorkbenchConstructionOptions;
readonly logFile: URI;
readonly logExtensionHostCommunication: boolean;
readonly debugSearch: IDebugParams;
readonly webviewResourceRoot: string;
readonly webviewCspSource: string;
readonly skipGettingStarted: boolean | undefined;
readonly skipReleaseNotes: boolean | undefined;
}
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { EnvironmentService, parseSearchPort } from 'vs/platform/environment/node/environmentService';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { memoize } from 'vs/base/common/decorators';
@@ -12,27 +12,36 @@ import { Schemas } from 'vs/base/common/network';
import { toBackupWorkspaceResource } from 'vs/workbench/services/backup/common/backup';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { join } from 'vs/base/common/path';
import { IDebugParams } from 'vs/platform/environment/common/environment';
export class WorkbenchEnvironmentService extends EnvironmentService implements IWorkbenchEnvironmentService {
_serviceBrand!: ServiceIdentifier<any>;
readonly webviewResourceRoot = 'vscode-resource:{{resource}}';
readonly webviewCspSource = 'vscode-resource:';
constructor(
private _configuration: IWindowConfiguration,
readonly configuration: IWindowConfiguration,
execPath: string
) {
super(_configuration, execPath);
super(configuration, execPath);
this._configuration.backupWorkspaceResource = this._configuration.backupPath ? toBackupWorkspaceResource(this._configuration.backupPath, this) : undefined;
this.configuration.backupWorkspaceResource = this.configuration.backupPath ? toBackupWorkspaceResource(this.configuration.backupPath, this) : undefined;
}
get configuration(): IWindowConfiguration {
return this._configuration;
}
get skipGettingStarted(): boolean { return !!this.args['skip-getting-started']; }
get skipReleaseNotes(): boolean { return !!this.args['skip-release-notes']; }
@memoize
get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.userData }); }
@memoize
get logFile(): URI { return URI.file(join(this.logsPath, `renderer${this.configuration.windowId}.log`)); }
get logExtensionHostCommunication(): boolean { return !!this.args.logExtensionHostCommunication; }
@memoize
get debugSearch(): IDebugParams { return parseSearchPort(this.args, this.isBuilt); }
}
@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ExtHostCustomersRegistry } from 'vs/workbench/api/common/extHostCustomers';
import { ExtHostContext, ExtHostExtensionServiceShape, IExtHostContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
@@ -59,7 +59,7 @@ export class ExtensionHostProcessManager extends Disposable {
private readonly _remoteAuthority: string,
initialActivationEvents: string[],
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
) {
super();
this._extensionHostProcessFinishedActivateEvents = Object.create(null);
@@ -5,7 +5,7 @@
import { Emitter, Event } from 'vs/base/common/event';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { ILabelService } from 'vs/platform/label/common/label';
import { ILogService } from 'vs/platform/log/common/log';
import { connectRemoteAgentExtensionHost, IRemoteExtensionHostStartParams, IConnectionOptions, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
@@ -49,7 +49,7 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
private readonly _initDataProvider: IInitDataProvider,
private readonly _socketFactory: ISocketFactory,
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@ILogService private readonly _logService: ILogService,
@@ -489,7 +489,14 @@ export class ExtensionService extends AbstractExtensionService implements IExten
}
// fetch the remote environment
const remoteEnv = (await this._remoteAgentService.getEnvironment())!;
const remoteEnv = (await this._remoteAgentService.getEnvironment());
if (!remoteEnv) {
this._notificationService.notify({ severity: Severity.Error, message: nls.localize('getEnvironmentFailure', "Could not fetch remote environment") });
// Proceed with the local extension host
await this._startLocalExtensionHost(extensionHost, localExtensions, localExtensions.map(extension => extension.identifier));
return;
}
// enable or disable proposed API per extension
this._checkEnableProposedApi(remoteEnv.extensions);
@@ -19,8 +19,8 @@ declare namespace self {
let close: any;
let postMessage: any;
let addEventLister: any;
let indexedDB: any;
let caches: any;
let indexedDB: { open: any, [k: string]: any };
let caches: { open: any, [k: string]: any };
}
const nativeClose = self.close.bind(self);
@@ -32,9 +32,8 @@ self.postMessage = () => console.trace(`'postMessage' has been blocked`);
const nativeAddEventLister = addEventListener.bind(self);
self.addEventLister = () => console.trace(`'addEventListener' has been blocked`);
// readonly, cannot redefine...
// self.indexedDB = undefined;
// self.caches = undefined;
self.indexedDB.open = () => console.trace(`'indexedDB.open' has been blocked`);
self.caches.open = () => console.trace(`'indexedDB.caches' has been blocked`);
//#endregion ---
@@ -129,7 +129,10 @@ export class LabelService implements ILabelService {
}
getUriLabel(resource: URI, options: { relative?: boolean, noPrefix?: boolean, endWithSeparator?: boolean } = {}): string {
const formatting = this.findFormatting(resource);
return this.doGetUriLabel(resource, this.findFormatting(resource), options);
}
private doGetUriLabel(resource: URI, formatting?: ResourceLabelFormatting, options: { relative?: boolean, noPrefix?: boolean, endWithSeparator?: boolean } = {}): string {
if (!formatting) {
return getPathLabel(resource.path, this.environmentService, options.relative ? this.contextService : undefined);
}
@@ -161,13 +164,16 @@ export class LabelService implements ILabelService {
}
getUriBasenameLabel(resource: URI): string {
const label = this.getUriLabel(resource);
const formatting = this.findFormatting(resource);
if (formatting && formatting.separator === '\\') {
return paths.win32.basename(label);
const label = this.doGetUriLabel(resource, formatting);
if (formatting) {
switch (formatting.separator) {
case paths.win32.sep: return paths.win32.basename(label);
case paths.posix.sep: return paths.posix.basename(label);
}
}
return paths.posix.basename(label);
return paths.basename(label);
}
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
@@ -214,7 +214,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
private openSettings2(options?: ISettingsEditorOptions): Promise<IEditor> {
const input = this.settingsEditor2Input;
return this.editorGroupService.activeGroup.openEditor(input, options)
return this.editorService.openEditor(input, options)
.then(() => this.editorGroupService.activeGroup.activeControl!);
}
@@ -160,14 +160,14 @@ export class KeybindingsEditorModel extends EditorModel {
return result;
}
resolve(editorActionsLabels: Map<string, string>): Promise<EditorModel> {
resolve(actionLabels: Map<string, string>): Promise<EditorModel> {
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
this._keybindingItemsSortedByPrecedence = [];
const boundCommands: Map<string, boolean> = new Map<string, boolean>();
for (const keybinding of this.keybindingsService.getKeybindings()) {
if (keybinding.command) { // Skip keybindings without commands
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(keybinding.command, keybinding, workbenchActionsRegistry, editorActionsLabels));
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(keybinding.command, keybinding, workbenchActionsRegistry, actionLabels));
boundCommands.set(keybinding.command, true);
}
}
@@ -175,7 +175,7 @@ export class KeybindingsEditorModel extends EditorModel {
const commandsWithDefaultKeybindings = this.keybindingsService.getDefaultKeybindings().map(keybinding => keybinding.command);
for (const command of KeybindingResolver.getAllUnboundCommands(boundCommands)) {
const keybindingItem = new ResolvedKeybindingItem(undefined, command, null, undefined, commandsWithDefaultKeybindings.indexOf(command) === -1);
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(command, keybindingItem, workbenchActionsRegistry, editorActionsLabels));
this._keybindingItemsSortedByPrecedence.push(KeybindingsEditorModel.toKeybindingEntry(command, keybindingItem, workbenchActionsRegistry, actionLabels));
}
this._keybindingItems = this._keybindingItemsSortedByPrecedence.slice(0).sort((a, b) => KeybindingsEditorModel.compareKeybindingData(a, b));
return Promise.resolve(this);
@@ -209,9 +209,9 @@ export class KeybindingsEditorModel extends EditorModel {
return a.command.localeCompare(b.command);
}
private static toKeybindingEntry(command: string, keybindingItem: ResolvedKeybindingItem, workbenchActionsRegistry: IWorkbenchActionRegistry, editorActions: Map<string, string>): IKeybindingItem {
private static toKeybindingEntry(command: string, keybindingItem: ResolvedKeybindingItem, workbenchActionsRegistry: IWorkbenchActionRegistry, actions: Map<string, string>): IKeybindingItem {
const menuCommand = MenuRegistry.getCommand(command)!;
const editorActionLabel = editorActions.get(command)!;
const editorActionLabel = actions.get(command)!;
return <IKeybindingItem>{
keybinding: keybindingItem.resolvedKeybinding,
keybindingItem,
@@ -264,13 +264,13 @@ class KeybindingItemMatches {
this.commandLabelMatches = keybindingItem.commandLabel ? this.matches(searchValue, keybindingItem.commandLabel, (word, wordToMatchAgainst) => matchesWords(word, keybindingItem.commandLabel, true), words) : null;
this.commandDefaultLabelMatches = keybindingItem.commandDefaultLabel ? this.matches(searchValue, keybindingItem.commandDefaultLabel, (word, wordToMatchAgainst) => matchesWords(word, keybindingItem.commandDefaultLabel, true), words) : null;
this.sourceMatches = this.matches(searchValue, keybindingItem.source, (word, wordToMatchAgainst) => matchesWords(word, keybindingItem.source, true), words);
this.whenMatches = keybindingItem.when ? this.matches(searchValue, keybindingItem.when, or(matchesWords, matchesCamelCase), words) : null;
this.whenMatches = keybindingItem.when ? this.matches(null, keybindingItem.when, or(matchesWords, matchesCamelCase), words) : null;
}
this.keybindingMatches = keybindingItem.keybinding ? this.matchesKeybinding(keybindingItem.keybinding, searchValue, keybindingWords, completeMatch) : null;
}
private matches(searchValue: string, wordToMatchAgainst: string, wordMatchesFilter: IFilter, words: string[]): IMatch[] | null {
let matches = wordFilter(searchValue, wordToMatchAgainst);
private matches(searchValue: string | null, wordToMatchAgainst: string, wordMatchesFilter: IFilter, words: string[]): IMatch[] | null {
let matches = searchValue ? wordFilter(searchValue, wordToMatchAgainst) : null;
if (!matches) {
matches = this.matchesWords(words, wordToMatchAgainst, wordMatchesFilter);
}
@@ -167,20 +167,12 @@ export class SettingsEditorOptions extends EditorOptions implements ISettingsEdi
static create(settings: ISettingsEditorOptions): SettingsEditorOptions {
const options = new SettingsEditorOptions();
options.overwrite(settings);
options.target = settings.target;
options.folderUri = settings.folderUri;
options.query = settings.query;
// IEditorOptions
options.preserveFocus = settings.preserveFocus;
options.forceReload = settings.forceReload;
options.revealIfVisible = settings.revealIfVisible;
options.revealIfOpened = settings.revealIfOpened;
options.pinned = settings.pinned;
options.index = settings.index;
options.inactive = settings.inactive;
return options;
}
}
@@ -348,7 +348,9 @@ export class ProgressService extends Disposable implements IProgressService {
const disposables = new DisposableStore();
const allowableCommands = [
'workbench.action.quit',
'workbench.action.reloadWindow'
'workbench.action.reloadWindow',
'copy',
'cut'
];
let dialog: Dialog;
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IRequestOptions, IRequestContext } from 'vs/platform/request/common/request';
import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
@@ -12,7 +12,8 @@ import { URI as uri } from 'vs/base/common/uri';
import { getNextTickChannel } from 'vs/base/parts/ipc/common/ipc';
import { Client, IIPCOptions } from 'vs/base/parts/ipc/node/ipc.cp';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IDebugParams, IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IDebugParams } from 'vs/platform/environment/common/environment';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IFileService } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { FileMatch, IFileMatch, IFileQuery, IProgressMessage, IRawSearchService, ISearchComplete, ISearchConfiguration, ISearchProgressItem, ISearchResultProvider, ISerializedFileMatch, ISerializedSearchComplete, ISerializedSearchProgressItem, isSerializedSearchComplete, isSerializedSearchSuccess, ITextQuery, ISearchService } from 'vs/workbench/services/search/common/search';
@@ -35,7 +36,7 @@ export class LocalSearchService extends SearchService {
@ILogService logService: ILogService,
@IExtensionService extensionService: IExtensionService,
@IFileService fileService: IFileService,
@IEnvironmentService readonly environmentService: IEnvironmentService,
@IWorkbenchEnvironmentService readonly environmentService: IWorkbenchEnvironmentService,
@IInstantiationService readonly instantiationService: IInstantiationService
) {
super(modelService, untitledEditorService, editorService, telemetryService, logService, extensionService, fileService);
@@ -685,7 +685,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
protected async promptForPath(resource: URI, defaultUri: URI, availableFileSystems?: string[]): Promise<URI | undefined> {
// Help user to find a name for the file by opening it first
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true, } });
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true } });
return this.fileDialogService.pickFileToSave(this.getSaveDialogOptions(defaultUri, availableFileSystems));
}
@@ -710,6 +710,10 @@ export class TestEditorGroupsService implements IEditorGroupsService {
throw new Error('not implemented');
}
restoreGroup(_group: number | IEditorGroup): IEditorGroup {
throw new Error('not implemented');
}
getSize(_group: number | IEditorGroup): { width: number, height: number } {
return { width: 100, height: 100 };
}
+6
View File
@@ -11,6 +11,7 @@ import { IWebSocketFactory } from 'vs/platform/remote/browser/browserSocketFacto
import { ICredentialsProvider } from 'vs/workbench/services/credentials/browser/credentialsService';
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
import { IProductConfiguration } from 'vs/platform/product/common/product';
export interface IWorkbenchConstructionOptions {
@@ -71,6 +72,11 @@ export interface IWorkbenchConstructionOptions {
* Experimental: Support for URL callbacks.
*/
urlCallbackProvider?: IURLCallbackProvider;
/**
* Experimental: Support for product configuration.
*/
productConfiguration?: IProductConfiguration;
}
/**