Skip to content

Commit

Permalink
#1587 Support actions for language based settings
Browse files Browse the repository at this point in the history
  • Loading branch information
sandy081 committed Jan 23, 2017
1 parent 7e97ca5 commit 28d937f
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 40 deletions.
10 changes: 9 additions & 1 deletion src/vs/platform/configuration/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export class ConfigModel<T> implements IConfigModel<T> {

function onOverrideSettingsValue(property: string, value: any): void {
overrides.push({
identifiers: [property.substring(1, property.length - 1).trim()],
identifiers: [overrideIdentifierFromKey(property).trim()],
raw: value,
contents: null
});
Expand Down Expand Up @@ -256,4 +256,12 @@ export class DefaultConfigModel<T> extends ConfigModel<T> {
public get keys(): string[] {
return getConfigurationKeys();
}
}

export function overrideIdentifierFromKey(key: string): string {
return key.substring(1, key.length - 1);
}

export function keyFromOverrideIdentifier(overrideIdentifier: string): string {
return `[${overrideIdentifier}]`;
}
4 changes: 2 additions & 2 deletions src/vs/workbench/browser/parts/editor/editorStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,8 @@ export class ChangeModeAction extends Action {
const configuration = this.configurationService.getConfiguration<{ tabSize: number; insertSpaces: boolean }>('editor');
const {eol} = this.configurationService.getConfiguration<{ eol: string }>('files');
if (setting) {
if (setting.settings.length) {
const lastSetting = setting.settings[setting.settings.length - 1];
if (setting.overrides.length) {
const lastSetting = setting.overrides[setting.overrides.length - 1];
let content;
if (lastSetting.valueRange.endLineNumber === setting.range.endLineNumber) {
content = ',' + eol + this.spaces(2, configuration) + eol + this.spaces(1, configuration);
Expand Down
75 changes: 51 additions & 24 deletions src/vs/workbench/parts/preferences/browser/preferencesEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { VSash } from 'vs/base/browser/ui/sash/sash';
import { Widget } from 'vs/base/browser/ui/widget';
import { overrideIdentifierFromKey } from 'vs/platform/configuration/common/model';

// Ignore following contributions
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
Expand Down Expand Up @@ -469,7 +470,7 @@ export interface IPreferencesRenderer<T> {
onClearFocusPreference: Event<ISetting>;
preferencesModel: ISettingsEditorModel;
render(): void;
updatePreference(setting: ISetting, value: any): void;
updatePreference(key: string, value: any, source: T): void;
filterPreferences(filterResult: IFilterResult): void;
focusPreference(setting: ISetting): void;
clearFocus(setting: ISetting): void;
Expand Down Expand Up @@ -601,7 +602,7 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
this.defaultSettingsModel = <DefaultSettingsEditorModel>defaultSettingsModel;
this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.preferencesModel, () => defaultSettingsModel, this.settingHighlighter));
this._register(this.editor.getModel().onDidChangeContent(() => this.modelChangeDelayer.trigger(() => this.onModelChanged())));
this._register(this.editSettingActionRenderer.onUpdateSetting(({setting, value}) => this.updatePreference(setting, value)));
this._register(this.editSettingActionRenderer.onUpdateSetting(({key, value, source}) => this.updatePreference(key, value, source)));
return null;
});
}
Expand All @@ -614,18 +615,35 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
this.render();
}

public updatePreference(setting: ISetting, value: any): void {
this.telemetryService.publicLog('defaultSettingsActions.copySetting', { userConfigurationKeys: [setting.key] });
this.configurationEditingService.writeConfiguration(this.preferencesModel.configurationTarget, { key: setting.key, value }, { writeToBuffer: true, autoSave: true })
.then(() => this.onSettingUpdated(setting), error => this.messageService.show(Severity.Error, error));
public updatePreference(key: string, value: any, source: ISetting): void {
this.telemetryService.publicLog('defaultSettingsActions.copySetting', { userConfigurationKeys: [key] });
const overrideIdentifier = source.overrideOf ? overrideIdentifierFromKey(source.overrideOf.key) : null;
this.configurationEditingService.writeConfiguration(this.preferencesModel.configurationTarget, { key, value, overrideIdentifier }, { writeToBuffer: true, autoSave: true })
.then(() => this.onSettingUpdated(source), error => this.messageService.show(Severity.Error, error));
}

private onSettingUpdated(setting: ISetting) {
this.editor.focus();
setting = this.preferencesModel.getPreference(setting.key);
// TODO:@sandy Selection range should be template range
this.editor.setSelection(setting.valueRange);
this.settingHighlighter.highlight(this.preferencesModel.getPreference(setting.key), true);
setting = this.getSetting(setting);
if (setting) {
// TODO:@sandy Selection range should be template range
this.editor.setSelection(setting.valueRange);
this.settingHighlighter.highlight(setting, true);
}
}

private getSetting(setting: ISetting): ISetting {
const {key, overrideOf} = setting;
if (overrideOf) {
const setting = this.getSetting(overrideOf);
for (const override of setting.overrides) {
if (override.key === key) {
return override;
}
}
return null;
}
return this.preferencesModel.getPreference(key);
}

public filterPreferences(filterResult: IFilterResult): void {
Expand All @@ -635,7 +653,7 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
const settings = distinct(filterResult.filteredGroups.reduce((settings: ISetting[], settingsGroup: ISettingsGroup) => {
for (const section of settingsGroup.sections) {
for (const setting of section.settings) {
const s = this.preferencesModel.getPreference(setting.key);
const s = this.getSetting(setting);
if (s) {
settings.push(s);
}
Expand All @@ -648,7 +666,7 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
}

public focusPreference(setting: ISetting): void {
const s = this.preferencesModel.getPreference(setting.key);
const s = this.getSetting(setting);
if (s) {
this.settingHighlighter.highlight(s, true);
} else {
Expand Down Expand Up @@ -691,7 +709,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor));
this.filteredSettingsNavigationRenderer = this._register(instantiationService.createInstance(FilteredSettingsNavigationRenderer, editor, this.settingHighlighter));
this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, () => (<DefaultPreferencesCodeEditor>this.editor).settingsModel, this.settingHighlighter));
this._register(this.editSettingActionRenderer.onUpdateSetting(({setting, value}) => this.updatePreference(setting, value)));
this._register(this.editSettingActionRenderer.onUpdateSetting(({key, value, source}) => this.updatePreference(key, value, source)));
const paranthesisHidingRenderer = this._register(instantiationService.createInstance(StaticContentHidingRenderer, editor, preferencesModel.settingsGroups));
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, paranthesisHidingRenderer]));

Expand Down Expand Up @@ -739,10 +757,10 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
this.settingsGroupTitleRenderer.collapseAll();
}

public updatePreference(setting: ISetting, value: any): void {
public updatePreference(key: string, value: any, source: ISetting): void {
const settingsEditor = this.getEditableSettingsEditor();
if (settingsEditor) {
settingsEditor.getContribution<PreferencesEditorContribution<ISetting>>(SettingsEditorContribution.ID).getPreferencesRenderer().updatePreference(setting, value);
settingsEditor.getContribution<PreferencesEditorContribution<ISetting>>(SettingsEditorContribution.ID).getPreferencesRenderer().updatePreference(key, value, source);
}
}

Expand Down Expand Up @@ -1080,8 +1098,8 @@ class EditSettingRenderer extends Disposable {
private settingsGroups: ISettingsGroup[];
private toggleEditPreferencesForMouseMoveDelayer: Delayer<void>;

private _onUpdateSetting: Emitter<{ setting: ISetting, value: any }> = new Emitter<{ setting: ISetting, value: any }>();
public readonly onUpdateSetting: Event<{ setting: ISetting, value: any }> = this._onUpdateSetting.event;
private _onUpdateSetting: Emitter<{ key: string, value: any, source: ISetting }> = new Emitter<{ key: string, value: any, source: ISetting }>();
public readonly onUpdateSetting: Event<{ key: string, value: any, source: ISetting }> = this._onUpdateSetting.event;

constructor(private editor: ICodeEditor, private masterSettingsModel: ISettingsEditorModel,
private otherSettingsModel: () => ISettingsEditorModel,
Expand Down Expand Up @@ -1186,7 +1204,16 @@ class EditSettingRenderer extends Disposable {
break;
}
if (lineNumber >= setting.range.startLineNumber && lineNumber <= setting.range.endLineNumber) {
settings.push(setting);
if (setting.overrides.length > 0) {
// Only one level because override settings cannot have override settings
for (const overrideSetting of setting.overrides) {
if (lineNumber >= overrideSetting.range.startLineNumber && lineNumber <= overrideSetting.range.endLineNumber) {
settings.push(overrideSetting);
}
}
} else {
settings.push(setting);
}
}
}
}
Expand Down Expand Up @@ -1220,12 +1247,12 @@ class EditSettingRenderer extends Disposable {
id: 'truthyValue',
label: 'true',
enabled: true,
run: () => this.updateSetting(setting, true)
run: () => this.updateSetting(setting.key, true, setting)
}, <IAction>{
id: 'falsyValue',
label: 'false',
enabled: true,
run: () => this.updateSetting(setting, false)
run: () => this.updateSetting(setting.key, false, setting)
}];
}
if (jsonSchema.enum) {
Expand All @@ -1234,7 +1261,7 @@ class EditSettingRenderer extends Disposable {
id: value,
label: JSON.stringify(value),
enabled: true,
run: () => this.updateSetting(setting, value)
run: () => this.updateSetting(setting.key, value, setting)
};
});
}
Expand All @@ -1248,14 +1275,14 @@ class EditSettingRenderer extends Disposable {
id: 'setDefaultValue',
label: settingInOtherModel ? nls.localize('replaceDefaultValue', "Replace in Settings") : nls.localize('copyDefaultValue', "Copy to Settings"),
enabled: true,
run: () => this.updateSetting(setting, setting.value)
run: () => this.updateSetting(setting.key, setting.value, setting)
}];
}
return [];
}

private updateSetting(setting: ISetting, value: any): void {
this._onUpdateSetting.fire({ setting, value });
private updateSetting(key: string, value: any, source: ISetting): void {
this._onUpdateSetting.fire({ key, value, source });
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/parts/preferences/common/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export interface ISetting {
valueRange: IRange;
description: string[];
descriptionRanges: IRange[];
settings: ISetting[];
overrides?: ISetting[];
overrideOf?: ISetting;
}

export interface IFilterResult {
Expand Down
17 changes: 9 additions & 8 deletions src/vs/workbench/parts/preferences/common/preferencesModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
}
if (previousParents.length === 1 || (previousParents.length === 2 && overrideSetting !== null)) {
// settings value started
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.settings[overrideSetting.settings.length - 1];
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1];
let valueStartPosition = model.getPositionAt(offset);
let valueEndPosition = model.getPositionAt(offset + length);
setting.value = value;
Expand Down Expand Up @@ -287,7 +287,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
if (previousParents.length === 1 || (previousParents.length === 2 && overrideSetting !== null)) {
// setting started
let settingStartPosition = model.getPositionAt(offset);
const setting = {
const setting: ISetting = {
description: [],
key: name,
keyRange: {
Expand All @@ -305,23 +305,24 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
value: null,
valueRange: null,
descriptionRanges: null,
settings: []
overrides: [],
overrideOf: overrideSetting
};
if (previousParents.length === 1) {
settings.push(setting);
if (OVERRIDE_PROPERTY_PATTERN.test(name)) {
overrideSetting = setting;
}
} else {
overrideSetting.settings.push(setting);
overrideSetting.overrides.push(setting);
}
}
},
onObjectEnd: (offset: number, length: number) => {
currentParent = previousParents.pop();
if (previousParents.length === 1 || (previousParents.length === 2 && overrideSetting !== null)) {
// setting ended
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.settings[overrideSetting.settings.length - 1];
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1];
let valueEndPosition = model.getPositionAt(offset + length);
setting.valueRange = assign(setting.valueRange, {
endLineNumber: valueEndPosition.lineNumber,
Expand Down Expand Up @@ -354,7 +355,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
currentParent = previousParents.pop();
if (previousParents.length === 1 || (previousParents.length === 2 && overrideSetting !== null)) {
// setting value ended
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.settings[overrideSetting.settings.length - 1];
const setting = previousParents.length === 1 ? settings[settings.length - 1] : overrideSetting.overrides[overrideSetting.overrides.length - 1];
let valueEndPosition = model.getPositionAt(offset + length);
setting.valueRange = assign(setting.valueRange, {
endLineNumber: valueEndPosition.lineNumber,
Expand Down Expand Up @@ -466,7 +467,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
value: setting.value,
range: null,
valueRange: null,
settings: []
overrides: []
};
}
return null;
Expand Down Expand Up @@ -506,7 +507,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
const prop = config.properties[key];
const value = prop.default;
const description = (prop.description || '').split('\n');
return { key, value, description, range: null, keyRange: null, valueRange: null, descriptionRanges: [], settings: [] };
return { key, value, description, range: null, keyRange: null, valueRange: null, descriptionRanges: [], overrides: [] };
});
settingsGroup.sections[settingsGroup.sections.length - 1].settings.push(...configurationSettings);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export enum ConfigurationTarget {
export interface IConfigurationValue {
key: string;
value: any;
overrideIdentifier?: string;
}

export interface IConfigurationEditingOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { keyFromOverrideIdentifier } from 'vs/platform/configuration/common/model';
import { WORKSPACE_CONFIG_DEFAULT_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationEditingService, ConfigurationEditingErrorCode, IConfigurationEditingError, ConfigurationTarget, IConfigurationValue, IConfigurationEditingOptions } from 'vs/workbench/services/configuration/common/configurationEditing';
Expand Down Expand Up @@ -187,8 +188,8 @@ export class ConfigurationEditingService implements IConfigurationEditingService
const {tabSize, insertSpaces} = this.configurationService.getConfiguration<{ tabSize: number; insertSpaces: boolean }>('editor');
const {eol} = this.configurationService.getConfiguration<{ eol: string }>('files');

const {key, value} = edit;
return setProperty(content, [key], value, { tabSize, insertSpaces, eol });
const {key, value, overrideIdentifier} = edit;
return setProperty(content, overrideIdentifier ? [keyFromOverrideIdentifier(overrideIdentifier), key] : [key], value, { tabSize, insertSpaces, eol });
}

private validate(target: ConfigurationTarget, operation: IConfigurationEditOperation, options: IConfigurationEditingOptions): TPromise<IValidationResult> {
Expand Down Expand Up @@ -272,9 +273,9 @@ export class ConfigurationEditingService implements IConfigurationEditingService
}

if (target === ConfigurationTarget.USER) {
return { key: config.key, value: config.value, target: URI.file(this.environmentService.appSettingsPath) };
return { key: config.key, value: config.value, overrideIdentifier: config.overrideIdentifier, target: URI.file(this.environmentService.appSettingsPath) };
}

return { key: config.key, value: config.value, target: this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH) };
return { key: config.key, value: config.value, overrideIdentifier: config.overrideIdentifier, target: this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH) };
}
}

0 comments on commit 28d937f

Please sign in to comment.