SQL Operations Studio Public Preview 1 (0.23) release source code
211
src/vs/editor/contrib/suggest/browser/completionModel.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
1
src/vs/editor/contrib/suggest/browser/media/Misc_16x.svg
Normal 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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
47
src/vs/editor/contrib/suggest/browser/media/Snippet_16x.svg
Normal 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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
1
src/vs/editor/contrib/suggest/browser/media/close.svg
Normal 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 |
1
src/vs/editor/contrib/suggest/browser/media/info.svg
Normal 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 |
322
src/vs/editor/contrib/suggest/browser/media/suggest.css
Normal 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'); }
|
||||
245
src/vs/editor/contrib/suggest/browser/suggest.ts
Normal 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);
|
||||
}
|
||||
|
||||
434
src/vs/editor/contrib/suggest/browser/suggestController.ts
Normal 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 }
|
||||
}
|
||||
}));
|
||||
455
src/vs/editor/contrib/suggest/browser/suggestModel.ts
Normal 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
1071
src/vs/editor/contrib/suggest/browser/suggestWidget.ts
Normal 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');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
110
src/vs/editor/contrib/suggest/test/browser/suggest.test.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
460
src/vs/editor/contrib/suggest/test/browser/suggestModel.test.ts
Normal 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);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||