提交 0724266e 编写于 作者: R Rob Lourens

Show section for settings from new extensions, with decorations on each

上级 91198d94
......@@ -276,6 +276,13 @@
cursor: pointer;
}
.monaco-editor .newExtensionInstall {
background: url('info.svg') center center no-repeat;
width: 16px;
height: 16px;
cursor: pointer;
}
.monaco-editor .edit-preferences-widget.hidden {
display: none;
visibility: hidden;
......
......@@ -436,8 +436,8 @@ class PreferencesRenderersController extends Disposable {
this._currentNewExtensionsSearchProvider = (updateCurrentResults && this._currentNewExtensionsSearchProvider) || this.preferencesSearchService.getRemoteSearchProvider(query, true);
this._remoteFiltersInProgress = [
this.filterOrSearchPreferences(query, this._currentNewExtensionsSearchProvider, 'newExtensionsResult', nls.localize('newExtensionsResult', "Other Extension Results")),
this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results"))
this.filterOrSearchPreferences(query, this._currentRemoteSearchProvider, 'nlpResult', nls.localize('nlpResult', "Natural Language Results"), 1),
this.filterOrSearchPreferences(query, this._currentNewExtensionsSearchProvider, 'newExtensionsResult', nls.localize('newExtensionsResult', "Other Extension Results"), 2)
];
return TPromise.join(this._remoteFiltersInProgress).then(() => {
......@@ -453,16 +453,18 @@ class PreferencesRenderersController extends Disposable {
localFilterPreferences(query: string, updateCurrentResults?: boolean): TPromise<void> {
this._currentLocalSearchProvider = (updateCurrentResults && this._currentLocalSearchProvider) || this.preferencesSearchService.getLocalSearchProvider(query);
return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results"));
return this.filterOrSearchPreferences(query, this._currentLocalSearchProvider, 'filterResult', nls.localize('filterResult', "Filtered Results"), 0);
}
private filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string): TPromise<void> {
private filterOrSearchPreferences(query: string, searchProvider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number, newExtensionsOnly?: boolean): TPromise<void> {
this._lastQuery = query;
return TPromise.join([
this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel),
this._filterOrSearchPreferences(query, this.editablePreferencesRenderer, searchProvider, groupId, groupLabel)]
).then(results => {
const filterPs = [this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel, groupOrder)];
if (!newExtensionsOnly) {
filterPs.push(this._filterOrSearchPreferences(query, this.defaultPreferencesRenderer, searchProvider, groupId, groupLabel, groupOrder));
}
return TPromise.join(filterPs).then(results => {
const [defaultFilterResult, editableFilterResult] = results;
this.consolidateAndUpdate(defaultFilterResult, editableFilterResult);
......@@ -485,7 +487,7 @@ class PreferencesRenderersController extends Disposable {
this._focusPreference(setting, this._editablePreferencesRenderer);
}
private _filterOrSearchPreferences(filter: string, preferencesRenderer: IPreferencesRenderer<ISetting>, provider: ISearchProvider, groupId: string, groupLabel: string): TPromise<IFilterResult> {
private _filterOrSearchPreferences(filter: string, preferencesRenderer: IPreferencesRenderer<ISetting>, provider: ISearchProvider, groupId: string, groupLabel: string, groupOrder: number): TPromise<IFilterResult> {
if (preferencesRenderer) {
const model = <ISettingsEditorModel>preferencesRenderer.preferencesModel;
const searchP = provider ? provider.searchModel(model) : TPromise.wrap(null);
......@@ -509,7 +511,8 @@ class PreferencesRenderersController extends Disposable {
model.updateResultGroup(groupId, {
id: groupId,
label: groupLabel,
result: searchResult
result: searchResult,
order: groupOrder
}) :
model.updateResultGroup(groupId, null);
......
......@@ -6,6 +6,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import * as nls from 'vs/nls';
import { Delayer } from 'vs/base/common/async';
import * as arrays from 'vs/base/common/arrays';
import * as strings from 'vs/base/common/strings';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IAction } from 'vs/base/common/actions';
......@@ -255,6 +256,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
private editSettingActionRenderer: EditSettingRenderer;
private feedbackWidgetRenderer: FeedbackWidgetRenderer;
private bracesHidingRenderer: BracesHidingRenderer;
private extensionCodelensRenderer: ExtensionCodelensRenderer;
private filterResult: IFilterResult;
private _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
......@@ -279,6 +281,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
this.feedbackWidgetRenderer = this._register(instantiationService.createInstance(FeedbackWidgetRenderer, editor));
this.bracesHidingRenderer = this._register(instantiationService.createInstance(BracesHidingRenderer, editor, preferencesModel));
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, this.bracesHidingRenderer]));
this.extensionCodelensRenderer = this._register(instantiationService.createInstance(ExtensionCodelensRenderer, editor));
this._register(this.editSettingActionRenderer.onUpdateSetting(e => this._onUpdatePreference.fire(e)));
this._register(this.settingsGroupTitleRenderer.onHiddenAreasChanged(() => this.hiddenAreasRenderer.render()));
......@@ -314,6 +317,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
this.settingHighlighter.clear(true);
this.bracesHidingRenderer.render(filterResult, this.preferencesModel.settingsGroups);
this.editSettingActionRenderer.render(filterResult.filteredGroups, this._associatedPreferencesModel);
this.extensionCodelensRenderer.render(filterResult);
} else {
this.settingHighlighter.clear(true);
this.filteredMatchesRenderer.render(null, this.preferencesModel.settingsGroups);
......@@ -323,6 +327,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
this.settingsGroupTitleRenderer.showGroup(0);
this.bracesHidingRenderer.render(null, this.preferencesModel.settingsGroups);
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
this.extensionCodelensRenderer.render(null);
}
this.hiddenAreasRenderer.render();
......@@ -836,6 +841,48 @@ export class HighlightMatchesRenderer extends Disposable {
}
}
export class ExtensionCodelensRenderer extends Disposable {
private decorationIds: string[] = [];
constructor(private editor: ICodeEditor) {
super();
}
public render(filterResult: IFilterResult): void {
this.editor.changeDecorations(changeAccessor => {
this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []);
});
const newExtensionGroup = filterResult && arrays.first(filterResult.filteredGroups, g => g.id === 'newExtensionsResult');
if (newExtensionGroup) {
this.editor.changeDecorations(changeAccessor => {
const settings = newExtensionGroup.sections[0].settings;
this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, settings.map(setting => this.createDecoration(setting)));
});
}
}
private createDecoration(setting: ISetting): IModelDeltaDecoration {
return {
range: new Range(setting.keyRange.startLineNumber, 1, setting.keyRange.endLineNumber, 1),
options: {
glyphMarginClassName: 'newExtensionInstall',
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
}
};
}
public dispose() {
if (this.decorationIds) {
this.decorationIds = this.editor.changeDecorations(changeAccessor => {
return changeAccessor.deltaDecorations(this.decorationIds, []);
});
}
super.dispose();
}
}
export interface IIndexedSetting extends ISetting {
index: number;
groupId: string;
......
......@@ -65,6 +65,7 @@ export interface ISearchResultGroup {
id: string;
label: string;
result: ISearchResult;
order: number;
}
export interface IFilterResult {
......@@ -82,7 +83,15 @@ export interface ISettingMatch {
}
export interface IScoredResults {
[key: string]: number;
[key: string]: IRemoteSetting;
}
export interface IRemoteSetting {
score: number;
key: string;
defaultValue: string;
description: string;
packageId: string;
}
export interface IFilterMetadata {
......
......@@ -611,7 +611,9 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
protected update(): IFilterResult {
// Grab current result groups, only render non-empty groups
const resultGroups = map.values(this._currentResultGroups);
const resultGroups = map
.values(this._currentResultGroups)
.sort((a, b) => a.order - b.order);
const nonEmptyResultGroups = resultGroups.filter(group => group.result.filterMatches.length);
const startLine = tail(this.settingsGroups).range.endLineNumber + 2;
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { ISettingsEditorModel, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService, ISearchResult, ISearchProvider, IGroupFilter, ISettingMatcher, IScoredResults } from 'vs/workbench/parts/preferences/common/preferences';
import { ISettingsEditorModel, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata, IPreferencesSearchService, ISearchResult, ISearchProvider, IGroupFilter, ISettingMatcher, IScoredResults, ISettingMatch, IRemoteSetting } from 'vs/workbench/parts/preferences/common/preferences';
import { IRange } from 'vs/editor/common/core/range';
import { distinct, top } from 'vs/base/common/arrays';
import * as strings from 'vs/base/common/strings';
......@@ -131,19 +131,37 @@ export class RemoteSearchProvider implements ISearchProvider {
searchModel(preferencesModel: ISettingsEditorModel): TPromise<ISearchResult> {
return this._remoteSearchP.then(remoteResult => {
if (remoteResult) {
const highScoreKey = top(Object.keys(remoteResult.scoredResults), (a, b) => remoteResult.scoredResults[b] - remoteResult.scoredResults[a], 1)[0];
const highScore = highScoreKey ? remoteResult.scoredResults[highScoreKey] : 0;
const minScore = highScore / 5;
if (!remoteResult) {
return null;
}
const resultKeys = Object.keys(remoteResult.scoredResults);
const highScoreKey = top(resultKeys, (a, b) => remoteResult.scoredResults[b].score - remoteResult.scoredResults[a].score, 1)[0];
const highScore = highScoreKey ? remoteResult.scoredResults[highScoreKey].score : 0;
const minScore = highScore / 5;
if (this.newExtensionsOnly) {
const passingScoreKeys = resultKeys.filter(k => remoteResult.scoredResults[k].score >= minScore);
const filterMatches: ISettingMatch[] = passingScoreKeys.map(k => {
const remoteSetting = remoteResult.scoredResults[k];
const setting = remoteSettingToISetting(remoteSetting);
return <ISettingMatch>{
setting,
score: remoteSetting.score,
matches: [] // TODO
};
});
return <ISearchResult>{
filterMatches,
metadata: remoteResult
};
} else {
const settingMatcher = this.getRemoteSettingMatcher(remoteResult.scoredResults, minScore, preferencesModel);
const filterMatches = preferencesModel.filterSettings(this._filter, group => null, settingMatcher);
return <ISearchResult>{
filterMatches,
metadata: remoteResult
};
} else {
return null;
}
});
}
......@@ -168,18 +186,18 @@ export class RemoteSearchProvider implements ISearchProvider {
}).then((result: any) => {
const timestamp = Date.now();
const duration = timestamp - start;
const suggestions = (result.value || [])
.map(r => ({
name: r.setting || r.Setting,
score: r['@search.score']
const remoteSettings: IRemoteSetting[] = (result.value || [])
.map(r => (<IRemoteSetting>{
key: JSON.parse(r.setting || r.Setting),
defaultValue: r['value'],
score: r['@search.score'],
description: JSON.parse(r['details']),
packageId: r['packageid']
}));
const scoredResults = Object.create(null);
suggestions.forEach(s => {
const name = s.name
.replace(/^"/, '')
.replace(/"$/, '');
scoredResults[name] = s.score;
remoteSettings.forEach(s => {
scoredResults[s.key] = s;
});
return <IFilterMetadata>{
......@@ -195,10 +213,10 @@ export class RemoteSearchProvider implements ISearchProvider {
private getRemoteSettingMatcher(scoredResults: IScoredResults, minScore: number, preferencesModel: ISettingsEditorModel): ISettingMatcher {
return (setting: ISetting) => {
const score = scoredResults[setting.key];
if (typeof score === 'number' && score >= minScore) {
const remoteSetting = scoredResults[setting.key];
if (remoteSetting && remoteSetting.score >= minScore) {
const settingMatches = new SettingMatches(this._filter, setting, false, (filter, setting) => preferencesModel.findValueMatches(filter, setting)).matches;
return { matches: settingMatches, score: scoredResults[setting.key] };
return { matches: settingMatches, score: remoteSetting.score };
}
return null;
......@@ -271,6 +289,19 @@ function escapeSpecialChars(query: string): string {
.trim();
}
function remoteSettingToISetting(remoteSetting: IRemoteSetting): ISetting {
return {
description: remoteSetting.description.split('\n'),
descriptionRanges: null,
key: remoteSetting.key,
keyRange: null,
value: remoteSetting.defaultValue,
range: null,
valueRange: null,
overrides: []
};
}
class SettingMatches {
private readonly descriptionMatchingWords: Map<string, IRange[]> = new Map<string, IRange[]>();
......@@ -345,7 +376,7 @@ class SettingMatches {
const valueMatches = or(matchesPrefix, matchesContiguousSubString)(searchString, setting.value);
valueRanges = valueMatches ? valueMatches.map(match => this.toValueRange(setting, match)) : this.getRangesForWords(words, this.valueMatchingWords, [this.keyMatchingWords, this.descriptionMatchingWords]);
} else {
valueRanges = this.valuesMatcher(searchString, setting);
valueRanges = this.valuesMatcher ? this.valuesMatcher(searchString, setting) : [];
}
return [...descriptionRanges, ...keyRanges, ...valueRanges];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册