提交 06040bdf 编写于 作者: R Rob Lourens

WIP - Remove 'most relevant' renderer, do IModel changing from prefs model

上级 26360c2c
......@@ -450,7 +450,7 @@ class PreferencesRenderers extends Disposable {
const editablePreferencesFilteredGroups = editablePreferencesFilterResult ? editablePreferencesFilterResult.filteredGroups : this._getAllPreferences(this._editablePreferencesRenderer);
const consolidatedSettings = this._consolidateSettings(editablePreferencesFilteredGroups, defaultPreferencesFilteredGroups);
if (defaultPreferencesFilterResult && defaultPreferencesFilterResult.remoteResult) {
if (defaultPreferencesFilterResult && defaultPreferencesFilterResult.metadata) {
// Disable navigation for remote settings search
this._settingsNavigator = null;
} else {
......
......@@ -296,7 +296,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
public filterPreferences(filterResult: IFilterResult): void {
this.filterResult = filterResult;
if (filterResult) {
if (filterResult.remoteResult) {
if (filterResult.metadata) {
this.filteredMatchesRenderer.render(null);
this.settingsGroupTitleRenderer.render(null);
} else {
......@@ -553,13 +553,6 @@ export class HiddenAreasRenderer extends Disposable {
}
export class MostRelevantMatchesRenderer extends Disposable implements HiddenAreasProvider {
private static settingsInsertStart = 4;
private static settingsInsertEnd = DefaultSettingsEditorModel.MOST_RELEVANT_SECTION_LENGTH - 1;
private static emptyLines = MostRelevantMatchesRenderer.settingsInsertEnd - MostRelevantMatchesRenderer.settingsInsertStart + 1;
private static bunchOfNewlines = strings.repeat('\n', MostRelevantMatchesRenderer.emptyLines);
private static editId = 'mostRelevantMatchesRenderer';
public hiddenAreas: IRange[] = [];
constructor(private editor: ICodeEditor,
......@@ -569,129 +562,10 @@ export class MostRelevantMatchesRenderer extends Disposable implements HiddenAre
}
public render(result: IFilterResult): void {
this.hiddenAreas = [];
if (result && result.matches.length && result.remoteResult) {
const settingsTextEndLine = this.renderResults(result);
this.hiddenAreas = [{
startLineNumber: settingsTextEndLine + 1,
startColumn: 0,
endLineNumber: this.editor.getModel().getLineCount(),
endColumn: 0
}];
} else {
this.renderSearchResultsSection();
this.hiddenAreas = [{
startLineNumber: MostRelevantMatchesRenderer.settingsInsertStart,
startColumn: 0,
endLineNumber: MostRelevantMatchesRenderer.settingsInsertEnd,
endColumn: 0
}];
if (result && result.metadata) {
// TODO - Hide unused portion of most relevant results section
}
}
private renderResults(result: IFilterResult): number {
this.hiddenAreas = [];
this.editor.updateOptions({ readOnly: false });
const relevantRanges = this.getOrderedSettingRanges(result.filteredGroups, result.allGroups, result.remoteResult.scores, this.editor.getModel());
let totalLines = 0;
const settingsValue = relevantRanges.map(visibleRange => {
const settingLines = (visibleRange.endLineNumber - visibleRange.startLineNumber) + 1;
if (totalLines + settingLines <= MostRelevantMatchesRenderer.emptyLines) {
totalLines += settingLines;
const value = this.editor.getModel().getValueInRange(visibleRange);
return value.replace(/([^,])\n$/, '$1,\n'); // ensure ends in ','
} else {
// Skip lines that push the total length past 50
return null;
}
})
.filter(line => !!line)
.join('\n');
const settingsTextStartLine = MostRelevantMatchesRenderer.settingsInsertStart;
const settingsTextEndLine = settingsTextStartLine + totalLines - 1;
this.editor.executeEdits(MostRelevantMatchesRenderer.editId, [{
text: settingsValue,
forceMoveMarkers: false,
range: new Range(settingsTextStartLine, 0, settingsTextEndLine, 0),
identifier: { major: 1, minor: 0 }
}]);
this.editor.updateOptions({ readOnly: true });
return settingsTextEndLine;
}
private renderSearchResultsSection(): void {
this.editor.updateOptions({ readOnly: false });
this.editor.executeEdits(MostRelevantMatchesRenderer.editId, [{
text: MostRelevantMatchesRenderer.bunchOfNewlines,
forceMoveMarkers: false,
range: new Range(MostRelevantMatchesRenderer.settingsInsertStart, 0, MostRelevantMatchesRenderer.settingsInsertEnd + 1, 0),
identifier: { major: 1, minor: 0 }
}]);
this.editor.updateOptions({ readOnly: true });
}
private getOrderedSettingRanges(filteredGroups: ISettingsGroup[], allSettingsGroups: ISettingsGroup[], scores: any, model: editorCommon.IModel): IRange[] {
// Manually exclude mostCommonlyUsed section to avoid dupes
if (filteredGroups.length && filteredGroups[0].id === 'mostCommonlyUsed') {
filteredGroups.shift();
}
const matchingRanges: { range: IRange, name: string }[] = [];
for (const group of allSettingsGroups) {
const filteredGroup = filteredGroups.filter(g => g.title === group.title)[0];
if (filteredGroup) {
for (const section of group.sections) {
for (const setting of section.settings) {
if (this.containsLine(setting.range.startLineNumber, filteredGroup)) {
matchingRanges.push({
name: setting.key,
range: this.createCompleteRange(setting.range, model)
});
}
}
}
}
}
return matchingRanges
.sort((a, b) => scores[b.name] - scores[a.name])
.map(r => r.range);
}
private containsLine(lineNumber: number, settingsGroup: ISettingsGroup): boolean {
if (settingsGroup.titleRange && lineNumber >= settingsGroup.titleRange.startLineNumber && lineNumber <= settingsGroup.titleRange.endLineNumber) {
return true;
}
for (const section of settingsGroup.sections) {
if (section.titleRange && lineNumber >= section.titleRange.startLineNumber && lineNumber <= section.titleRange.endLineNumber) {
return true;
}
for (const setting of section.settings) {
if (lineNumber >= setting.range.startLineNumber && lineNumber <= setting.range.endLineNumber) {
return true;
}
}
}
return false;
}
private createCompleteRange(range: IRange, model: editorCommon.IModel): IRange {
return {
startLineNumber: range.startLineNumber,
startColumn: model.getLineMinColumn(range.startLineNumber),
endLineNumber: range.endLineNumber,
endColumn: model.getLineMaxColumn(range.endLineNumber)
};
}
}
export class FeedbackWidgetRenderer extends Disposable {
......@@ -710,7 +584,7 @@ export class FeedbackWidgetRenderer extends Disposable {
public render(result: IFilterResult): void {
this._currentResult = result;
if (result && result.remoteResult) {
if (result && result.metadata) {
this.showWidget();
} else if (this._feedbackWidget) {
this.disposeWidget();
......@@ -727,8 +601,7 @@ export class FeedbackWidgetRenderer extends Disposable {
private getFeedback(): void {
const result = this._currentResult;
const actualResults = Object.keys(result.remoteResult.scores)
.sort((a, b) => result.remoteResult.scores[b] - result.remoteResult.scores[a]);
const actualResults = result.filteredGroups[0].sections[0].settings.map(setting => setting.key);
const actualResultText = actualResults.join('\n');
const contents = FeedbackWidgetRenderer.COMMENT_TEXT + '\n' + actualResultText;
......@@ -769,9 +642,9 @@ export class FeedbackWidgetRenderer extends Disposable {
userComment: commentText === FeedbackWidgetRenderer.COMMENT_TEXT ? undefined : commentText,
actualResults,
expectedResults,
url: result.remoteResult.url,
duration: result.remoteResult.duration,
timestamp: result.remoteResult.timestamp
url: result.metadata.remoteUrl,
duration: result.metadata.duration,
timestamp: result.metadata.timestamp
});
console.log('Feedback sent successfully');
}
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { ISettingsEditorModel, IFilterResult, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IRemoteFilterResult } from 'vs/workbench/parts/preferences/common/preferences';
import { ISettingsEditorModel, IFilterResult, ISetting, ISettingsGroup, IWorkbenchSettingsConfiguration, IFilterMetadata } from 'vs/workbench/parts/preferences/common/preferences';
import { IRange, Range } from 'vs/editor/common/core/range';
import { distinct } from 'vs/base/common/arrays';
import * as strings from 'vs/base/common/strings';
......@@ -73,9 +73,18 @@ class LocalSearchProvider {
}
}
export interface IRemoteScores {
[key: string]: number;
}
interface IRemoteResult {
metadata: IFilterMetadata;
scores: IRemoteScores;
}
class RemoteSearchProvider {
private _filter: string;
private _remoteSearchP: TPromise<IRemoteFilterResult>;
private _remoteSearchP: TPromise<IRemoteResult>;
constructor(filter: string) {
this._filter = filter;
......@@ -98,8 +107,8 @@ class RemoteSearchProvider {
};
if (remoteResult) {
const result = preferencesModel.filterSettings(this._filter, group => null, settingFilter);
result.remoteResult = remoteResult;
const result = preferencesModel.filterSettings(this._filter, group => null, settingFilter, remoteResult.scores);
result.metadata = remoteResult.metadata;
return result;
} else {
return null;
......@@ -108,16 +117,16 @@ class RemoteSearchProvider {
}
}
function getSettingsFromBing(filter: string): TPromise<IRemoteFilterResult> {
function getSettingsFromBing(filter: string): TPromise<IRemoteResult> {
const url = prepareUrl(filter);
console.log('fetching: ' + url);
const start = Date.now();
const p = fetch(url, {
headers: {
headers: new Headers({
'User-Agent': 'request',
'Content-Type': 'application/json; charset=utf-8',
'api-key': endpoint.key
}
})
})
.then(r => r.json())
.then(result => {
......@@ -138,11 +147,13 @@ function getSettingsFromBing(filter: string): TPromise<IRemoteFilterResult> {
scores[name] = s.score;
});
return <IRemoteFilterResult>{
url,
scores,
duration,
timestamp
return <IRemoteResult>{
metadata: {
remoteUrl: url,
duration,
timestamp
},
scores
};
});
......
......@@ -56,14 +56,13 @@ export interface IFilterResult {
filteredGroups: ISettingsGroup[];
allGroups: ISettingsGroup[];
matches: IRange[];
remoteResult?: IRemoteFilterResult;
metadata?: IFilterMetadata;
}
export interface IRemoteFilterResult {
url: string;
export interface IFilterMetadata {
remoteUrl: string;
timestamp: number;
duration: number;
scores: { [key: string]: number };
}
export interface IPreferencesEditorModel<T> {
......@@ -79,7 +78,7 @@ export type ISettingFilter = (setting: ISetting) => IRange[];
export interface ISettingsEditorModel extends IPreferencesEditorModel<ISetting> {
settingsGroups: ISettingsGroup[];
groupsTerms: string[];
filterSettings(filter: string, groupFilter: IGroupFilter, settingFilter: ISettingFilter): IFilterResult;
filterSettings(filter: string, groupFilter: IGroupFilter, settingFilter: ISettingFilter, scores?: { [key: string]: number }): IFilterResult;
findValueMatches(filter: string, setting: ISetting): IRange[];
}
......
......@@ -6,6 +6,7 @@
import * as nls from 'vs/nls';
import { assign } from 'vs/base/common/objects';
import * as arrays from 'vs/base/common/arrays';
import * as strings from 'vs/base/common/strings';
import URI from 'vs/base/common/uri';
import { IReference } from 'vs/base/common/lifecycle';
import Event from 'vs/base/common/event';
......@@ -17,7 +18,7 @@ import { IConfigurationNode, IConfigurationRegistry, Extensions, OVERRIDE_PROPER
import { ISettingsEditorModel, IKeybindingsEditorModel, ISettingsGroup, ISetting, IFilterResult, ISettingsSection, IGroupFilter, ISettingFilter } from 'vs/workbench/parts/preferences/common/preferences';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
import { IRange } from 'vs/editor/common/core/range';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ITextFileService, StateChange } from 'vs/workbench/services/textfile/common/textfiles';
import { TPromise } from 'vs/base/common/winjs.base';
import { Queue } from 'vs/base/common/async';
......@@ -478,11 +479,14 @@ export class WorkspaceConfigModel extends SettingsEditorModel implements ISettin
export class DefaultSettingsEditorModel extends AbstractSettingsModel implements ISettingsEditorModel {
public static MOST_RELEVANT_SECTION_LENGTH = 100;
public static MOST_RELEVANT_START_LINE = 3;
public static MOST_RELEVANT_END_LINE = DefaultSettingsEditorModel.MOST_RELEVANT_SECTION_LENGTH - 1;
private static BUNCH_OF_NEWLINES = strings.repeat('\n', DefaultSettingsEditorModel.MOST_RELEVANT_END_LINE - DefaultSettingsEditorModel.MOST_RELEVANT_START_LINE + 1);
private _allSettingsGroups: ISettingsGroup[];
private _content: string;
private _contentByLines: string[];
private _model: IModel;
private _settingsByName: Map<string, ISetting>;
constructor(
private _uri: URI,
......@@ -522,8 +526,42 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
return this.settingsGroups[0];
}
public filterSettings(filter: string, groupFilter: IGroupFilter, settingFilter: ISettingFilter): IFilterResult {
return this.doFilterSettings(filter, groupFilter, settingFilter);
public filterSettings(filter: string, groupFilter: IGroupFilter, settingFilter: ISettingFilter, scores?: { [key: string]: number }): IFilterResult {
if (scores) {
const group = this.getMostRelevantSettings(Object.keys(scores));
const builder = new SettingsContentBuilder(DefaultSettingsEditorModel.MOST_RELEVANT_START_LINE - 1);
builder.pushGroup(group);
const settingsTextEndLine = DefaultSettingsEditorModel.MOST_RELEVANT_START_LINE + builder.lineCount - 1;
this.model.applyEdits([
{
text: DefaultSettingsEditorModel.BUNCH_OF_NEWLINES,
forceMoveMarkers: false,
range: new Range(DefaultSettingsEditorModel.MOST_RELEVANT_START_LINE, 0, DefaultSettingsEditorModel.MOST_RELEVANT_END_LINE + 1, 0),
identifier: { major: 1, minor: 0 }
}
]);
this.model.applyEdits([
{
text: builder.content,
forceMoveMarkers: false,
range: new Range(DefaultSettingsEditorModel.MOST_RELEVANT_START_LINE, 0, settingsTextEndLine, 0),
identifier: { major: 1, minor: 0 }
}
]);
return {
allGroups: this._allSettingsGroups,
filteredGroups: [group],
matches: [],
query: filter
};
} else {
// local
return this.doFilterSettings(filter, groupFilter, settingFilter);
}
}
public findValueMatches(filter: string, setting: ISetting): IRange[] {
......@@ -543,25 +581,58 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
return null;
}
private getMostRelevantSettings(rankedSettingNames: string[]): ISettingsGroup {
const settings = rankedSettingNames.map(key => {
const setting = this._settingsByName.get(key);
if (setting) {
return <ISetting>{
description: setting.description,
key: setting.key,
value: setting.value,
range: null,
valueRange: null,
overrides: []
};
}
return null;
}).filter(setting => !!setting);
return <ISettingsGroup>{
id: 'mostRelevant',
range: null,
title: nls.localize('mostRelevant', "Most Relevant"),
titleRange: null,
sections: [
{
settings
}
]
};
}
private parse() {
const configurations = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurations().slice();
const settingsGroups = this.removeEmptySettingsGroups(configurations.sort(this.compareConfigurationNodes).reduce((result, config, index, array) => this.parseConfig(config, result, array), []));
this.initAllSettingsMap(settingsGroups);
const mostCommonlyUsed = this.getMostCommonlyUsedSettings(settingsGroups);
this._allSettingsGroups = [mostCommonlyUsed, ...settingsGroups];
this._content = this.toContent(mostCommonlyUsed, settingsGroups);
}
private getMostCommonlyUsedSettings(allSettingsGroups: ISettingsGroup[]): ISettingsGroup {
const map: Map<string, ISetting> = new Map<string, ISetting>();
private initAllSettingsMap(allSettingsGroups: ISettingsGroup[]): void {
this._settingsByName = new Map<string, ISetting>();
for (const group of allSettingsGroups) {
for (const section of group.sections) {
for (const setting of section.settings) {
map.set(setting.key, setting);
this._settingsByName.set(setting.key, setting);
}
}
}
}
private getMostCommonlyUsedSettings(allSettingsGroups: ISettingsGroup[]): ISettingsGroup {
const settings = this._mostCommonlyUsedSettingsKeys.map(key => {
const setting = map.get(key);
const setting = this._settingsByName.get(key);
if (setting) {
return <ISetting>{
description: setting.description,
......@@ -675,20 +746,48 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
}
private toContent(mostCommonlyUsed: ISettingsGroup, settingsGroups: ISettingsGroup[]): string {
this._contentByLines = [];
this._contentByLines.push('[');
this._contentByLines.push('{');
this._contentByLines.push(...arrays.fill(DefaultSettingsEditorModel.MOST_RELEVANT_SECTION_LENGTH - 3, () => ''));
this._contentByLines.push('}');
this._contentByLines.push(',');
this.pushGroups([mostCommonlyUsed]);
this._contentByLines.push(',');
this.pushGroups(settingsGroups);
this._contentByLines.push(']');
const builder = new SettingsContentBuilder();
builder.pushLine('[');
builder.pushLine('{');
builder.pushLine(...arrays.fill(DefaultSettingsEditorModel.MOST_RELEVANT_SECTION_LENGTH - 3, () => ''));
builder.pushLine('}');
builder.pushLine(',');
builder.pushGroups([mostCommonlyUsed]);
builder.pushLine(',');
builder.pushGroups(settingsGroups);
builder.pushLine(']');
return builder.content;
}
public dispose(): void {
super.dispose();
}
}
class SettingsContentBuilder {
private _contentByLines: string[];
get content(): string {
return this._contentByLines.join('\n');
}
private pushGroups(settingsGroups: ISettingsGroup[]): void {
get lineCount(): number {
return this._contentByLines.length;
}
private get lineCountWithOffset(): number {
return this._contentByLines.length + this._rangeOffset;
}
constructor(private _rangeOffset = 0) {
this._contentByLines = [];
}
pushLine(...lineText: string[]): void {
this._contentByLines.push(...lineText);
}
pushGroups(settingsGroups: ISettingsGroup[]): void {
let lastSetting: ISetting = null;
this._contentByLines.push('{');
this._contentByLines.push('');
......@@ -702,16 +801,16 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
this._contentByLines.push('}');
}
private pushGroup(group: ISettingsGroup): ISetting {
pushGroup(group: ISettingsGroup): ISetting {
const indent = ' ';
let lastSetting: ISetting = null;
this._contentByLines.push('');
let groupStart = this._contentByLines.length + 1;
let groupStart = this.lineCountWithOffset + 1;
for (const section of group.sections) {
if (section.title) {
let sectionTitleStart = this._contentByLines.length + 1;
let sectionTitleStart = this.lineCountWithOffset + 1;
this.addDescription([section.title], indent, this._contentByLines);
section.titleRange = { startLineNumber: sectionTitleStart, startColumn: 1, endLineNumber: this._contentByLines.length, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
section.titleRange = { startLineNumber: sectionTitleStart, startColumn: 1, endLineNumber: this.lineCountWithOffset, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
}
if (section.settings.length) {
......@@ -725,32 +824,32 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
}
}
group.range = { startLineNumber: groupStart, startColumn: 1, endLineNumber: this._contentByLines.length, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
group.range = { startLineNumber: groupStart, startColumn: 1, endLineNumber: this.lineCountWithOffset, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
return lastSetting;
}
private pushSetting(setting: ISetting, indent: string): void {
const settingStart = this._contentByLines.length + 1;
const settingStart = this.lineCountWithOffset + 1;
setting.descriptionRanges = [];
const descriptionPreValue = indent + '// ';
for (const line of setting.description) {
this._contentByLines.push(descriptionPreValue + line);
setting.descriptionRanges.push({ startLineNumber: this._contentByLines.length, startColumn: this._contentByLines[this._contentByLines.length - 1].indexOf(line) + 1, endLineNumber: this._contentByLines.length, endColumn: this._contentByLines[this._contentByLines.length - 1].length });
setting.descriptionRanges.push({ startLineNumber: this.lineCountWithOffset, startColumn: this._contentByLines[this._contentByLines.length - 1].indexOf(line) + 1, endLineNumber: this.lineCountWithOffset, endColumn: this._contentByLines[this._contentByLines.length - 1].length });
}
let preValueConent = indent;
const keyString = JSON.stringify(setting.key);
preValueConent += keyString;
setting.keyRange = { startLineNumber: this._contentByLines.length + 1, startColumn: preValueConent.indexOf(setting.key) + 1, endLineNumber: this._contentByLines.length + 1, endColumn: setting.key.length };
setting.keyRange = { startLineNumber: this.lineCountWithOffset + 1, startColumn: preValueConent.indexOf(setting.key) + 1, endLineNumber: this.lineCountWithOffset + 1, endColumn: setting.key.length };
preValueConent += ': ';
const valueStart = this._contentByLines.length + 1;
const valueStart = this.lineCountWithOffset + 1;
this.pushValue(setting, preValueConent, indent);
setting.valueRange = { startLineNumber: valueStart, startColumn: preValueConent.length + 1, endLineNumber: this._contentByLines.length, endColumn: this._contentByLines[this._contentByLines.length - 1].length + 1 };
setting.valueRange = { startLineNumber: valueStart, startColumn: preValueConent.length + 1, endLineNumber: this.lineCountWithOffset, endColumn: this._contentByLines[this._contentByLines.length - 1].length + 1 };
this._contentByLines[this._contentByLines.length - 1] += ',';
this._contentByLines.push('');
setting.range = { startLineNumber: settingStart, startColumn: 1, endLineNumber: this._contentByLines.length, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
setting.range = { startLineNumber: settingStart, startColumn: 1, endLineNumber: this.lineCountWithOffset, endColumn: this._contentByLines[this._contentByLines.length - 1].length };
}
private pushValue(setting: ISetting, preValueConent: string, indent: string): void {
......@@ -783,11 +882,6 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
result.push(indent + '// ' + line);
}
}
public dispose(): void {
super.dispose();
}
}
export function defaultKeybindingsContents(keybindingService: IKeybindingService): string {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册