SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,211 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { fuzzyScore } from 'vs/base/common/filters';
import { ISuggestSupport } from 'vs/editor/common/modes';
import { ISuggestionItem, SnippetConfig } from './suggest';
export interface ICompletionItem extends ISuggestionItem {
matches?: number[];
score?: number;
idx?: number;
}
export interface ICompletionStats {
suggestionCount: number;
snippetCount: number;
textCount: number;
[name: string]: any;
}
export class LineContext {
leadingLineContent: string;
characterCountDelta: number;
}
export class CompletionModel {
private readonly _column: number;
private readonly _items: ISuggestionItem[];
private readonly _snippetCompareFn = CompletionModel._compareCompletionItems;
private _lineContext: LineContext;
private _filteredItems: ICompletionItem[];
private _isIncomplete: boolean;
private _stats: ICompletionStats;
constructor(items: ISuggestionItem[], column: number, lineContext: LineContext, snippetConfig?: SnippetConfig) {
this._items = items;
this._column = column;
this._lineContext = lineContext;
if (snippetConfig === 'top') {
this._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsUp;
} else if (snippetConfig === 'bottom') {
this._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsDown;
}
}
get lineContext(): LineContext {
return this._lineContext;
}
set lineContext(value: LineContext) {
if (this._lineContext.leadingLineContent !== value.leadingLineContent
|| this._lineContext.characterCountDelta !== value.characterCountDelta) {
this._lineContext = value;
this._filteredItems = undefined;
}
}
get items(): ICompletionItem[] {
this._ensureCachedState();
return this._filteredItems;
}
get incomplete(): boolean {
this._ensureCachedState();
return this._isIncomplete;
}
resolveIncompleteInfo(): { incomplete: ISuggestSupport[], complete: ISuggestionItem[] } {
const incomplete: ISuggestSupport[] = [];
const complete: ISuggestionItem[] = [];
for (const item of this._items) {
if (!item.container.incomplete) {
complete.push(item);
} else if (incomplete.indexOf(item.support) < 0) {
incomplete.push(item.support);
}
}
return { incomplete, complete };
}
get stats(): ICompletionStats {
this._ensureCachedState();
return this._stats;
}
private _ensureCachedState(): void {
if (!this._filteredItems) {
this._createCachedState();
}
}
private _createCachedState(): void {
this._filteredItems = [];
this._isIncomplete = false;
this._stats = { suggestionCount: 0, snippetCount: 0, textCount: 0 };
const { leadingLineContent, characterCountDelta } = this._lineContext;
let word = '';
for (let i = 0; i < this._items.length; i++) {
const item = <ICompletionItem>this._items[i];
const { suggestion, container } = item;
// collect those supports that signaled having
// an incomplete result
this._isIncomplete = this._isIncomplete || container.incomplete;
// 'word' is that remainder of the current line that we
// filter and score against. In theory each suggestion uses a
// differnet word, but in practice not - that's why we cache
const wordLen = suggestion.overwriteBefore + characterCountDelta - (item.position.column - this._column);
if (word.length !== wordLen) {
word = wordLen === 0 ? '' : leadingLineContent.slice(-wordLen);
}
if (wordLen === 0) {
// when there is nothing to score against, don't
// event try to do. Use a const rank and rely on
// the fallback-sort using the initial sort order.
// use a score of `-100` because that is out of the
// bound of values `fuzzyScore` will return
item.score = -100;
} else if (typeof suggestion.filterText === 'string') {
// when there is a `filterText` it must match the `word`.
// if it matches we check with the label to compute highlights
// and if that doesn't yield a result we have no highlights,
// despite having the match
let match = fuzzyScore(word, suggestion.filterText, suggestion.overwriteBefore);
if (!match) {
continue;
}
item.score = match[0];
item.matches = [];
match = fuzzyScore(word, suggestion.label, suggestion.overwriteBefore);
if (match) {
item.matches = match[1];
}
} else {
// by default match `word` against the `label`
let match = fuzzyScore(word, suggestion.label, suggestion.overwriteBefore);
if (match) {
item.score = match[0];
item.matches = match[1];
} else {
continue;
}
}
item.idx = i;
this._filteredItems.push(item);
// update stats
this._stats.suggestionCount++;
switch (suggestion.type) {
case 'snippet': this._stats.snippetCount++; break;
case 'text': this._stats.textCount++; break;
}
}
this._filteredItems.sort(this._snippetCompareFn);
}
private static _compareCompletionItems(a: ICompletionItem, b: ICompletionItem): number {
if (a.score > b.score) {
return -1;
} else if (a.score < b.score) {
return 1;
} else if (a.idx < b.idx) {
return -1;
} else if (a.idx > b.idx) {
return 1;
} else {
return 0;
}
}
private static _compareCompletionItemsSnippetsDown(a: ICompletionItem, b: ICompletionItem): number {
if (a.suggestion.type !== b.suggestion.type) {
if (a.suggestion.type === 'snippet') {
return 1;
} else if (b.suggestion.type === 'snippet') {
return -1;
}
}
return CompletionModel._compareCompletionItems(a, b);
}
private static _compareCompletionItemsSnippetsUp(a: ICompletionItem, b: ICompletionItem): number {
if (a.suggestion.type !== b.suggestion.type) {
if (a.suggestion.type === 'snippet') {
return -1;
} else if (b.suggestion.type === 'snippet') {
return 1;
}
}
return CompletionModel._compareCompletionItems(a, b);
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-orange{fill:#c27d1a}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 6.586l-3-3L11.586 5H9.414l1-1-4-4h-.828L0 5.586v.828l4 4L6.414 8H7v5h1.586l3 3h.828L16 12.414v-.828L13.914 9.5 16 7.414v-.828z" id="outline"/><path class="icon-vs-action-orange" d="M13 10l2 2-3 3-2-2 1-1H8V7H6L4 9 1 6l5-5 3 3-2 2h5l1-1 2 2-3 3-2-2 1-1H9v4l2.999.002L13 10z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 584 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-action-orange{fill:#e8ab53}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 6.586l-3-3L11.586 5H9.414l1-1-4-4h-.828L0 5.586v.828l4 4L6.414 8H7v5h1.586l3 3h.828L16 12.414v-.828L13.914 9.5 16 7.414v-.828z" id="outline"/><path class="icon-vs-action-orange" d="M13 10l2 2-3 3-2-2 1-1H8V7H6L4 9 1 6l5-5 3 3-2 2h5l1-1 2 2-3 3-2-2 1-1H9v4l2.999.002L13 10z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 584 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-red{fill:#e51400}.icon-vs-yellow{fill:#ffcc00}.icon-vs-green{fill:#339933}.icon-vs-blue{fill:#1ba1e2}.icon-vs-action-purple{fill:#652d90}.icon-white{fill:#ffffff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 8c0 4.411-3.589 8-8 8a2.803 2.803 0 0 1-2.8-2.8c0-.833.272-1.629.766-2.241a.596.596 0 0 0 .101-.359.667.667 0 0 0-.667-.666.58.58 0 0 0-.358.102A3.584 3.584 0 0 1 2.8 10.8 2.803 2.803 0 0 1 0 8c0-4.411 3.589-8 8-8s8 3.589 8 8z" id="outline"/><path class="icon-white" d="M5.4 7.933a2.67 2.67 0 0 1 2.667 2.666c0 .606-.193 1.179-.544 1.614a1.599 1.599 0 0 0-.323.987.8.8 0 0 0 .8.8c3.309 0 6-2.691 6-6s-2.691-6-6-6-6 2.691-6 6c0 .441.359.8.8.8.378 0 .729-.114.986-.322A2.568 2.568 0 0 1 5.4 7.933z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M8 15c-.992 0-1.8-.808-1.8-1.8 0-.606.193-1.179.544-1.613.208-.259.323-.609.323-.987 0-.919-.748-1.666-1.667-1.666-.377 0-.728.115-.986.323A2.58 2.58 0 0 1 2.8 9.8C1.808 9.8 1 8.992 1 8c0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM5.4 7.933a2.67 2.67 0 0 1 2.667 2.666c0 .606-.193 1.179-.544 1.614a1.599 1.599 0 0 0-.323.987.8.8 0 0 0 .8.8c3.309 0 6-2.691 6-6s-2.691-6-6-6-6 2.691-6 6c0 .441.359.8.8.8.378 0 .729-.114.986-.322A2.568 2.568 0 0 1 5.4 7.933z"/><path class="icon-vs-action-purple" d="M4.5 5.375a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-blue" d="M7.125 3.625a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-green" d="M10.625 4.5a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-yellow" d="M11.5 8a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-red" d="M9.75 10.625a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-red{fill:#f48771}.icon-vs-yellow{fill:#ffcc00}.icon-vs-green{fill:#339933}.icon-vs-blue{fill:#1ba1e2}.icon-vs-action-purple{fill:#b180d7}.icon-white{fill:#000000}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 8c0 4.411-3.589 8-8 8a2.803 2.803 0 0 1-2.8-2.8c0-.833.272-1.629.766-2.241a.596.596 0 0 0 .101-.359.667.667 0 0 0-.667-.666.58.58 0 0 0-.358.102A3.584 3.584 0 0 1 2.8 10.8 2.803 2.803 0 0 1 0 8c0-4.411 3.589-8 8-8s8 3.589 8 8z" id="outline"/><path class="icon-white" d="M5.4 7.933a2.67 2.67 0 0 1 2.667 2.666c0 .606-.193 1.179-.544 1.614a1.599 1.599 0 0 0-.323.987.8.8 0 0 0 .8.8c3.309 0 6-2.691 6-6s-2.691-6-6-6-6 2.691-6 6c0 .441.359.8.8.8.378 0 .729-.114.986-.322A2.568 2.568 0 0 1 5.4 7.933z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M8 15c-.992 0-1.8-.808-1.8-1.8 0-.606.193-1.179.544-1.613.208-.259.323-.609.323-.987 0-.919-.748-1.666-1.667-1.666-.377 0-.728.115-.986.323A2.58 2.58 0 0 1 2.8 9.8C1.808 9.8 1 8.992 1 8c0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM5.4 7.933a2.67 2.67 0 0 1 2.667 2.666c0 .606-.193 1.179-.544 1.614a1.599 1.599 0 0 0-.323.987.8.8 0 0 0 .8.8c3.309 0 6-2.691 6-6s-2.691-6-6-6-6 2.691-6 6c0 .441.359.8.8.8.378 0 .729-.114.986-.322A2.568 2.568 0 0 1 5.4 7.933z"/><path class="icon-vs-action-purple" d="M4.5 5.375a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-blue" d="M7.125 3.625a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-green" d="M10.625 4.5a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-yellow" d="M11.5 8a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/><path class="icon-vs-red" d="M9.75 10.625a.875.875 0 1 0 0 1.75.875.875 0 0 0 0-1.75z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M2.879 14L1 12.121V3.879L2.879 2h10.242L15 3.879v8.242L13.121 14H2.879z" id="outline"/><path class="icon-vs-fg" d="M12.293 4H3.707L3 4.707v6.586l.707.707h8.586l.707-.707V4.707L12.293 4zM11 10H5V9h6v1zm0-3H5V6h6v1z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M12.707 13H3.293L2 11.707V4.293L3.293 3h9.414L14 4.293v7.414L12.707 13zm-9-1h8.586l.707-.707V4.707L12.293 4H3.707L3 4.707v6.586l.707.707z"/><path class="icon-vs-action-blue" d="M11 7H5V6h6v1zm0 2H5v1h6V9z"/></g></svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#252526}.icon-vs-out{fill:#252526}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M2.879 14L1 12.121V3.879L2.879 2h10.242L15 3.879v8.242L13.121 14H2.879z" id="outline"/><path class="icon-vs-fg" d="M12.293 4H3.707L3 4.707v6.586l.707.707h8.586l.707-.707V4.707L12.293 4zM11 10H5V9h6v1zm0-3H5V6h6v1z" id="iconFg"/><g id="iconBg"><path class="icon-vs-bg" d="M12.707 13H3.293L2 11.707V4.293L3.293 3h9.414L14 4.293v7.414L12.707 13zm-9-1h8.586l.707-.707V4.707L12.293 4H3.707L3 4.707v6.586l.707.707z"/><path class="icon-vs-action-blue" d="M11 7H5V6h6v1zm0 2H5v1h6V9z"/></g></svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M15 16H2V0h8.621L15 4.379V16z" id="outline"/><path class="icon-vs-fg" d="M13 14H4V2h5v4h4v8zm-3-9V2.207L12.793 5H10z" id="iconFg"/><path class="icon-vs-bg" d="M3 1v14h11V4.793L10.207 1H3zm10 13H4V2h5v4h4v8zm-3-9V2.207L12.793 5H10z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M15 16H2V0h8.621L15 4.379V16z" id="outline"/><path class="icon-vs-fg" d="M13 14H4V2h5v4h4v8zm-3-9V2.207L12.793 5H10z" id="iconFg"/><path class="icon-vs-bg" d="M3 1v14h11V4.793L10.207 1H3zm10 13H4V2h5v4h4v8zm-3-9V2.207L12.793 5H10z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 15V6h6V2.586L7.585 1h6.829L16 2.586v5.829L14.414 10H10v5H0zm3-6z" id="outline"/><path class="icon-vs-fg" d="M8 3v3h5v1h-3v1h4V3H8zm5 2H9V4h4v1zM2 8v5h6V8H2zm5 3H3v-1h4v1z" id="iconFg"/><path class="icon-vs-action-blue" d="M10 6h3v1h-3V6zM9 4v1h4V4H9zm5-2H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1zm-7 8H3v1h4v-1zm2-3v7H1V7h8zM8 8H2v5h6V8z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 664 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 15V6h6V2.586L7.585 1h6.829L16 2.586v5.829L14.414 10H10v5H0zm3-6z" id="outline"/><path class="icon-vs-fg" d="M8 3v3h5v1h-3v1h4V3H8zm5 2H9V4h4v1zM2 8v5h6V8H2zm5 3H3v-1h4v1z" id="iconFg"/><path class="icon-vs-action-blue" d="M10 6h3v1h-3V6zM9 4v1h4V4H9zm5-2H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1zm-7 8H3v1h4v-1zm2-3v7H1V7h8zM8 8H2v5h6V8z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 664 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-orange{fill:#c27d1a}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14.414 1L16 2.586v5.828L14.414 10H10v3.416L8.414 15H1.586L0 13.416v-5.83L1.586 6H6V2.586L7.586 1h6.828z" id="outline"/><path class="icon-vs-fg" d="M2 13h6V8H2v5zm1-4h4v1H3V9zm0 2h4v1H3v-1zm11-5V3H8v3h.414L9 6.586V6h4v1H9.414l.586.586V8h4V6zm-1-1H9V4h4v1z" id="iconFg"/><path class="icon-vs-action-orange" d="M3 11h4.001v1H3v-1zm0-1h4.001V9H3v1zm6-2v5l-1 1H2l-1-1V8l1-1h6l1 1zM8 8H2v5h6V8zm1-2l1 1h3V6H9zm0-1h4V4H9v1zm5-3H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 789 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-orange{fill:#e8ab53}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14.414 1L16 2.586v5.828L14.414 10H10v3.416L8.414 15H1.586L0 13.416v-5.83L1.586 6H6V2.586L7.586 1h6.828z" id="outline"/><path class="icon-vs-fg" d="M2 13h6V8H2v5zm1-4h4v1H3V9zm0 2h4v1H3v-1zm11-5V3H8v3h.414L9 6.586V6h4v1H9.414l.586.586V8h4V6zm-1-1H9V4h4v1z" id="iconFg"/><path class="icon-vs-action-orange" d="M3 11h4.001v1H3v-1zm0-1h4.001V9H3v1zm6-2v5l-1 1H2l-1-1V8l1-1h6l1 1zM8 8H2v5h6V8zm1-2l1 1h3V6H9zm0-1h4V4H9v1zm5-3H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 789 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-orange{fill:#c27d1a}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 1.414L9.414 6H14v1.414L5.414 16H3v-1.234L5.371 10H2V8.764L6.382 0H14v1.414z" id="outline" style="display: none;"/><path class="icon-vs-action-orange" d="M7 7h6l-8 8H4l2.985-6H3l4-8h6L7 7z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 499 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-action-orange{fill:#e8ab53}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 1.414L9.414 6H14v1.414L5.414 16H3v-1.234L5.371 10H2V8.764L6.382 0H14v1.414z" id="outline" style="display: none;"/><path class="icon-vs-action-orange" d="M7 7h6l-8 8H4l2.985-6H3l4-8h6L7 7z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 499 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 10.736V4.5L9 0l7 3.5v6.236l-9 4.5-7-3.5z" id="outline"/><path class="icon-vs-action-blue" d="M9 1L1 5v5l6 3 8-4V4L9 1zM7 6.882L3.236 5 9 2.118 12.764 4 7 6.882z" id="iconBg"/><path class="icon-vs-fg" d="M9 2.118L12.764 4 7 6.882 3.236 5 9 2.118z" id="iconFg"/></svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 10.736V4.5L9 0l7 3.5v6.236l-9 4.5-7-3.5z" id="outline"/><path class="icon-vs-action-blue" d="M9 1L1 5v5l6 3 8-4V4L9 1zM7 6.882L3.236 5 9 2.118 12.764 4 7 6.882z" id="iconBg"/><path class="icon-vs-fg" d="M9 2.118L12.764 4 7 6.882 3.236 5 9 2.118z" id="iconFg"/></svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{opacity:0;fill:#F6F6F6;} .icon-vs-fg{fill:#F0EFF1;} .icon-folder{fill:#656565;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 2.5v10c0 .827-.673 1.5-1.5 1.5h-11.996c-.827 0-1.5-.673-1.5-1.5v-8c0-.827.673-1.5 1.5-1.5h2.886l1-2h8.11c.827 0 1.5.673 1.5 1.5z" id="outline"/><path class="icon-folder" d="M14.5 2h-7.492l-1 2h-3.504c-.277 0-.5.224-.5.5v8c0 .276.223.5.5.5h11.996c.275 0 .5-.224.5-.5v-10c0-.276-.225-.5-.5-.5zm-.496 2h-6.496l.5-1h5.996v1z" id="iconBg"/><path class="icon-vs-fg" d="M14 3v1h-6.5l.5-1h6z" id="iconFg"/></svg>

After

Width:  |  Height:  |  Size: 750 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{opacity:0;fill:#F6F6F6;} .icon-vs-fg{opacity:0;fill:#F0EFF1;} .icon-folder{fill:#C5C5C5;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 2.5v10c0 .827-.673 1.5-1.5 1.5h-11.996c-.827 0-1.5-.673-1.5-1.5v-8c0-.827.673-1.5 1.5-1.5h2.886l1-2h8.11c.827 0 1.5.673 1.5 1.5z" id="outline"/><path class="icon-folder" d="M14.5 2h-7.492l-1 2h-3.504c-.277 0-.5.224-.5.5v8c0 .276.223.5.5.5h11.996c.275 0 .5-.224.5-.5v-10c0-.276-.225-.5-.5-.5zm-.496 2h-6.496l.5-1h5.996v1z" id="iconBg"/><path class="icon-vs-fg" d="M14 3v1h-6.5l.5-1h6z" id="iconFg"/></svg>

After

Width:  |  Height:  |  Size: 760 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 4.556V13c0 .97-.701 2-2 2H4c-.97 0-2-.701-2-2V6.649A3.495 3.495 0 0 1 0 3.5C0 1.57 1.57 0 3.5 0H5v1h5.061L14 4.556z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M13 5v8s-.035 1-1.035 1h-8S3 14 3 13V9h1v4h8V6H9.397l.517-.52L9 4.572V3H7.419L6.413 2h3.228L13 5z" id="iconBg"/><path class="icon-vs-fg" d="M7.419 3H9v1.572L7.419 3zm1.978 3L6.416 9H4v4h8V6H9.397z" id="iconFg" style="display: none;"/><path class="icon-vs-action-blue" d="M5.988 6H3.5a2.5 2.5 0 1 1 0-5H4v1h-.5C2.673 2 2 2.673 2 3.5S2.673 5 3.5 5h2.513L4 3h2l2.5 2.484L6 8H4l1.988-2z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 929 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M14 4.556V13c0 .97-.701 2-2 2H4c-.97 0-2-.701-2-2V6.649A3.495 3.495 0 0 1 0 3.5C0 1.57 1.57 0 3.5 0H5v1h5.061L14 4.556z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M13 5v8s-.035 1-1.035 1h-8S3 14 3 13V9h1v4h8V6H9.397l.517-.52L9 4.572V3H7.419L6.413 2h3.228L13 5z" id="iconBg"/><path class="icon-vs-fg" d="M7.419 3H9v1.572L7.419 3zm1.978 3L6.416 9H4v4h8V6H9.397z" id="iconFg" style="display: none;"/><path class="icon-vs-action-blue" d="M5.988 6H3.5a2.5 2.5 0 1 1 0-5H4v1h-.5C2.673 2 2 2.673 2 3.5S2.673 5 3.5 5h2.513L4 3h2l2.5 2.484L6 8H4l1.988-2z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 929 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 5V2H9V1H0v14h13v-3h3V9h-1V6H9V5h7zm-8 7V9h1v3H8z" id="outline"/><path class="icon-vs-fg" d="M2 3h5v1H2V3z" id="iconFg"/><path class="icon-vs-bg" d="M15 4h-5V3h5v1zm-1 3h-2v1h2V7zm-4 0H1v1h9V7zm2 6H1v1h11v-1zm-5-3H1v1h6v-1zm8 0h-5v1h5v-1zM8 2v3H1V2h7zM7 3H2v1h5V3z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 589 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 5V2H9V1H0v14h13v-3h3V9h-1V6H9V5h7zm-8 7V9h1v3H8z" id="outline"/><path class="icon-vs-fg" d="M2 3h5v1H2V3z" id="iconFg"/><path class="icon-vs-bg" d="M15 4h-5V3h5v1zm-1 3h-2v1h2V7zm-4 0H1v1h9V7zm2 6H1v1h11v-1zm-5-3H1v1h6v-1zm8 0h-5v1h5v-1zM8 2v3H1V2h7zM7 3H2v1h5V3z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 589 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11.5 12c-1.915 0-3.602-1.241-4.228-3h-1.41a3.11 3.11 0 0 1-2.737 1.625C1.402 10.625 0 9.223 0 7.5s1.402-3.125 3.125-3.125c1.165 0 2.201.639 2.737 1.625h1.41c.626-1.759 2.313-3 4.228-3C13.981 3 16 5.019 16 7.5S13.981 12 11.5 12z" id="outline"/><path class="icon-vs-fg" d="M11.5 9A1.501 1.501 0 1 1 13 7.5c0 .826-.673 1.5-1.5 1.5z" id="iconFg"/><path class="icon-vs-action-blue" d="M11.5 4a3.49 3.49 0 0 0-3.45 3H5.185A2.122 2.122 0 0 0 1 7.5a2.123 2.123 0 1 0 4.185.5H8.05a3.49 3.49 0 0 0 3.45 3 3.5 3.5 0 1 0 0-7zm0 5c-.827 0-1.5-.673-1.5-1.5S10.673 6 11.5 6s1.5.673 1.5 1.5S12.327 9 11.5 9z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 923 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11.5 12c-1.915 0-3.602-1.241-4.228-3h-1.41a3.11 3.11 0 0 1-2.737 1.625C1.402 10.625 0 9.223 0 7.5s1.402-3.125 3.125-3.125c1.165 0 2.201.639 2.737 1.625h1.41c.626-1.759 2.313-3 4.228-3C13.981 3 16 5.019 16 7.5S13.981 12 11.5 12z" id="outline"/><path class="icon-vs-fg" d="M11.5 9A1.501 1.501 0 1 1 13 7.5c0 .826-.673 1.5-1.5 1.5z" id="iconFg"/><path class="icon-vs-action-blue" d="M11.5 4a3.49 3.49 0 0 0-3.45 3H5.185A2.122 2.122 0 0 0 1 7.5a2.123 2.123 0 1 0 4.185.5H8.05a3.49 3.49 0 0 0 3.45 3 3.5 3.5 0 1 0 0-7zm0 5c-.827 0-1.5-.673-1.5-1.5S10.673 6 11.5 6s1.5.673 1.5 1.5S12.327 9 11.5 9z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 923 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11 3v1.015L8.733 2.882 5 4.749V3H0v10h5v-1.859l2.156 1.077L11 10.295V13h5V3h-5z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M2 5v6h2v1H1V4h3v1H2zm10 6v1h3V4h-3v1h2v6h-2z" id="iconBg"/><path class="icon-vs-fg" d="M7.156 7.156l-1.578-.789 3.156-1.578 1.578.789-3.156 1.578z" id="iconFg" style="display: none;"/><path class="icon-vs-action-blue" d="M8.733 4L4 6.367v3.156L7.156 11.1l4.733-2.367V5.578L8.733 4zM7.156 7.156l-1.578-.789 3.156-1.578 1.578.789-3.156 1.578z" id="colorImportance"/></svg>

After

Width:  |  Height:  |  Size: 853 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11 3v1.015L8.733 2.882 5 4.749V3H0v10h5v-1.859l2.156 1.077L11 10.295V13h5V3h-5z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M2 5v6h2v1H1V4h3v1H2zm10 6v1h3V4h-3v1h2v6h-2z" id="iconBg"/><path class="icon-vs-fg" d="M7.156 7.156l-1.578-.789 3.156-1.578 1.578.789-3.156 1.578z" id="iconFg" style="display: none;"/><path class="icon-vs-action-blue" d="M8.733 4L4 6.367v3.156L7.156 11.1l4.733-2.367V5.578L8.733 4zM7.156 7.156l-1.578-.789 3.156-1.578 1.578.789-3.156 1.578z" id="colorImportance"/></svg>

After

Width:  |  Height:  |  Size: 853 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-purple{fill:#652d90}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M15 3.349v8.403L8.975 16H8.07L1 11.582V3.327L7.595 0h1.118L15 3.349z" id="outline"/><path class="icon-vs-fg" d="M12.715 4.398L8.487 7.02 3.565 4.272l4.578-2.309 4.572 2.435zM3 5.102l5 2.792v5.705l-5-3.125V5.102zm6 8.434V7.878l4-2.48v5.317l-4 2.821z" id="iconFg"/><path class="icon-vs-action-purple" d="M8.156.837L2 3.942v7.085L8.517 15.1 14 11.233V3.95L8.156.837zm4.559 3.561L8.487 7.02 3.565 4.272l4.578-2.309 4.572 2.435zM3 5.102l5 2.792v5.705l-5-3.125V5.102zm6 8.434V7.878l4-2.48v5.317l-4 2.821z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 831 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-purple{fill:#b180d7}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M15 3.349v8.403L8.975 16H8.07L1 11.582V3.327L7.595 0h1.118L15 3.349z" id="outline"/><path class="icon-vs-fg" d="M12.715 4.398L8.487 7.02 3.565 4.272l4.578-2.309 4.572 2.435zM3 5.102l5 2.792v5.705l-5-3.125V5.102zm6 8.434V7.878l4-2.48v5.317l-4 2.821z" id="iconFg"/><path class="icon-vs-action-purple" d="M8.156.837L2 3.942v7.085L8.517 15.1 14 11.233V3.95L8.156.837zm4.559 3.561L8.487 7.02 3.565 4.272l4.578-2.309 4.572 2.435zM3 5.102l5 2.792v5.705l-5-3.125V5.102zm6 8.434V7.878l4-2.48v5.317l-4 2.821z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 831 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 10c0 2.205-1.794 4-4 4-1.858 0-3.411-1.279-3.858-3h-.978l2.318 4H0v-1.703l2-3.408V0h11v6.142c1.721.447 3 2 3 3.858z" id="outline"/><path class="icon-vs-bg" d="M12 1v4.75A4.255 4.255 0 0 0 7.75 10h-.732L4.275 5.269 3 7.442V1h9zM7.747 14L4.269 8 .748 14h6.999zM15 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 10c0 2.205-1.794 4-4 4-1.858 0-3.411-1.279-3.858-3h-.978l2.318 4H0v-1.703l2-3.408V0h11v6.142c1.721.447 3 2 3 3.858z" id="outline"/><path class="icon-vs-bg" d="M12 1v4.75A4.255 4.255 0 0 0 7.75 10h-.732L4.275 5.269 3 7.442V1h9zM7.747 14L4.269 8 .748 14h6.999zM15 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9.26 11.984l.978-.021a.962.962 0 0 0 .09-.006c.011-.063.026-.179.026-.361V9.688c0-.679.185-1.257.53-1.707-.346-.452-.53-1.03-.53-1.705V4.35c0-.167-.021-.259-.034-.302L9.26 4.02V.973l1.011.011c2.167.024 3.409 1.156 3.409 3.105v1.962c0 .351.071.461.072.462l.936.06.053.927v1.936l-.936.061c-.076.016-.125.146-.125.424v2.017c0 .914-.332 3.043-3.408 3.078l-1.012.011v-3.043zm-3.521 3.032c-3.089-.035-3.422-2.164-3.422-3.078V9.921c0-.327-.066-.432-.067-.433l-.937-.06-.063-.929V6.563l.942-.06c.058 0 .125-.114.125-.452V4.09c0-1.949 1.248-3.081 3.422-3.105L6.75.973V4.02l-.975.023a.572.572 0 0 0-.093.01c.006.021-.019.115-.019.297v1.928c0 .675-.186 1.253-.534 1.705.348.45.534 1.028.534 1.707v1.907c0 .175.014.291.027.363.023.002 1.06.025 1.06.025v3.043l-1.011-.012z" id="outline"/><path class="icon-vs-bg" d="M5.75 14.016c-1.623-.019-2.434-.711-2.434-2.078V9.921c0-.902-.355-1.376-1.066-1.422v-.998c.711-.045 1.066-.529 1.066-1.449V4.09c0-1.385.811-2.087 2.434-2.105v1.06c-.725.017-1.087.453-1.087 1.305v1.928c0 .92-.454 1.488-1.36 1.702V8c.907.201 1.36.763 1.36 1.688v1.907c0 .488.081.835.243 1.042.162.208.443.316.844.325v1.054zm7.99-5.517c-.706.045-1.06.52-1.06 1.422v2.017c0 1.367-.807 2.06-2.42 2.078v-1.053c.396-.009.678-.118.844-.328.167-.21.25-.556.25-1.039V9.688c0-.925.449-1.488 1.347-1.688v-.021c-.898-.214-1.347-.782-1.347-1.702V4.35c0-.852-.364-1.288-1.094-1.306v-1.06c1.613.018 2.42.72 2.42 2.105v1.962c0 .92.354 1.404 1.06 1.449v.999z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9.26 11.984l.978-.021a.962.962 0 0 0 .09-.006c.011-.063.026-.179.026-.361V9.688c0-.679.185-1.257.53-1.707-.346-.452-.53-1.03-.53-1.705V4.35c0-.167-.021-.259-.034-.302L9.26 4.02V.973l1.011.011c2.167.024 3.409 1.156 3.409 3.105v1.962c0 .351.071.461.072.462l.936.06.053.927v1.936l-.936.061c-.076.016-.125.146-.125.424v2.017c0 .914-.332 3.043-3.408 3.078l-1.012.011v-3.043zm-3.521 3.032c-3.089-.035-3.422-2.164-3.422-3.078V9.921c0-.327-.066-.432-.067-.433l-.937-.06-.063-.929V6.563l.942-.06c.058 0 .125-.114.125-.452V4.09c0-1.949 1.248-3.081 3.422-3.105L6.75.973V4.02l-.975.023a.572.572 0 0 0-.093.01c.006.021-.019.115-.019.297v1.928c0 .675-.186 1.253-.534 1.705.348.45.534 1.028.534 1.707v1.907c0 .175.014.291.027.363.023.002 1.06.025 1.06.025v3.043l-1.011-.012z" id="outline"/><path class="icon-vs-bg" d="M5.75 14.016c-1.623-.019-2.434-.711-2.434-2.078V9.921c0-.902-.355-1.376-1.066-1.422v-.998c.711-.045 1.066-.529 1.066-1.449V4.09c0-1.385.811-2.087 2.434-2.105v1.06c-.725.017-1.087.453-1.087 1.305v1.928c0 .92-.454 1.488-1.36 1.702V8c.907.201 1.36.763 1.36 1.688v1.907c0 .488.081.835.243 1.042.162.208.443.316.844.325v1.054zm7.99-5.517c-.706.045-1.06.52-1.06 1.422v2.017c0 1.367-.807 2.06-2.42 2.078v-1.053c.396-.009.678-.118.844-.328.167-.21.25-.556.25-1.039V9.688c0-.925.449-1.488 1.347-1.688v-.021c-.898-.214-1.347-.782-1.347-1.702V4.35c0-.852-.364-1.288-1.094-1.306v-1.06c1.613.018 2.42.72 2.42 2.105v1.962c0 .92.354 1.404 1.06 1.449v.999z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-fg{fill:#f0eff1}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 16H0V0h16v16z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M1 1v14h14V1H1zm6 12H3v-1h4v1zm0-3H3V9h4v1zm0-5H5v2H4V5H2V4h2V2h1v2h2v1zm3.281 8H8.719l3-4h1.563l-3.001 4zM14 5H9V4h5v1z" id="iconBg"/><path class="icon-vs-fg" d="M7 5H5v2H4V5H2V4h2V2h1v2h2v1zm7-1H9v1h5V4zM7 9H3v1h4V9zm0 3H3v1h4v-1zm3.281 1l3-4h-1.563l-3 4h1.563z" id="iconFg" style="display: none;"/></svg>

After

Width:  |  Height:  |  Size: 710 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-fg{fill:#2b282e}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 16H0V0h16v16z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M1 1v14h14V1H1zm6 12H3v-1h4v1zm0-3H3V9h4v1zm0-5H5v2H4V5H2V4h2V2h1v2h2v1zm3.281 8H8.719l3-4h1.563l-3.001 4zM14 5H9V4h5v1z" id="iconBg"/><path class="icon-vs-fg" d="M7 5H5v2H4V5H2V4h2V2h1v2h2v1zm7-1H9v1h5V4zM7 9H3v1h4V9zm0 3H3v1h4v-1zm3.281 1l3-4h-1.563l-3 4h1.563z" id="iconFg" style="display: none;"/></svg>

After

Width:  |  Height:  |  Size: 710 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 5.5a5.5 5.5 0 0 1-5.5 5.5c-.275 0-.543-.027-.807-.066l-.079-.012a5.429 5.429 0 0 1-.81-.192l-4.537 4.537c-.472.473-1.1.733-1.767.733s-1.295-.26-1.768-.732a2.502 2.502 0 0 1 0-3.535l4.537-4.537a5.452 5.452 0 0 1-.191-.812c-.005-.025-.008-.051-.012-.077A5.503 5.503 0 0 1 5 5.5a5.5 5.5 0 1 1 11 0z" id="outline"/><path class="icon-vs-bg" d="M15 5.5a4.5 4.5 0 0 1-4.5 4.5c-.693 0-1.342-.17-1.929-.45l-5.01 5.01c-.293.294-.677.44-1.061.44s-.768-.146-1.061-.439a1.5 1.5 0 0 1 0-2.121l5.01-5.01A4.483 4.483 0 0 1 6 5.5 4.5 4.5 0 0 1 10.5 1c.693 0 1.342.17 1.929.45L9.636 4.243l2.121 2.121 2.793-2.793c.28.587.45 1.236.45 1.929z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 922 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 5.5a5.5 5.5 0 0 1-5.5 5.5c-.275 0-.543-.027-.807-.066l-.079-.012a5.429 5.429 0 0 1-.81-.192l-4.537 4.537c-.472.473-1.1.733-1.767.733s-1.295-.26-1.768-.732a2.502 2.502 0 0 1 0-3.535l4.537-4.537a5.452 5.452 0 0 1-.191-.812c-.005-.025-.008-.051-.012-.077A5.503 5.503 0 0 1 5 5.5a5.5 5.5 0 1 1 11 0z" id="outline"/><path class="icon-vs-bg" d="M15 5.5a4.5 4.5 0 0 1-4.5 4.5c-.693 0-1.342-.17-1.929-.45l-5.01 5.01c-.293.294-.677.44-1.061.44s-.768-.146-1.061-.439a1.5 1.5 0 0 1 0-2.121l5.01-5.01A4.483 4.483 0 0 1 6 5.5 4.5 4.5 0 0 1 10.5 1c.693 0 1.342.17 1.929.45L9.636 4.243l2.121 2.121 2.793-2.793c.28.587.45 1.236.45 1.929z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 922 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 11.013H1V4h15v7.013z" id="outline"/><path class="icon-vs-fg" d="M8 9H7V6h3v3H9V7H8v2zM4 7h1v2h1V6H3v3h1V7zm8 0h1v2h1V6h-3v3h1V7z" id="iconFg"/><path class="icon-vs-bg" d="M2 5v5h13V5H2zm4 4H5V7H4v2H3V6h3v3zm4 0H9V7H8v2H7V6h3v3zm4 0h-1V7h-1v2h-1V6h3v3z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 11.013H1V4h15v7.013z" id="outline"/><path class="icon-vs-fg" d="M8 9H7V6h3v3H9V7H8v2zM4 7h1v2h1V6H3v3h1V7zm8 0h1v2h1V6h-3v3h1V7z" id="iconFg"/><path class="icon-vs-bg" d="M2 5v5h13V5H2zm4 4H5V7H4v2H3V6h3v3zm4 0H9V7H8v2H7V6h3v3zm4 0h-1V7h-1v2h-1V6h3v3z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg4694"
viewBox="0 0 16 16">
<metadata
id="metadata4705">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4703" />
<style
id="style4696">.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-orange{fill:#c27d1a}</style>
<g
id="g4707"
transform="matrix(1.3333333,0,0,1.3333333,-245.99999,-5.333333)">
<path
d="m 185,4 11,0 0,12 -11,0 z"
id="path4534"
style="fill:#f6f6f6" />
<path
d="m 194,13 0,-7 -7,0 0,7 -1,0 0,-8 9,0 0,8 -1,0 z m -7,2 -1,0 0,-1 1,0 0,1 z m 2,-1 -1,0 0,1 1,0 0,-1 z m 2,0 -1,0 0,1 1,0 0,-1 z m 2,1 -1,0 0,-1 1,0 0,1 z m 2,-1 -1,0 0,1 1,0 0,-1 z"
id="path4536"
style="fill:#424242" />
<path
d="m 187,13 0,-7 7,0 0,7 -7,0 z"
id="path4538"
style="fill:#f0eff1" />
</g>
<path
id="canvas"
d="M16 16H0V0h16v16z"
class="icon-canvas-transparent" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg4694"
viewBox="0 0 16 16">
<metadata
id="metadata4705">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4703" />
<style
id="style4696">.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-orange{fill:#c27d1a}</style>
<g
id="g4724"
transform="matrix(1.3333333,0,0,1.3333333,-245.99999,-31.999999)">
<path
d="m 185,24 11,0 0,12 -11,0 z"
id="path4528"
style="fill:#2d2d30" />
<path
d="m 194,33 0,-7 -7,0 0,7 -1,0 0,-8 9,0 0,8 z m -8,1 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z"
id="path4530"
style="fill:#c5c5c5" />
<path
d="m 187,26 7,0 0,7 -7,0 z"
id="path4532"
style="fill:#2b282e" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 15H0V1h16v14z" id="outline"/><path class="icon-vs-fg" d="M9.229 7.354c.035.146.052.31.052.494 0 .234-.02.441-.06.621-.039.18-.095.328-.168.445a.687.687 0 0 1-.914.281.76.76 0 0 1-.237-.207.988.988 0 0 1-.154-.306 1.262 1.262 0 0 1-.057-.381v-.506c0-.17.02-.326.061-.465s.096-.258.168-.359a.756.756 0 0 1 .257-.232c.1-.055.21-.082.331-.082a.646.646 0 0 1 .571.32c.067.105.116.23.15.377zm-5.126.869a.557.557 0 0 0-.196.132c-.047.053-.08.112-.097.18s-.028.147-.028.233a.513.513 0 0 0 .157.39.528.528 0 0 0 .186.113.682.682 0 0 0 .242.041.76.76 0 0 0 .593-.271.897.897 0 0 0 .165-.295c.038-.113.059-.234.059-.365v-.346l-.761.11a1.29 1.29 0 0 0-.32.078zM14 3v10H2V3h12zM5.962 7.469c0-.238-.027-.451-.083-.637a1.286 1.286 0 0 0-.249-.471 1.08 1.08 0 0 0-.424-.295 1.644 1.644 0 0 0-.608-.101c-.119 0-.241.012-.368.033a3.213 3.213 0 0 0-.673.195 1.313 1.313 0 0 0-.212.114v.768c.158-.132.341-.235.544-.313.204-.078.413-.117.627-.117.213 0 .377.063.494.186.116.125.174.324.174.6l-1.03.154c-.205.026-.38.077-.526.151a1.083 1.083 0 0 0-.563.66A1.562 1.562 0 0 0 3 8.857c0 .17.025.323.074.463a.945.945 0 0 0 .568.596c.139.057.297.084.478.084.229 0 .431-.053.604-.16a1.3 1.3 0 0 0 .439-.463h.014v.529h.785V7.469zM10 7.861a3.54 3.54 0 0 0-.074-.734 2.047 2.047 0 0 0-.228-.611 1.203 1.203 0 0 0-.394-.416 1.03 1.03 0 0 0-.574-.153c-.123 0-.234.018-.336.051a1 1 0 0 0-.278.147 1.153 1.153 0 0 0-.225.222 2.022 2.022 0 0 0-.181.289h-.013V5H7v4.887h.697v-.485h.013c.044.082.095.158.151.229.057.07.119.133.191.186a.835.835 0 0 0 .238.121.943.943 0 0 0 .293.042c.23 0 .434-.053.609-.16a1.34 1.34 0 0 0 .443-.443c.12-.188.211-.412.272-.672A3.62 3.62 0 0 0 10 7.861zm3-1.658a.7.7 0 0 0-.106-.066 1.183 1.183 0 0 0-.142-.063 1.233 1.233 0 0 0-.363-.065c-.209 0-.399.051-.569.15a1.355 1.355 0 0 0-.433.424c-.118.182-.21.402-.273.66a3.63 3.63 0 0 0-.008 1.615c.06.23.143.43.252.602.109.168.241.303.396.396a.972.972 0 0 0 .524.144c.158 0 .296-.021.413-.068.117-.045.219-.108.309-.184v-.77a1.094 1.094 0 0 1-.288.225.819.819 0 0 1-.158.068.48.48 0 0 1-.153.027.62.62 0 0 1-.274-.074c-.241-.136-.423-.479-.423-1.146 0-.715.206-1.12.469-1.301.077-.032.153-.064.238-.064.113 0 .22.027.317.082.096.057.188.131.272.223v-.815z" id="iconFg"/><path class="icon-vs-bg" d="M1 2v12h14V2H1zm13 11H2V3h12v10zM5.63 6.361a1.08 1.08 0 0 0-.424-.295 1.644 1.644 0 0 0-.608-.101c-.119 0-.241.012-.368.033a3.213 3.213 0 0 0-.673.195 1.313 1.313 0 0 0-.212.114v.768c.158-.132.341-.235.544-.313.204-.078.413-.117.627-.117.213 0 .377.063.494.186.116.125.174.324.174.6l-1.03.154c-.205.026-.38.077-.526.151a1.083 1.083 0 0 0-.563.66A1.562 1.562 0 0 0 3 8.857c0 .17.025.323.074.463a.945.945 0 0 0 .568.596c.139.057.297.084.478.084.229 0 .431-.053.604-.16a1.3 1.3 0 0 0 .439-.463h.014v.529h.785V7.469c0-.238-.027-.451-.083-.637a1.286 1.286 0 0 0-.249-.471zm-.446 2.02c0 .131-.02.252-.059.365a.897.897 0 0 1-.165.295.758.758 0 0 1-.593.272.682.682 0 0 1-.242-.041.507.507 0 0 1-.302-.286.583.583 0 0 1-.041-.218c0-.086.01-.164.027-.232s.051-.127.098-.18a.546.546 0 0 1 .196-.133c.083-.033.189-.061.32-.078l.761-.109v.345zm4.514-1.865a1.203 1.203 0 0 0-.394-.416 1.03 1.03 0 0 0-.574-.153c-.123 0-.234.018-.336.051a1 1 0 0 0-.278.147 1.153 1.153 0 0 0-.225.222 2.022 2.022 0 0 0-.181.289h-.013V5H7v4.887h.697v-.485h.013c.044.082.095.158.151.229.057.07.119.133.191.186a.835.835 0 0 0 .238.121.943.943 0 0 0 .293.042c.23 0 .434-.053.609-.16a1.34 1.34 0 0 0 .443-.443c.12-.188.211-.412.272-.672A3.62 3.62 0 0 0 10 7.861a3.54 3.54 0 0 0-.074-.734 2.047 2.047 0 0 0-.228-.611zm-.476 1.953c-.039.18-.095.328-.168.445a.755.755 0 0 1-.264.266.687.687 0 0 1-.651.015.76.76 0 0 1-.237-.207.988.988 0 0 1-.154-.306 1.262 1.262 0 0 1-.057-.381v-.506c0-.17.02-.326.061-.465s.096-.258.168-.359a.756.756 0 0 1 .257-.232c.1-.055.21-.082.331-.082a.646.646 0 0 1 .571.32c.066.105.116.23.15.377.035.146.052.31.052.494 0 .234-.019.441-.059.621zm3.672-2.332a.7.7 0 0 1 .106.066v.814a1.178 1.178 0 0 0-.273-.223.645.645 0 0 0-.317-.081c-.085 0-.161.032-.238.064-.263.181-.469.586-.469 1.301 0 .668.182 1.011.423 1.146.084.04.171.074.274.074.049 0 .101-.01.153-.027a.856.856 0 0 0 .158-.068 1.16 1.16 0 0 0 .288-.225v.77c-.09.076-.192.139-.309.184a1.098 1.098 0 0 1-.412.068.974.974 0 0 1-.523-.143 1.257 1.257 0 0 1-.396-.396 2.098 2.098 0 0 1-.252-.602 3.118 3.118 0 0 1-.088-.754c0-.316.032-.604.096-.861.063-.258.155-.479.273-.66.119-.182.265-.322.433-.424a1.102 1.102 0 0 1 1.073-.023z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}.icon-vs-fg{fill:#2b282e}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 15H0V1h16v14z" id="outline"/><path class="icon-vs-fg" d="M9.229 7.354c.035.146.052.31.052.494 0 .234-.02.441-.06.621-.039.18-.095.328-.168.445a.687.687 0 0 1-.914.281.76.76 0 0 1-.237-.207.988.988 0 0 1-.154-.306 1.262 1.262 0 0 1-.057-.381v-.506c0-.17.02-.326.061-.465s.096-.258.168-.359a.756.756 0 0 1 .257-.232c.1-.055.21-.082.331-.082a.646.646 0 0 1 .571.32c.067.105.116.23.15.377zm-5.126.869a.557.557 0 0 0-.196.132c-.047.053-.08.112-.097.18s-.028.147-.028.233a.513.513 0 0 0 .157.39.528.528 0 0 0 .186.113.682.682 0 0 0 .242.041.76.76 0 0 0 .593-.271.897.897 0 0 0 .165-.295c.038-.113.059-.234.059-.365v-.346l-.761.11a1.29 1.29 0 0 0-.32.078zM14 3v10H2V3h12zM5.962 7.469c0-.238-.027-.451-.083-.637a1.286 1.286 0 0 0-.249-.471 1.08 1.08 0 0 0-.424-.295 1.644 1.644 0 0 0-.608-.101c-.119 0-.241.012-.368.033a3.213 3.213 0 0 0-.673.195 1.313 1.313 0 0 0-.212.114v.768c.158-.132.341-.235.544-.313.204-.078.413-.117.627-.117.213 0 .377.063.494.186.116.125.174.324.174.6l-1.03.154c-.205.026-.38.077-.526.151a1.083 1.083 0 0 0-.563.66A1.562 1.562 0 0 0 3 8.857c0 .17.025.323.074.463a.945.945 0 0 0 .568.596c.139.057.297.084.478.084.229 0 .431-.053.604-.16a1.3 1.3 0 0 0 .439-.463h.014v.529h.785V7.469zM10 7.861a3.54 3.54 0 0 0-.074-.734 2.047 2.047 0 0 0-.228-.611 1.203 1.203 0 0 0-.394-.416 1.03 1.03 0 0 0-.574-.153c-.123 0-.234.018-.336.051a1 1 0 0 0-.278.147 1.153 1.153 0 0 0-.225.222 2.022 2.022 0 0 0-.181.289h-.013V5H7v4.887h.697v-.485h.013c.044.082.095.158.151.229.057.07.119.133.191.186a.835.835 0 0 0 .238.121.943.943 0 0 0 .293.042c.23 0 .434-.053.609-.16a1.34 1.34 0 0 0 .443-.443c.12-.188.211-.412.272-.672A3.62 3.62 0 0 0 10 7.861zm3-1.658a.7.7 0 0 0-.106-.066 1.183 1.183 0 0 0-.142-.063 1.233 1.233 0 0 0-.363-.065c-.209 0-.399.051-.569.15a1.355 1.355 0 0 0-.433.424c-.118.182-.21.402-.273.66a3.63 3.63 0 0 0-.008 1.615c.06.23.143.43.252.602.109.168.241.303.396.396a.972.972 0 0 0 .524.144c.158 0 .296-.021.413-.068.117-.045.219-.108.309-.184v-.77a1.094 1.094 0 0 1-.288.225.819.819 0 0 1-.158.068.48.48 0 0 1-.153.027.62.62 0 0 1-.274-.074c-.241-.136-.423-.479-.423-1.146 0-.715.206-1.12.469-1.301.077-.032.153-.064.238-.064.113 0 .22.027.317.082.096.057.188.131.272.223v-.815z" id="iconFg"/><path class="icon-vs-bg" d="M1 2v12h14V2H1zm13 11H2V3h12v10zM5.63 6.361a1.08 1.08 0 0 0-.424-.295 1.644 1.644 0 0 0-.608-.101c-.119 0-.241.012-.368.033a3.213 3.213 0 0 0-.673.195 1.313 1.313 0 0 0-.212.114v.768c.158-.132.341-.235.544-.313.204-.078.413-.117.627-.117.213 0 .377.063.494.186.116.125.174.324.174.6l-1.03.154c-.205.026-.38.077-.526.151a1.083 1.083 0 0 0-.563.66A1.562 1.562 0 0 0 3 8.857c0 .17.025.323.074.463a.945.945 0 0 0 .568.596c.139.057.297.084.478.084.229 0 .431-.053.604-.16a1.3 1.3 0 0 0 .439-.463h.014v.529h.785V7.469c0-.238-.027-.451-.083-.637a1.286 1.286 0 0 0-.249-.471zm-.446 2.02c0 .131-.02.252-.059.365a.897.897 0 0 1-.165.295.758.758 0 0 1-.593.272.682.682 0 0 1-.242-.041.507.507 0 0 1-.302-.286.583.583 0 0 1-.041-.218c0-.086.01-.164.027-.232s.051-.127.098-.18a.546.546 0 0 1 .196-.133c.083-.033.189-.061.32-.078l.761-.109v.345zm4.514-1.865a1.203 1.203 0 0 0-.394-.416 1.03 1.03 0 0 0-.574-.153c-.123 0-.234.018-.336.051a1 1 0 0 0-.278.147 1.153 1.153 0 0 0-.225.222 2.022 2.022 0 0 0-.181.289h-.013V5H7v4.887h.697v-.485h.013c.044.082.095.158.151.229.057.07.119.133.191.186a.835.835 0 0 0 .238.121.943.943 0 0 0 .293.042c.23 0 .434-.053.609-.16a1.34 1.34 0 0 0 .443-.443c.12-.188.211-.412.272-.672A3.62 3.62 0 0 0 10 7.861a3.54 3.54 0 0 0-.074-.734 2.047 2.047 0 0 0-.228-.611zm-.476 1.953c-.039.18-.095.328-.168.445a.755.755 0 0 1-.264.266.687.687 0 0 1-.651.015.76.76 0 0 1-.237-.207.988.988 0 0 1-.154-.306 1.262 1.262 0 0 1-.057-.381v-.506c0-.17.02-.326.061-.465s.096-.258.168-.359a.756.756 0 0 1 .257-.232c.1-.055.21-.082.331-.082a.646.646 0 0 1 .571.32c.066.105.116.23.15.377.035.146.052.31.052.494 0 .234-.019.441-.059.621zm3.672-2.332a.7.7 0 0 1 .106.066v.814a1.178 1.178 0 0 0-.273-.223.645.645 0 0 0-.317-.081c-.085 0-.161.032-.238.064-.263.181-.469.586-.469 1.301 0 .668.182 1.011.423 1.146.084.04.171.074.274.074.049 0 .101-.01.153-.027a.856.856 0 0 0 .158-.068 1.16 1.16 0 0 0 .288-.225v.77c-.09.076-.192.139-.309.184a1.098 1.098 0 0 1-.412.068.974.974 0 0 1-.523-.143 1.257 1.257 0 0 1-.396-.396 2.098 2.098 0 0 1-.252-.602 3.118 3.118 0 0 1-.088-.754c0-.316.032-.604.096-.861.063-.258.155-.479.273-.66.119-.182.265-.322.433-.424a1.102 1.102 0 0 1 1.073-.023z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-action-blue{fill:#00539c}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9 14V8H7v6H1V2h14v12H9z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M10 9h4v4h-4V9zm-8 4h4V9H2v4zM2 3v4h12V3H2z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 449 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-action-blue{fill:#75beff}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M9 14V8H7v6H1V2h14v12H9z" id="outline" style="display: none;"/><path class="icon-vs-action-blue" d="M10 9h4v4h-4V9zm-8 4h4V9H2v4zM2 3v4h12V3H2z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 449 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M10.702 10.5l2-2-2-2 .5-.5H10v5h1v3H5v-3h1V6H4.798l.5.5-2 2 2 2L3 12.797l-3-3V7.201l3-3V2h10v2.201l3 3v2.596l-3 3-2.298-2.297z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M4 3h8v2h-1v-.5c0-.277-.224-.5-.5-.5H9v7.5c0 .275.224.5.5.5h.5v1H6v-1h.5a.5.5 0 0 0 .5-.5V4H5.5a.5.5 0 0 0-.5.5V5H4V3zM3 5.615L.116 8.5 3 11.383l.884-.883-2-2 2-2L3 5.615zm10 0l-.884.885 2 2-2 2 .884.883L15.884 8.5 13 5.615z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#2d2d30}.icon-vs-out{fill:#2d2d30}.icon-vs-bg{fill:#c5c5c5}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M10.702 10.5l2-2-2-2 .5-.5H10v5h1v3H5v-3h1V6H4.798l.5.5-2 2 2 2L3 12.797l-3-3V7.201l3-3V2h10v2.201l3 3v2.596l-3 3-2.298-2.297z" id="outline" style="display: none;"/><path class="icon-vs-bg" d="M4 3h8v2h-1v-.5c0-.277-.224-.5-.5-.5H9v7.5c0 .275.224.5.5.5h.5v1H6v-1h.5a.5.5 0 0 0 .5-.5V4H5.5a.5.5 0 0 0-.5.5V5H4V3zM3 5.615L.116 8.5 3 11.383l.884-.883-2-2 2-2L3 5.615zm10 0l-.884.885 2 2-2 2 .884.883L15.884 8.5 13 5.615z" id="iconBg"/></svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#e8e8e8" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#424242" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" fill="#1BA1E2"/><path d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 243 B

View File

@@ -0,0 +1,322 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Suggest widget*/
.monaco-editor .suggest-widget {
z-index: 40;
}
/** Initial widths **/
.monaco-editor .suggest-widget {
width: 430px;
}
.monaco-editor .suggest-widget > .message,
.monaco-editor .suggest-widget > .tree,
.monaco-editor .suggest-widget > .details {
width: 100%;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
}
.monaco-editor.hc-black .suggest-widget > .message,
.monaco-editor.hc-black .suggest-widget > .tree,
.monaco-editor.hc-black .suggest-widget > .details {
border-width: 2px;
}
/** Adjust width when docs are expanded to the side **/
.monaco-editor .suggest-widget.docs-side {
width: 660px;
}
.monaco-editor .suggest-widget.docs-side > .tree,
.monaco-editor .suggest-widget.docs-side > .details {
width: 50%;
float: left;
}
.monaco-editor .suggest-widget.docs-side.list-right > .tree,
.monaco-editor .suggest-widget.docs-side.list-right > .details {
float: right;
}
/* Styles for Message element for when widget is loading or is empty */
.monaco-editor .suggest-widget > .message {
padding-left: 22px;
}
/** Styles for the list element **/
.monaco-editor .suggest-widget > .tree {
height: 100%;
}
/** Styles for each row in the list element **/
.monaco-editor .suggest-widget .monaco-list .monaco-list-row {
display: flex;
-mox-box-sizing: border-box;
box-sizing: border-box;
padding-right: 10px;
background-repeat: no-repeat;
background-position: 2px 2px;
white-space: nowrap;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents {
flex: 1;
height: 100%;
overflow: hidden;
padding-left: 2px;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main {
display: flex;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
}
.monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight {
font-weight: bold;
}
/** Icon styles **/
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .readMore {
opacity: 0.6;
background-position: center center;
background-repeat: no-repeat;
background-size: 70%;
cursor: pointer;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close {
background-image: url('./close.svg');
float: right;
margin-right: 5px;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .readMore {
background-image: url('./info.svg');
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close:hover,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .readMore:hover {
opacity: 1;
}
/** Type Info and icon next to the label in the focused completion item **/
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .type-label {
margin-left: 0.8em;
flex: 1;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
opacity: 0.7;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .type-label > .monaco-tokenized-source {
display: inline;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .readMore,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main > .type-label,
.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused > .contents > .main > .readMore,
.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused > .contents > .main > .type-label,
.monaco-editor .suggest-widget.docs-below .monaco-list .monaco-list-row.focused > .contents > .main > .readMore {
display: none;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused > .contents > .main > .readMore,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused > .contents > .main > .type-label {
display: inline;
}
/** Styles for each row in the list **/
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon {
display: block;
height: 16px;
width: 16px;
background-repeat: no-repeat;
background-size: 80%;
background-position: center;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon { background-image: url('Misc_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.method,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.function,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constructor { background-image: url('Method_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.field { background-image: url('Field_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.event { background-image: url('Event_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.operator { background-image: url('Operator_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.variable { background-image: url('LocalVariable_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.class { background-image: url('Class_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.interface { background-image: url('Interface_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.struct { background-image: url('Structure_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter { background-image: url('Template_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.module { background-image: url('Namespace_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.property { background-image: url('Property_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.unit { background-image: url('Ruler_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constant { background-image: url('Constant_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.value,
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum { background-image: url('Enumerator_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum-member { background-image: url('EnumItem_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.keyword { background-image: url('IntelliSenseKeyword_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.text { background-image: url('String_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.color { background-image: url('ColorPalette_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.file { background-image: url('Document_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.reference { background-image: url('ImportFile_16x_vscode.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.snippet { background-image: url('Snippet_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor { background-image: none; }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.folder { background-image: url('Folder_16x.svg'); }
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor .colorspan {
margin: 0 0 0 0.3em;
border: 0.1em solid #000;
width: 0.7em;
height: 0.7em;
display: inline-block;
}
/** Styles for the docs of the completion item in focus **/
.monaco-editor .suggest-widget .details {
display: flex;
flex-direction: column;
cursor: default;
}
.monaco-editor .suggest-widget .details.no-docs {
display: none;
}
.monaco-editor .suggest-widget.docs-below .details {
border-top-width: 0px;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element {
flex: 1;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body {
position: absolute;
box-sizing: border-box;
height: 100%;
width: 100%;
white-space: pre-wrap;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .type {
flex: 2;
overflow: hidden;
text-overflow: ellipsis;
opacity: 0.7;
word-break: break-all;
margin: 0;
padding: 4px 0 4px 5px;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs {
margin: 0;
padding: 4px 5px;
}
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > p:empty {
display: none;
}
/* High Contrast and Dark Theming */
.monaco-editor.vs-dark .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close,
.monaco-editor.hc-black .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close {
background-image: url('./close-dark.svg');
}
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon { background-image: url('Misc_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.method,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.method,
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.function,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.function,
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constructor,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constructor { background-image: url('Method_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.field,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.field { background-image: url('Field_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.event,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.event { background-image: url('Event_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.operator,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.operator { background-image: url('Operator_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.variable,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.variable { background-image: url('LocalVariable_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.class,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.class { background-image: url('Class_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.interface,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.interface { background-image: url('Interface_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.struct,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.struct { background-image: url('Structure_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter { background-image: url('Template_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.module,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.module { background-image: url('Namespace_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.property,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.property { background-image: url('Property_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.unit,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.unit { background-image: url('Ruler_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constant,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constant { background-image: url('Constant_16x_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.value,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.value,
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum { background-image: url('Enumerator_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum-member,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum-member { background-image: url('EnumItem_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.keyword,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.keyword { background-image: url('IntelliSenseKeyword_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.text,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.text { background-image: url('String_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.color,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.color { background-image: url('ColorPalette_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.file,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.file { background-image: url('Document_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.reference,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.reference { background-image: url('ImportFile_16x_vscode_inverse.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.snippet,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.snippet { background-image: url('Snippet_inverse_16x.svg'); }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.customcolor,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.customcolor { background-image: none; }
.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.folder,
.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.folder { background-image: url('Folder_inverse_16x.svg'); }

View File

@@ -0,0 +1,245 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { sequence, asWinJsPromise } from 'vs/base/common/async';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { compareIgnoreCase } from 'vs/base/common/strings';
import { assign } from 'vs/base/common/objects';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { IModel, IEditorContribution, ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { ISuggestResult, ISuggestSupport, ISuggestion, SuggestRegistry } from 'vs/editor/common/modes';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
export const Context = {
Visible: new RawContextKey<boolean>('suggestWidgetVisible', false),
MultipleSuggestions: new RawContextKey<boolean>('suggestWidgetMultipleSuggestions', false),
MakesTextEdit: new RawContextKey('suggestionMakesTextEdit', true),
AcceptOnKey: new RawContextKey<boolean>('suggestionSupportsAcceptOnKey', true),
AcceptSuggestionsOnEnter: new RawContextKey<boolean>('acceptSuggestionOnEnter', true)
};
export interface ISuggestionItem {
position: IPosition;
suggestion: ISuggestion;
container: ISuggestResult;
support: ISuggestSupport;
resolve(): TPromise<void>;
}
export type SnippetConfig = 'top' | 'bottom' | 'inline' | 'none';
let _snippetSuggestSupport: ISuggestSupport;
export function setSnippetSuggestSupport(support: ISuggestSupport): ISuggestSupport {
const old = _snippetSuggestSupport;
_snippetSuggestSupport = support;
return old;
}
export function provideSuggestionItems(model: IModel, position: Position, snippetConfig: SnippetConfig = 'bottom', onlyFrom?: ISuggestSupport[]): TPromise<ISuggestionItem[]> {
const allSuggestions: ISuggestionItem[] = [];
const acceptSuggestion = createSuggesionFilter(snippetConfig);
position = position.clone();
// get provider groups, always add snippet suggestion provider
const supports = SuggestRegistry.orderedGroups(model);
// add snippets provider unless turned off
if (snippetConfig !== 'none' && _snippetSuggestSupport) {
supports.unshift([_snippetSuggestSupport]);
}
// add suggestions from contributed providers - providers are ordered in groups of
// equal score and once a group produces a result the process stops
let hasResult = false;
const factory = supports.map(supports => {
return () => {
// stop when we have a result
if (hasResult) {
return undefined;
}
// for each support in the group ask for suggestions
return TPromise.join(supports.map(support => {
if (!isFalsyOrEmpty(onlyFrom) && onlyFrom.indexOf(support) < 0) {
return undefined;
}
return asWinJsPromise(token => support.provideCompletionItems(model, position, token)).then(container => {
const len = allSuggestions.length;
if (container && !isFalsyOrEmpty(container.suggestions)) {
for (let suggestion of container.suggestions) {
if (acceptSuggestion(suggestion)) {
fixOverwriteBeforeAfter(suggestion, container);
allSuggestions.push({
position,
container,
suggestion,
support,
resolve: createSuggestionResolver(support, suggestion, model, position)
});
}
}
}
if (len !== allSuggestions.length && support !== _snippetSuggestSupport) {
hasResult = true;
}
}, onUnexpectedExternalError);
}));
};
});
const result = sequence(factory).then(() => allSuggestions.sort(getSuggestionComparator(snippetConfig)));
// result.then(items => {
// console.log(model.getWordUntilPosition(position), items.map(item => `${item.suggestion.label}, type=${item.suggestion.type}, incomplete?${item.container.incomplete}, overwriteBefore=${item.suggestion.overwriteBefore}`));
// return items;
// }, err => {
// console.warn(model.getWordUntilPosition(position), err);
// });
return result;
}
function fixOverwriteBeforeAfter(suggestion: ISuggestion, container: ISuggestResult): void {
if (typeof suggestion.overwriteBefore !== 'number') {
suggestion.overwriteBefore = 0;
}
if (typeof suggestion.overwriteAfter !== 'number' || suggestion.overwriteAfter < 0) {
suggestion.overwriteAfter = 0;
}
}
function createSuggestionResolver(provider: ISuggestSupport, suggestion: ISuggestion, model: IModel, position: Position): () => TPromise<void> {
return () => {
if (typeof provider.resolveCompletionItem === 'function') {
return asWinJsPromise(token => provider.resolveCompletionItem(model, position, suggestion, token))
.then(value => { assign(suggestion, value); });
}
return TPromise.as(void 0);
};
}
function createSuggesionFilter(snippetConfig: SnippetConfig): (candidate: ISuggestion) => boolean {
if (snippetConfig === 'none') {
return suggestion => suggestion.type !== 'snippet';
} else {
return () => true;
}
}
function defaultComparator(a: ISuggestionItem, b: ISuggestionItem): number {
let ret = 0;
// check with 'sortText'
if (typeof a.suggestion.sortText === 'string' && typeof b.suggestion.sortText === 'string') {
ret = compareIgnoreCase(a.suggestion.sortText, b.suggestion.sortText);
}
// check with 'label'
if (ret === 0) {
ret = compareIgnoreCase(a.suggestion.label, b.suggestion.label);
}
// check with 'type' and lower snippets
if (ret === 0 && a.suggestion.type !== b.suggestion.type) {
if (a.suggestion.type === 'snippet') {
ret = 1;
} else if (b.suggestion.type === 'snippet') {
ret = -1;
}
}
return ret;
}
function snippetUpComparator(a: ISuggestionItem, b: ISuggestionItem): number {
if (a.suggestion.type !== b.suggestion.type) {
if (a.suggestion.type === 'snippet') {
return -1;
} else if (b.suggestion.type === 'snippet') {
return 1;
}
}
return defaultComparator(a, b);
}
function snippetDownComparator(a: ISuggestionItem, b: ISuggestionItem): number {
if (a.suggestion.type !== b.suggestion.type) {
if (a.suggestion.type === 'snippet') {
return 1;
} else if (b.suggestion.type === 'snippet') {
return -1;
}
}
return defaultComparator(a, b);
}
export function getSuggestionComparator(snippetConfig: SnippetConfig): (a: ISuggestionItem, b: ISuggestionItem) => number {
if (snippetConfig === 'top') {
return snippetUpComparator;
} else if (snippetConfig === 'bottom') {
return snippetDownComparator;
} else {
return defaultComparator;
}
}
CommonEditorRegistry.registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => {
const result: ISuggestResult = {
incomplete: false,
suggestions: []
};
return provideSuggestionItems(model, position).then(items => {
for (const { container, suggestion } of items) {
result.incomplete = result.incomplete || container.incomplete;
result.suggestions.push(suggestion);
}
return result;
});
});
interface SuggestController extends IEditorContribution {
triggerSuggest(onlyFrom?: ISuggestSupport[]): void;
}
let _suggestions: ISuggestion[];
let _provider = new class implements ISuggestSupport {
provideCompletionItems(): ISuggestResult {
return _suggestions && { suggestions: _suggestions };
}
};
SuggestRegistry.register('*', _provider);
/**
*
* @param editor
* @param suggestions
*/
export function showSimpleSuggestions(editor: ICommonCodeEditor, suggestions: ISuggestion[]) {
setTimeout(() => {
_suggestions = suggestions;
editor.getContribution<SuggestController>('editor.contrib.suggestController').triggerSuggest([_provider]);
_suggestions = undefined;
}, 0);
}

View File

@@ -0,0 +1,434 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { onUnexpectedError } from 'vs/base/common/errors';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICommonCodeEditor, IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { editorAction, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Range } from 'vs/editor/common/core/range';
import { ISuggestSupport } from 'vs/editor/common/modes';
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { Context as SuggestContext } from './suggest';
import { SuggestModel, State } from './suggestModel';
import { ICompletionItem } from './completionModel';
import { SuggestWidget } from './suggestWidget';
class AcceptOnCharacterOracle {
private _disposables: IDisposable[] = [];
private _activeAcceptCharacters = new Set<string>();
private _activeItem: ICompletionItem;
constructor(editor: ICodeEditor, widget: SuggestWidget, accept: (item: ICompletionItem) => any) {
this._disposables.push(widget.onDidShow(() => this._onItem(widget.getFocusedItem())));
this._disposables.push(widget.onDidFocus(this._onItem, this));
this._disposables.push(widget.onDidHide(this.reset, this));
this._disposables.push(editor.onWillType(text => {
if (this._activeItem) {
const ch = text[text.length - 1];
if (this._activeAcceptCharacters.has(ch) && editor.getConfiguration().contribInfo.acceptSuggestionOnCommitCharacter) {
accept(this._activeItem);
}
}
}));
}
private _onItem(item: ICompletionItem): void {
if (!item || isFalsyOrEmpty(item.suggestion.commitCharacters)) {
this.reset();
return;
}
this._activeItem = item;
this._activeAcceptCharacters.clear();
for (const ch of item.suggestion.commitCharacters) {
if (ch.length > 0) {
this._activeAcceptCharacters.add(ch[0]);
}
}
}
reset(): void {
this._activeItem = undefined;
}
dispose() {
dispose(this._disposables);
}
}
@editorContribution
export class SuggestController implements IEditorContribution {
private static ID: string = 'editor.contrib.suggestController';
public static get(editor: ICommonCodeEditor): SuggestController {
return editor.getContribution<SuggestController>(SuggestController.ID);
}
private _model: SuggestModel;
private _widget: SuggestWidget;
private _toDispose: IDisposable[] = [];
constructor(
private _editor: ICodeEditor,
@ICommandService private _commandService: ICommandService,
@ITelemetryService private _telemetryService: ITelemetryService,
@IContextKeyService _contextKeyService: IContextKeyService,
@IInstantiationService _instantiationService: IInstantiationService
) {
this._model = new SuggestModel(this._editor);
this._toDispose.push(this._model.onDidTrigger(e => this._widget.showTriggered(e.auto)));
this._toDispose.push(this._model.onDidSuggest(e => this._widget.showSuggestions(e.completionModel, e.isFrozen, e.auto)));
this._toDispose.push(this._model.onDidCancel(e => !e.retrigger && this._widget.hideWidget()));
// Manage the acceptSuggestionsOnEnter context key
let acceptSuggestionsOnEnter = SuggestContext.AcceptSuggestionsOnEnter.bindTo(_contextKeyService);
let updateFromConfig = () => {
const { acceptSuggestionOnEnter } = this._editor.getConfiguration().contribInfo;
acceptSuggestionsOnEnter.set(
acceptSuggestionOnEnter === 'on' || acceptSuggestionOnEnter === 'smart'
|| (<any /*migrate from old world*/>acceptSuggestionOnEnter) === true
);
};
this._toDispose.push(this._editor.onDidChangeConfiguration((e) => updateFromConfig()));
updateFromConfig();
this._widget = _instantiationService.createInstance(SuggestWidget, this._editor);
this._toDispose.push(this._widget.onDidSelect(this._onDidSelectItem, this));
// Wire up logic to accept a suggestion on certain characters
const autoAcceptOracle = new AcceptOnCharacterOracle(_editor, this._widget, item => this._onDidSelectItem(item));
this._toDispose.push(
autoAcceptOracle,
this._model.onDidSuggest(e => {
if (e.completionModel.items.length === 0) {
autoAcceptOracle.reset();
}
})
);
let makesTextEdit = SuggestContext.MakesTextEdit.bindTo(_contextKeyService);
this._toDispose.push(this._widget.onDidFocus(item => {
const position = this._editor.getPosition();
const startColumn = item.position.column - item.suggestion.overwriteBefore;
const endColumn = position.column;
let value = true;
if (
this._editor.getConfiguration().contribInfo.acceptSuggestionOnEnter === 'smart'
&& this._model.state === State.Auto
&& !item.suggestion.command
&& !item.suggestion.additionalTextEdits
&& item.suggestion.snippetType !== 'textmate'
&& endColumn - startColumn === item.suggestion.insertText.length
) {
const oldText = this._editor.getModel().getValueInRange({
startLineNumber: position.lineNumber,
startColumn,
endLineNumber: position.lineNumber,
endColumn
});
value = oldText !== item.suggestion.insertText;
}
makesTextEdit.set(value);
}));
this._toDispose.push({
dispose() { makesTextEdit.reset(); }
});
}
getId(): string {
return SuggestController.ID;
}
dispose(): void {
this._toDispose = dispose(this._toDispose);
if (this._widget) {
this._widget.dispose();
this._widget = null;
}
if (this._model) {
this._model.dispose();
this._model = null;
}
}
private _onDidSelectItem(item: ICompletionItem): void {
if (item) {
const { suggestion, position } = item;
const columnDelta = this._editor.getPosition().column - position.column;
if (Array.isArray(suggestion.additionalTextEdits)) {
this._editor.pushUndoStop();
this._editor.executeEdits('suggestController.additionalTextEdits', suggestion.additionalTextEdits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));
this._editor.pushUndoStop();
}
let { insertText } = suggestion;
if (suggestion.snippetType !== 'textmate') {
insertText = SnippetParser.escape(insertText);
}
SnippetController2.get(this._editor).insert(
insertText,
suggestion.overwriteBefore + columnDelta,
suggestion.overwriteAfter
);
if (suggestion.command) {
this._commandService.executeCommand(suggestion.command.id, ...suggestion.command.arguments).done(undefined, onUnexpectedError);
}
this._alertCompletionItem(item);
this._telemetryService.publicLog('suggestSnippetInsert', { ...this._editor.getTelemetryData(), suggestionType: suggestion.type });
}
this._model.cancel();
}
private _alertCompletionItem({ suggestion }: ICompletionItem): void {
let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' did insert the following text: {1}", suggestion.label, suggestion.insertText);
alert(msg);
}
triggerSuggest(onlyFrom?: ISuggestSupport[]): void {
this._model.trigger(false, false, onlyFrom);
this._editor.revealLine(this._editor.getPosition().lineNumber, ScrollType.Smooth);
this._editor.focus();
}
acceptSelectedSuggestion(): void {
if (this._widget) {
const item = this._widget.getFocusedItem();
this._onDidSelectItem(item);
}
}
cancelSuggestWidget(): void {
if (this._widget) {
this._model.cancel();
this._widget.hideWidget();
}
}
selectNextSuggestion(): void {
if (this._widget) {
this._widget.selectNext();
}
}
selectNextPageSuggestion(): void {
if (this._widget) {
this._widget.selectNextPage();
}
}
selectLastSuggestion(): void {
if (this._widget) {
this._widget.selectLast();
}
}
selectPrevSuggestion(): void {
if (this._widget) {
this._widget.selectPrevious();
}
}
selectPrevPageSuggestion(): void {
if (this._widget) {
this._widget.selectPreviousPage();
}
}
selectFirstSuggestion(): void {
if (this._widget) {
this._widget.selectFirst();
}
}
toggleSuggestionDetails(): void {
if (this._widget) {
this._widget.toggleDetails();
}
}
toggleSuggestionFocus(): void {
if (this._widget) {
this._widget.toggleDetailsFocus();
}
}
}
@editorAction
export class TriggerSuggestAction extends EditorAction {
constructor() {
super({
id: 'editor.action.triggerSuggest',
label: nls.localize('suggest.trigger.label', "Trigger Suggest"),
alias: 'Trigger Suggest',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCompletionItemProvider),
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.Space,
mac: { primary: KeyMod.WinCtrl | KeyCode.Space }
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const controller = SuggestController.get(editor);
if (!controller) {
return;
}
controller.triggerSuggest();
}
}
const weight = CommonEditorRegistry.commandWeight(90);
const SuggestCommand = EditorCommand.bindToContribution<SuggestController>(SuggestController.get);
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'acceptSelectedSuggestion',
precondition: SuggestContext.Visible,
handler: x => x.acceptSelectedSuggestion(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Tab
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'acceptSelectedSuggestionOnEnter',
precondition: SuggestContext.Visible,
handler: x => x.acceptSelectedSuggestion(),
kbOpts: {
weight: weight,
kbExpr: ContextKeyExpr.and(EditorContextKeys.textFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit),
primary: KeyCode.Enter
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'hideSuggestWidget',
precondition: SuggestContext.Visible,
handler: x => x.cancelSuggestWidget(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectNextSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectNextSuggestion(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.DownArrow,
secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow],
mac: { primary: KeyCode.DownArrow, secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow, KeyMod.WinCtrl | KeyCode.KEY_N] }
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectNextPageSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectNextPageSuggestion(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.PageDown,
secondary: [KeyMod.CtrlCmd | KeyCode.PageDown]
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectLastSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectLastSuggestion()
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectPrevSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectPrevSuggestion(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.UpArrow,
secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow],
mac: { primary: KeyCode.UpArrow, secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.WinCtrl | KeyCode.KEY_P] }
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectPrevPageSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectPrevPageSuggestion(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.PageUp,
secondary: [KeyMod.CtrlCmd | KeyCode.PageUp]
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'selectFirstSuggestion',
precondition: ContextKeyExpr.and(SuggestContext.Visible, SuggestContext.MultipleSuggestions),
handler: c => c.selectFirstSuggestion()
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'toggleSuggestionDetails',
precondition: SuggestContext.Visible,
handler: x => x.toggleSuggestionDetails(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.Space,
mac: { primary: KeyMod.WinCtrl | KeyCode.Space }
}
}));
CommonEditorRegistry.registerEditorCommand(new SuggestCommand({
id: 'toggleSuggestionFocus',
precondition: SuggestContext.Visible,
handler: x => x.toggleSuggestionFocus(),
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Space,
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Space }
}
}));

View File

@@ -0,0 +1,455 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError } from 'vs/base/common/errors';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { TimeoutTimer } from 'vs/base/common/async';
import Event, { Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICommonCodeEditor, IModel, IWordAtPosition } from 'vs/editor/common/editorCommon';
import { ISuggestSupport, SuggestRegistry, StandardTokenType } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position';
import { provideSuggestionItems, getSuggestionComparator, ISuggestionItem } from './suggest';
import { CompletionModel } from './completionModel';
import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
export interface ICancelEvent {
retrigger: boolean;
}
export interface ITriggerEvent {
auto: boolean;
}
export interface ISuggestEvent {
completionModel: CompletionModel;
isFrozen: boolean;
auto: boolean;
}
export class LineContext {
static shouldAutoTrigger(editor: ICommonCodeEditor): boolean {
const model = editor.getModel();
if (!model) {
return false;
}
const pos = editor.getPosition();
model.tokenizeIfCheap(pos.lineNumber);
const word = model.getWordAtPosition(pos);
if (!word) {
return false;
}
if (word.endColumn !== pos.column) {
return false;
}
if (!isNaN(Number(word.word))) {
return false;
}
return true;
}
static isInEditableRange(editor: ICommonCodeEditor): boolean {
const model = editor.getModel();
const position = editor.getPosition();
if (model.hasEditableRange()) {
const editableRange = model.getEditableRange();
if (!editableRange.containsPosition(position)) {
return false;
}
}
return true;
}
readonly lineNumber: number;
readonly column: number;
readonly leadingLineContent: string;
readonly leadingWord: IWordAtPosition;
readonly auto: boolean;
constructor(model: IModel, position: Position, auto: boolean) {
this.leadingLineContent = model.getLineContent(position.lineNumber).substr(0, position.column - 1);
this.leadingWord = model.getWordUntilPosition(position);
this.lineNumber = position.lineNumber;
this.column = position.column;
this.auto = auto;
}
}
export const enum State {
Idle = 0,
Manual = 1,
Auto = 2
}
export class SuggestModel implements IDisposable {
private toDispose: IDisposable[] = [];
private quickSuggestDelay: number;
private triggerCharacterListener: IDisposable;
private triggerAutoSuggestPromise: TPromise<void>;
private triggerRefilter = new TimeoutTimer();
private _state: State;
private requestPromise: TPromise<void>;
private context: LineContext;
private currentPosition: Position;
private completionModel: CompletionModel;
private _onDidCancel: Emitter<ICancelEvent> = new Emitter<ICancelEvent>();
get onDidCancel(): Event<ICancelEvent> { return this._onDidCancel.event; }
private _onDidTrigger: Emitter<ITriggerEvent> = new Emitter<ITriggerEvent>();
get onDidTrigger(): Event<ITriggerEvent> { return this._onDidTrigger.event; }
private _onDidSuggest: Emitter<ISuggestEvent> = new Emitter<ISuggestEvent>();
get onDidSuggest(): Event<ISuggestEvent> { return this._onDidSuggest.event; }
constructor(private editor: ICommonCodeEditor) {
this._state = State.Idle;
this.triggerAutoSuggestPromise = null;
this.requestPromise = null;
this.completionModel = null;
this.context = null;
this.currentPosition = editor.getPosition() || new Position(1, 1);
// wire up various listeners
this.toDispose.push(this.editor.onDidChangeModel(() => {
this.updateTriggerCharacters();
this.cancel();
}));
this.toDispose.push(editor.onDidChangeModelLanguage(() => {
this.updateTriggerCharacters();
this.cancel();
}));
this.toDispose.push(this.editor.onDidChangeConfiguration(() => {
this.updateTriggerCharacters();
this.updateQuickSuggest();
}));
this.toDispose.push(SuggestRegistry.onDidChange(() => {
this.updateTriggerCharacters();
this.updateActiveSuggestSession();
}));
this.toDispose.push(this.editor.onDidChangeCursorSelection(e => {
this.onCursorChange(e);
}));
this.updateTriggerCharacters();
this.updateQuickSuggest();
}
dispose(): void {
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger, this.triggerCharacterListener, this.triggerRefilter]);
this.toDispose = dispose(this.toDispose);
this.cancel();
}
// --- handle configuration & precondition changes
private updateQuickSuggest(): void {
this.quickSuggestDelay = this.editor.getConfiguration().contribInfo.quickSuggestionsDelay;
if (isNaN(this.quickSuggestDelay) || (!this.quickSuggestDelay && this.quickSuggestDelay !== 0) || this.quickSuggestDelay < 0) {
this.quickSuggestDelay = 10;
}
}
private updateTriggerCharacters(): void {
dispose(this.triggerCharacterListener);
if (this.editor.getConfiguration().readOnly
|| !this.editor.getModel()
|| !this.editor.getConfiguration().contribInfo.suggestOnTriggerCharacters) {
return;
}
const supportsByTriggerCharacter: { [ch: string]: ISuggestSupport[] } = Object.create(null);
for (const support of SuggestRegistry.all(this.editor.getModel())) {
if (isFalsyOrEmpty(support.triggerCharacters)) {
continue;
}
for (const ch of support.triggerCharacters) {
const array = supportsByTriggerCharacter[ch];
if (!array) {
supportsByTriggerCharacter[ch] = [support];
} else {
array.push(support);
}
}
}
this.triggerCharacterListener = this.editor.onDidType(text => {
const lastChar = text.charAt(text.length - 1);
const supports = supportsByTriggerCharacter[lastChar];
if (supports) {
// keep existing items that where not computed by the
// supports/providers that want to trigger now
const items: ISuggestionItem[] = [];
if (this.completionModel) {
for (const item of this.completionModel.items) {
if (supports.indexOf(item.support) < 0) {
items.push(item);
}
}
}
this.trigger(true, Boolean(this.completionModel), supports, items);
}
});
}
// --- trigger/retrigger/cancel suggest
get state(): State {
return this._state;
}
cancel(retrigger: boolean = false): void {
if (this.triggerAutoSuggestPromise) {
this.triggerAutoSuggestPromise.cancel();
this.triggerAutoSuggestPromise = null;
}
if (this.requestPromise) {
this.requestPromise.cancel();
this.requestPromise = null;
}
this._state = State.Idle;
this.completionModel = null;
this.context = null;
this._onDidCancel.fire({ retrigger });
}
private updateActiveSuggestSession(): void {
if (this._state !== State.Idle) {
if (!SuggestRegistry.has(this.editor.getModel())) {
this.cancel();
} else {
this.trigger(this._state === State.Auto, true);
}
}
}
private onCursorChange(e: ICursorSelectionChangedEvent): void {
const prevPosition = this.currentPosition;
this.currentPosition = this.editor.getPosition();
if (!e.selection.isEmpty()
|| e.source !== 'keyboard'
|| e.reason !== CursorChangeReason.NotSet) {
if (this._state === State.Idle) {
// Early exit if nothing needs to be done!
// Leave some form of early exit check here if you wish to continue being a cursor position change listener ;)
return;
}
this.cancel();
return;
}
if (!SuggestRegistry.has(this.editor.getModel())) {
return;
}
const model = this.editor.getModel();
if (!model) {
return;
}
if (this._state === State.Idle) {
// trigger 24x7 IntelliSense when idle, enabled, when cursor
// moved RIGHT, and when at a good position
if (this.editor.getConfiguration().contribInfo.quickSuggestions !== false
&& prevPosition.isBefore(this.currentPosition)
) {
this.cancel();
if (LineContext.shouldAutoTrigger(this.editor)) {
this.triggerAutoSuggestPromise = TPromise.timeout(this.quickSuggestDelay);
this.triggerAutoSuggestPromise.then(() => {
const model = this.editor.getModel();
const pos = this.editor.getPosition();
if (!model) {
return;
}
// validate enabled now
const { quickSuggestions } = this.editor.getConfiguration().contribInfo;
if (quickSuggestions === false) {
return;
} else if (quickSuggestions === true) {
// all good
} else {
model.tokenizeIfCheap(pos.lineNumber);
const { tokenType } = model
.getLineTokens(pos.lineNumber)
.findTokenAtOffset(pos.column - 1);
const inValidScope = quickSuggestions.other && tokenType === StandardTokenType.Other
|| quickSuggestions.comments && tokenType === StandardTokenType.Comment
|| quickSuggestions.strings && tokenType === StandardTokenType.String;
if (!inValidScope) {
return;
}
}
this.triggerAutoSuggestPromise = null;
this.trigger(true);
});
}
}
} else {
// refine active suggestion
this.triggerRefilter.cancelAndSet(() => {
const position = this.editor.getPosition();
const ctx = new LineContext(model, position, this._state === State.Auto);
this.onNewContext(ctx);
}, 25);
}
}
public trigger(auto: boolean, retrigger: boolean = false, onlyFrom?: ISuggestSupport[], existingItems?: ISuggestionItem[]): void {
const model = this.editor.getModel();
if (!model) {
return;
}
const ctx = new LineContext(model, this.editor.getPosition(), auto);
if (!LineContext.isInEditableRange(this.editor)) {
return;
}
// Cancel previous requests, change state & update UI
this.cancel(retrigger);
this._state = auto ? State.Auto : State.Manual;
this._onDidTrigger.fire({ auto });
// Capture context when request was sent
this.context = ctx;
this.requestPromise = provideSuggestionItems(model, this.editor.getPosition(),
this.editor.getConfiguration().contribInfo.snippetSuggestions,
onlyFrom
).then(items => {
this.requestPromise = null;
if (this._state === State.Idle) {
return;
}
const model = this.editor.getModel();
if (!model) {
return;
}
if (!isFalsyOrEmpty(existingItems)) {
const cmpFn = getSuggestionComparator(this.editor.getConfiguration().contribInfo.snippetSuggestions);
items = items.concat(existingItems).sort(cmpFn);
}
const ctx = new LineContext(model, this.editor.getPosition(), auto);
this.completionModel = new CompletionModel(items, this.context.column, {
leadingLineContent: ctx.leadingLineContent,
characterCountDelta: this.context ? ctx.column - this.context.column : 0
}, this.editor.getConfiguration().contribInfo.snippetSuggestions);
this.onNewContext(ctx);
}).then(null, onUnexpectedError);
}
private onNewContext(ctx: LineContext): void {
if (!this.context) {
// happens when 24x7 IntelliSense is enabled and still in its delay
return;
}
if (ctx.lineNumber !== this.context.lineNumber) {
// e.g. happens when pressing Enter while IntelliSense is computed
this.cancel();
return;
}
if (ctx.column < this.context.column) {
// typed -> moved cursor LEFT -> retrigger if still on a word
if (ctx.leadingWord.word) {
this.trigger(this.context.auto, true);
} else {
this.cancel();
}
return;
}
if (!this.completionModel) {
// happens when IntelliSense is not yet computed
return;
}
if (ctx.column > this.context.column && this.completionModel.incomplete && ctx.leadingWord.word.length !== 0) {
// typed -> moved cursor RIGHT & incomple model & still on a word -> retrigger
const { complete, incomplete } = this.completionModel.resolveIncompleteInfo();
this.trigger(this._state === State.Auto, true, incomplete, complete);
} else {
// typed -> moved cursor RIGHT -> update UI
let oldLineContext = this.completionModel.lineContext;
let isFrozen = false;
this.completionModel.lineContext = {
leadingLineContent: ctx.leadingLineContent,
characterCountDelta: ctx.column - this.context.column
};
if (this.completionModel.items.length === 0) {
if (LineContext.shouldAutoTrigger(this.editor) && this.context.leadingWord.endColumn < ctx.leadingWord.startColumn) {
// retrigger when heading into a new word
this.trigger(this.context.auto, true);
return;
}
if (!this.context.auto) {
// freeze when IntelliSense was manually requested
this.completionModel.lineContext = oldLineContext;
isFrozen = this.completionModel.items.length > 0;
if (isFrozen && ctx.leadingWord.word.length === 0) {
// there were results before but now there aren't
// and also we are not on a word anymore -> cancel
this.cancel();
return;
}
} else {
// nothing left
this.cancel();
return;
}
}
this._onDidSuggest.fire({
completionModel: this.completionModel,
auto: this.context.auto,
isFrozen,
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,231 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { ISuggestion, ISuggestResult, ISuggestSupport, SuggestionType } from 'vs/editor/common/modes';
import { ISuggestionItem, getSuggestionComparator } from 'vs/editor/contrib/suggest/browser/suggest';
import { CompletionModel } from 'vs/editor/contrib/suggest/browser/completionModel';
import { IPosition } from 'vs/editor/common/core/position';
import { TPromise } from 'vs/base/common/winjs.base';
suite('CompletionModel', function () {
function createSuggestItem(label: string, overwriteBefore: number, type: SuggestionType = 'property', incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }): ISuggestionItem {
return new class implements ISuggestionItem {
position = position;
suggestion: ISuggestion = {
label,
overwriteBefore,
insertText: label,
type
};
container: ISuggestResult = {
incomplete,
suggestions: [this.suggestion]
};
support: ISuggestSupport = {
provideCompletionItems(): any {
return;
}
};
resolve(): TPromise<void> {
return null;
}
};
}
let model: CompletionModel;
setup(function () {
model = new CompletionModel([
createSuggestItem('foo', 3),
createSuggestItem('Foo', 3),
createSuggestItem('foo', 2),
], 1, {
leadingLineContent: 'foo',
characterCountDelta: 0
});
});
test('filtering - cached', function () {
const itemsNow = model.items;
let itemsThen = model.items;
assert.ok(itemsNow === itemsThen);
// still the same context
model.lineContext = { leadingLineContent: 'foo', characterCountDelta: 0 };
itemsThen = model.items;
assert.ok(itemsNow === itemsThen);
// different context, refilter
model.lineContext = { leadingLineContent: 'foo1', characterCountDelta: 1 };
itemsThen = model.items;
assert.ok(itemsNow !== itemsThen);
});
test('complete/incomplete', function () {
assert.equal(model.incomplete, false);
let incompleteModel = new CompletionModel([
createSuggestItem('foo', 3, undefined, true),
createSuggestItem('foo', 2),
], 1, {
leadingLineContent: 'foo',
characterCountDelta: 0
});
assert.equal(incompleteModel.incomplete, true);
});
test('replaceIncomplete', function () {
const completeItem = createSuggestItem('foobar', 1, undefined, false, { lineNumber: 1, column: 2 });
const incompleteItem = createSuggestItem('foofoo', 1, undefined, true, { lineNumber: 1, column: 2 });
const model = new CompletionModel([completeItem, incompleteItem], 2, { leadingLineContent: 'f', characterCountDelta: 0 });
assert.equal(model.incomplete, true);
assert.equal(model.items.length, 2);
const { complete, incomplete } = model.resolveIncompleteInfo();
assert.equal(incomplete.length, 1);
assert.ok(incomplete[0] === incompleteItem.support);
assert.equal(complete.length, 1);
assert.ok(complete[0] === completeItem);
});
test('proper current word when length=0, #16380', function () {
model = new CompletionModel([
createSuggestItem(' </div', 4),
createSuggestItem('a', 0),
createSuggestItem('p', 0),
createSuggestItem(' </tag', 4),
createSuggestItem(' XYZ', 4),
], 1, {
leadingLineContent: ' <',
characterCountDelta: 0
});
assert.equal(model.items.length, 4);
const [a, b, c, d] = model.items;
assert.equal(a.suggestion.label, ' </div');
assert.equal(b.suggestion.label, ' </tag');
assert.equal(c.suggestion.label, 'a');
assert.equal(d.suggestion.label, 'p');
});
test('keep snippet sorting with prefix: top, #25495', function () {
model = new CompletionModel([
createSuggestItem('Snippet1', 1, 'snippet'),
createSuggestItem('tnippet2', 1, 'snippet'),
createSuggestItem('semver', 1, 'property'),
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, 'top');
assert.equal(model.items.length, 2);
const [a, b] = model.items;
assert.equal(a.suggestion.label, 'Snippet1');
assert.equal(b.suggestion.label, 'semver');
assert.ok(a.score < b.score); // snippet really promoted
});
test('keep snippet sorting with prefix: bottom, #25495', function () {
model = new CompletionModel([
createSuggestItem('snippet1', 1, 'snippet'),
createSuggestItem('tnippet2', 1, 'snippet'),
createSuggestItem('Semver', 1, 'property'),
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, 'bottom');
assert.equal(model.items.length, 2);
const [a, b] = model.items;
assert.equal(a.suggestion.label, 'Semver');
assert.equal(b.suggestion.label, 'snippet1');
assert.ok(a.score < b.score); // snippet really demoted
});
test('keep snippet sorting with prefix: inline, #25495', function () {
model = new CompletionModel([
createSuggestItem('snippet1', 1, 'snippet'),
createSuggestItem('tnippet2', 1, 'snippet'),
createSuggestItem('Semver', 1, 'property'),
], 1, {
leadingLineContent: 's',
characterCountDelta: 0
}, 'inline');
assert.equal(model.items.length, 2);
const [a, b] = model.items;
assert.equal(a.suggestion.label, 'snippet1');
assert.equal(b.suggestion.label, 'Semver');
assert.ok(a.score > b.score); // snippet really demoted
});
test('filterText seems ignored in autocompletion, #26874', function () {
const item1 = createSuggestItem('Map - java.util', 1, 'property');
item1.suggestion.filterText = 'Map';
const item2 = createSuggestItem('Map - java.util', 1, 'property');
model = new CompletionModel([item1, item2], 1, {
leadingLineContent: 'M',
characterCountDelta: 0
});
assert.equal(model.items.length, 2);
model.lineContext = {
leadingLineContent: 'Map ',
characterCountDelta: 3
};
assert.equal(model.items.length, 1);
});
test('Vscode 1.12 no longer obeys \'sortText\' in completion items (from language server), #26096', function () {
const item1 = createSuggestItem('<- groups', 2, 'property', false, { lineNumber: 1, column: 3 });
item1.suggestion.filterText = ' groups';
item1.suggestion.sortText = '00002';
const item2 = createSuggestItem('source', 0, 'property', false, { lineNumber: 1, column: 3 });
item2.suggestion.filterText = 'source';
item2.suggestion.sortText = '00001';
const items = [item1, item2].sort(getSuggestionComparator('inline'));
model = new CompletionModel(items, 3, {
leadingLineContent: ' ',
characterCountDelta: 0
});
assert.equal(model.items.length, 2);
const [first, second] = model.items;
assert.equal(first.suggestion.label, 'source');
assert.equal(second.suggestion.label, '<- groups');
});
});

View File

@@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { SuggestRegistry } from 'vs/editor/common/modes';
import { provideSuggestionItems } from 'vs/editor/contrib/suggest/browser/suggest';
import { Position } from 'vs/editor/common/core/position';
import { Model } from 'vs/editor/common/model/model';
suite('Suggest', function () {
let model: Model;
let registration: IDisposable;
setup(function () {
model = Model.createFromString('FOO\nbar\BAR\nfoo', undefined, undefined, URI.parse('foo:bar/path'));
registration = SuggestRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, {
provideCompletionItems() {
return {
incomplete: false,
suggestions: [{
label: 'aaa',
type: 'snippet',
insertText: 'aaa'
}, {
label: 'zzz',
type: 'snippet',
insertText: 'zzz'
}, {
label: 'fff',
type: 'property',
insertText: 'fff'
}]
};
}
});
});
teardown(() => {
registration.dispose();
model.dispose();
});
test('sort - snippet inline', function () {
return provideSuggestionItems(model, new Position(1, 1), 'inline').then(items => {
assert.equal(items.length, 3);
assert.equal(items[0].suggestion.label, 'aaa');
assert.equal(items[1].suggestion.label, 'fff');
assert.equal(items[2].suggestion.label, 'zzz');
});
});
test('sort - snippet top', function () {
return provideSuggestionItems(model, new Position(1, 1), 'top').then(items => {
assert.equal(items.length, 3);
assert.equal(items[0].suggestion.label, 'aaa');
assert.equal(items[1].suggestion.label, 'zzz');
assert.equal(items[2].suggestion.label, 'fff');
});
});
test('sort - snippet bottom', function () {
return provideSuggestionItems(model, new Position(1, 1), 'bottom').then(items => {
assert.equal(items.length, 3);
assert.equal(items[0].suggestion.label, 'fff');
assert.equal(items[1].suggestion.label, 'aaa');
assert.equal(items[2].suggestion.label, 'zzz');
});
});
test('sort - snippet none', function () {
return provideSuggestionItems(model, new Position(1, 1), 'none').then(items => {
assert.equal(items.length, 1);
assert.equal(items[0].suggestion.label, 'fff');
});
});
test('only from', function () {
const foo: any = {
triggerCharacters: [],
provideCompletionItems() {
return {
currentWord: '',
incomplete: false,
suggestions: [{
label: 'jjj',
type: 'property',
insertText: 'jjj'
}]
};
}
};
const registration = SuggestRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, foo);
provideSuggestionItems(model, new Position(1, 1), undefined, [foo]).then(items => {
registration.dispose();
assert.equal(items.length, 1);
assert.ok(items[0].support === foo);
});
});
});

View File

@@ -0,0 +1,460 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import Event from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { Model } from 'vs/editor/common/model/model';
import { ICommonCodeEditor, Handler } from 'vs/editor/common/editorCommon';
import { ISuggestSupport, ISuggestResult, SuggestRegistry } from 'vs/editor/common/modes';
import { SuggestModel, LineContext } from 'vs/editor/contrib/suggest/browser/suggestModel';
import { MockCodeEditor, MockScopeLocation } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
function createMockEditor(model: Model): MockCodeEditor {
const contextKeyService = new MockContextKeyService();
const telemetryService = NullTelemetryService;
const instantiationService = new InstantiationService(new ServiceCollection(
[IContextKeyService, contextKeyService],
[ITelemetryService, telemetryService]
));
const editor = new MockCodeEditor(new MockScopeLocation(), {}, instantiationService, contextKeyService);
editor.setModel(model);
return editor;
}
suite('SuggestModel - Context', function () {
let model: Model;
setup(function () {
model = Model.createFromString('Das Pferd frisst keinen Gurkensalat - Philipp Reis 1861.\nWer hat\'s erfunden?');
});
teardown(function () {
model.dispose();
});
test('Context - shouldAutoTrigger', function () {
function assertAutoTrigger(offset: number, expected: boolean): void {
const pos = model.getPositionAt(offset);
const editor = createMockEditor(model);
editor.setPosition(pos);
assert.equal(LineContext.shouldAutoTrigger(editor), expected);
editor.dispose();
}
assertAutoTrigger(3, true); // end of word, Das|
assertAutoTrigger(4, false); // no word Das |
assertAutoTrigger(1, false); // middle of word D|as
assertAutoTrigger(55, false); // number, 1861|
});
});
suite('SuggestModel - TriggerAndCancelOracle', function () {
const alwaysEmptySupport: ISuggestSupport = {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
incomplete: false,
suggestions: []
};
}
};
const alwaysSomethingSupport: ISuggestSupport = {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
incomplete: false,
suggestions: [{
label: doc.getWordUntilPosition(pos).word,
type: 'property',
insertText: 'foofoo'
}]
};
}
};
let disposables: IDisposable[] = [];
let model: Model;
setup(function () {
disposables = dispose(disposables);
model = Model.createFromString('abc def', undefined, undefined, URI.parse('test:somefile.ttt'));
disposables.push(model);
});
function withOracle(callback: (model: SuggestModel, editor: ICommonCodeEditor) => any): TPromise<any> {
return new TPromise((resolve, reject) => {
const editor = createMockEditor(model);
const oracle = new SuggestModel(editor);
disposables.push(oracle, editor);
try {
resolve(callback(oracle, editor));
} catch (err) {
reject(err);
}
});
}
function assertEvent<E>(event: Event<E>, action: () => any, assert: (e: E) => any) {
return new TPromise((resolve, reject) => {
const sub = event(e => {
sub.dispose();
try {
resolve(assert(e));
} catch (err) {
reject(err);
}
});
try {
action();
} catch (err) {
reject(err);
}
});
}
test('events - cancel/trigger', function () {
return withOracle(model => {
return TPromise.join([
assertEvent(model.onDidCancel, function () {
model.cancel();
}, function (event) {
assert.equal(event.retrigger, false);
}),
assertEvent(model.onDidCancel, function () {
model.cancel(true);
}, function (event) {
assert.equal(event.retrigger, true);
}),
// cancel on trigger
assertEvent(model.onDidCancel, function () {
model.trigger(false);
}, function (event) {
assert.equal(event.retrigger, false);
}),
assertEvent(model.onDidCancel, function () {
model.trigger(false, true);
}, function (event) {
assert.equal(event.retrigger, true);
}),
assertEvent(model.onDidTrigger, function () {
model.trigger(true);
}, function (event) {
assert.equal(event.auto, true);
}),
assertEvent(model.onDidTrigger, function () {
model.trigger(false);
}, function (event) {
assert.equal(event.auto, false);
})
]);
});
});
test('events - suggest/empty', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, alwaysEmptySupport));
return withOracle(model => {
return TPromise.join([
assertEvent(model.onDidCancel, function () {
model.trigger(true);
}, function (event) {
assert.equal(event.retrigger, false);
}),
assertEvent(model.onDidSuggest, function () {
model.trigger(false);
}, function (event) {
assert.equal(event.auto, false);
assert.equal(event.isFrozen, false);
assert.equal(event.completionModel.items.length, 0);
})
]);
});
});
test('trigger - on type', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, alwaysSomethingSupport));
return withOracle((model, editor) => {
return assertEvent(model.onDidSuggest, () => {
editor.setPosition({ lineNumber: 1, column: 4 });
editor.trigger('keyboard', Handler.Type, { text: 'd' });
}, event => {
assert.equal(event.auto, true);
assert.equal(event.completionModel.items.length, 1);
const [first] = event.completionModel.items;
assert.equal(first.support, alwaysSomethingSupport);
});
});
});
test('#17400: Keep filtering suggestModel.ts after space', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
currentWord: '',
incomplete: false,
suggestions: [{
label: 'My Table',
type: 'property',
insertText: 'My Table'
}]
};
}
}));
model.setValue('');
return withOracle((model, editor) => {
return assertEvent(model.onDidSuggest, () => {
// make sure completionModel starts here!
model.trigger(true);
}, event => {
return assertEvent(model.onDidSuggest, () => {
editor.setPosition({ lineNumber: 1, column: 1 });
editor.trigger('keyboard', Handler.Type, { text: 'My' });
}, event => {
assert.equal(event.auto, true);
assert.equal(event.completionModel.items.length, 1);
const [first] = event.completionModel.items;
assert.equal(first.suggestion.label, 'My Table');
return assertEvent(model.onDidSuggest, () => {
editor.setPosition({ lineNumber: 1, column: 3 });
editor.trigger('keyboard', Handler.Type, { text: ' ' });
}, event => {
assert.equal(event.auto, true);
assert.equal(event.completionModel.items.length, 1);
const [first] = event.completionModel.items;
assert.equal(first.suggestion.label, 'My Table');
});
});
});
});
});
test('#21484: Trigger character always force a new completion session', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
currentWord: '',
incomplete: false,
suggestions: [{
label: 'foo.bar',
type: 'property',
insertText: 'foo.bar',
overwriteBefore: pos.column - 1
}]
};
}
}));
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
triggerCharacters: ['.'],
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
currentWord: '',
incomplete: false,
suggestions: [{
label: 'boom',
type: 'property',
insertText: 'boom',
overwriteBefore: doc.getLineContent(pos.lineNumber)[pos.column - 2] === '.' ? 0 : pos.column - 1
}]
};
}
}));
model.setValue('');
return withOracle((model, editor) => {
return assertEvent(model.onDidSuggest, () => {
editor.setPosition({ lineNumber: 1, column: 1 });
editor.trigger('keyboard', Handler.Type, { text: 'foo' });
}, event => {
assert.equal(event.auto, true);
assert.equal(event.completionModel.items.length, 1);
const [first] = event.completionModel.items;
assert.equal(first.suggestion.label, 'foo.bar');
return assertEvent(model.onDidSuggest, () => {
editor.trigger('keyboard', Handler.Type, { text: '.' });
}, event => {
assert.equal(event.auto, true);
assert.equal(event.completionModel.items.length, 2);
const [first, second] = event.completionModel.items;
assert.equal(first.suggestion.label, 'foo.bar');
assert.equal(second.suggestion.label, 'boom');
});
});
});
});
test('Intellisense Completion doesn\'t respect space after equal sign (.html file), #29353 [1/2]', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, alwaysSomethingSupport));
return withOracle((model, editor) => {
editor.getModel().setValue('fo');
editor.setPosition({ lineNumber: 1, column: 3 });
return assertEvent(model.onDidSuggest, () => {
model.trigger(false);
}, event => {
assert.equal(event.auto, false);
assert.equal(event.isFrozen, false);
assert.equal(event.completionModel.items.length, 1);
return assertEvent(model.onDidCancel, () => {
editor.trigger('keyboard', Handler.Type, { text: '+' });
}, event => {
assert.equal(event.retrigger, false);
});
});
});
});
test('Intellisense Completion doesn\'t respect space after equal sign (.html file), #29353 [2/2]', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, alwaysSomethingSupport));
return withOracle((model, editor) => {
editor.getModel().setValue('fo');
editor.setPosition({ lineNumber: 1, column: 3 });
return assertEvent(model.onDidSuggest, () => {
model.trigger(false);
}, event => {
assert.equal(event.auto, false);
assert.equal(event.isFrozen, false);
assert.equal(event.completionModel.items.length, 1);
return assertEvent(model.onDidCancel, () => {
editor.trigger('keyboard', Handler.Type, { text: ' ' });
}, event => {
assert.equal(event.retrigger, false);
});
});
});
});
test('Incomplete suggestion results cause re-triggering when typing w/o further context, #28400 (1/2)', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
incomplete: true,
suggestions: [{
label: 'foo',
type: 'property',
insertText: 'foo',
overwriteBefore: pos.column - 1
}]
};
}
}));
return withOracle((model, editor) => {
editor.getModel().setValue('foo');
editor.setPosition({ lineNumber: 1, column: 4 });
return assertEvent(model.onDidSuggest, () => {
model.trigger(false);
}, event => {
assert.equal(event.auto, false);
assert.equal(event.completionModel.incomplete, true);
assert.equal(event.completionModel.items.length, 1);
return assertEvent(model.onDidCancel, () => {
editor.trigger('keyboard', Handler.Type, { text: ';' });
}, event => {
assert.equal(event.retrigger, false);
});
});
});
});
test('Incomplete suggestion results cause re-triggering when typing w/o further context, #28400 (2/2)', function () {
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
provideCompletionItems(doc, pos) {
return <ISuggestResult>{
incomplete: true,
suggestions: [{
label: 'foo;',
type: 'property',
insertText: 'foo',
overwriteBefore: pos.column - 1
}]
};
}
}));
return withOracle((model, editor) => {
editor.getModel().setValue('foo');
editor.setPosition({ lineNumber: 1, column: 4 });
return assertEvent(model.onDidSuggest, () => {
model.trigger(false);
}, event => {
assert.equal(event.auto, false);
assert.equal(event.completionModel.incomplete, true);
assert.equal(event.completionModel.items.length, 1);
return assertEvent(model.onDidSuggest, () => {
// while we cancel incrementally enriching the set of
// completions we still filter against those that we have
// until now
editor.trigger('keyboard', Handler.Type, { text: ';' });
}, event => {
assert.equal(event.auto, false);
assert.equal(event.completionModel.incomplete, true);
assert.equal(event.completionModel.items.length, 1);
});
});
});
});
});