Skip to content

Commit 45f9ce7

Browse files
authored
adopt keybindings for profile change (microsoft#153077)
1 parent 66b67e2 commit 45f9ce7

File tree

3 files changed

+89
-66
lines changed

3 files changed

+89
-66
lines changed

src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
7-
import { Disposable } from 'vs/base/common/lifecycle';
7+
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
88
import { Schemas } from 'vs/base/common/network';
99
import { isObject } from 'vs/base/common/types';
1010
import { URI } from 'vs/base/common/uri';
@@ -244,25 +244,32 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
244244
return accessor.get(IPreferencesService).openRawDefaultSettings();
245245
}
246246
});
247-
registerAction2(class extends Action2 {
248-
constructor() {
249-
super({
250-
id: '_workbench.openUserSettingsEditor',
251-
title: OPEN_SETTINGS2_ACTION_TITLE,
252-
icon: preferencesOpenSettingsIcon,
253-
menu: [{
254-
id: MenuId.EditorTitle,
255-
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.settingsResource.toString()), ContextKeyExpr.not('isInDiffEditor')),
256-
group: 'navigation',
257-
order: 1
258-
}]
259-
});
260-
}
261-
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
262-
args = sanitizeOpenSettingsArgs(args);
263-
return accessor.get(IPreferencesService).openUserSettings({ jsonEditor: false, ...args });
264-
}
265-
});
247+
248+
const registerOpenUserSettingsEditorFromJsonActionDisposable = this._register(new MutableDisposable());
249+
const registerOpenUserSettingsEditorFromJsonAction = () => {
250+
registerOpenUserSettingsEditorFromJsonActionDisposable.value = registerAction2(class extends Action2 {
251+
constructor() {
252+
super({
253+
id: '_workbench.openUserSettingsEditor',
254+
title: OPEN_SETTINGS2_ACTION_TITLE,
255+
icon: preferencesOpenSettingsIcon,
256+
menu: [{
257+
id: MenuId.EditorTitle,
258+
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.settingsResource.toString()), ContextKeyExpr.not('isInDiffEditor')),
259+
group: 'navigation',
260+
order: 1
261+
}]
262+
});
263+
}
264+
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
265+
args = sanitizeOpenSettingsArgs(args);
266+
return accessor.get(IPreferencesService).openUserSettings({ jsonEditor: false, ...args });
267+
}
268+
});
269+
};
270+
registerOpenUserSettingsEditorFromJsonAction();
271+
this._register(this.userDataProfileService.onDidChangeCurrentProfile(() => registerOpenUserSettingsEditorFromJsonAction()));
272+
266273
registerAction2(class extends Action2 {
267274
constructor() {
268275
super({
@@ -728,34 +735,39 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
728735
private registerKeybindingsActions() {
729736
const that = this;
730737
const category = { value: nls.localize('preferences', "Preferences"), original: 'Preferences' };
731-
registerAction2(class extends Action2 {
732-
constructor() {
733-
super({
734-
id: 'workbench.action.openGlobalKeybindings',
735-
title: { value: nls.localize('openGlobalKeybindings', "Open Keyboard Shortcuts"), original: 'Open Keyboard Shortcuts' },
736-
category,
737-
icon: preferencesOpenSettingsIcon,
738-
keybinding: {
739-
when: null,
740-
weight: KeybindingWeight.WorkbenchContrib,
741-
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyS)
742-
},
743-
menu: [
744-
{ id: MenuId.CommandPalette },
745-
{
746-
id: MenuId.EditorTitle,
747-
when: ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.keybindingsResource.toString()),
748-
group: 'navigation',
749-
order: 1,
750-
}
751-
]
752-
});
753-
}
754-
run(accessor: ServicesAccessor, args: string | undefined) {
755-
const query = typeof args === 'string' ? args : undefined;
756-
return accessor.get(IPreferencesService).openGlobalKeybindingSettings(false, { query });
757-
}
758-
});
738+
const registerOpenGlobalKeybindingsActionDisposable = this._register(new MutableDisposable());
739+
const registerOpenGlobalKeybindingsAction = () => {
740+
registerOpenGlobalKeybindingsActionDisposable.value = registerAction2(class extends Action2 {
741+
constructor() {
742+
super({
743+
id: 'workbench.action.openGlobalKeybindings',
744+
title: { value: nls.localize('openGlobalKeybindings', "Open Keyboard Shortcuts"), original: 'Open Keyboard Shortcuts' },
745+
category,
746+
icon: preferencesOpenSettingsIcon,
747+
keybinding: {
748+
when: null,
749+
weight: KeybindingWeight.WorkbenchContrib,
750+
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyS)
751+
},
752+
menu: [
753+
{ id: MenuId.CommandPalette },
754+
{
755+
id: MenuId.EditorTitle,
756+
when: ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.keybindingsResource.toString()),
757+
group: 'navigation',
758+
order: 1,
759+
}
760+
]
761+
});
762+
}
763+
run(accessor: ServicesAccessor, args: string | undefined) {
764+
const query = typeof args === 'string' ? args : undefined;
765+
return accessor.get(IPreferencesService).openGlobalKeybindingSettings(false, { query });
766+
}
767+
});
768+
};
769+
registerOpenGlobalKeybindingsAction();
770+
this._register(this.userDataProfileService.onDidChangeCurrentProfile(() => registerOpenGlobalKeybindingsAction()));
759771
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
760772
command: {
761773
id: 'workbench.action.openGlobalKeybindings',

src/vs/workbench/services/keybinding/browser/keybindingService.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
3434
import { MenuRegistry } from 'vs/platform/actions/common/actions';
3535
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
3636
import { commandsExtensionPoint } from 'vs/workbench/services/actions/common/menusExtensionPoint';
37-
import { Disposable } from 'vs/base/common/lifecycle';
37+
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
3838
import { RunOnceScheduler } from 'vs/base/common/async';
39-
import { URI } from 'vs/base/common/uri';
4039
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
4140
import { parse } from 'vs/base/common/json';
4241
import * as objects from 'vs/base/common/objects';
@@ -224,7 +223,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
224223

225224
this._cachedResolver = null;
226225

227-
this.userKeybindings = this._register(new UserKeybindings(userDataProfileService.currentProfile.keybindingsResource, fileService, logService));
226+
this.userKeybindings = this._register(new UserKeybindings(userDataProfileService, fileService, logService));
228227
this.userKeybindings.initialize().then(() => {
229228
if (this.userKeybindings.keybindings.length) {
230229
this.updateResolver();
@@ -707,34 +706,49 @@ class UserKeybindings extends Disposable {
707706

708707
private readonly reloadConfigurationScheduler: RunOnceScheduler;
709708

709+
private readonly watchDisposables = this._register(new DisposableStore());
710+
710711
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
711712
readonly onDidChange: Event<void> = this._onDidChange.event;
712713

713714
constructor(
714-
private readonly keybindingsResource: URI,
715+
private readonly userDataProfileService: IUserDataProfileService,
715716
private readonly fileService: IFileService,
716717
logService: ILogService,
717718
) {
718719
super();
719720

720-
this._register(fileService.watch(dirname(keybindingsResource)));
721-
// Also listen to the resource incase the resource is a symlink - https://github.com/microsoft/vscode/issues/118134
722-
this._register(this.fileService.watch(this.keybindingsResource));
721+
this.watch();
722+
723723
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reload().then(changed => {
724724
if (changed) {
725725
this._onDidChange.fire();
726726
}
727727
}), 50));
728-
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.keybindingsResource))(() => {
728+
729+
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.userDataProfileService.currentProfile.keybindingsResource))(() => {
729730
logService.debug('Keybindings file changed');
730731
this.reloadConfigurationScheduler.schedule();
731732
}));
733+
732734
this._register(this.fileService.onDidRunOperation((e) => {
733-
if (e.operation === FileOperation.WRITE && e.resource.toString() === this.keybindingsResource.toString()) {
735+
if (e.operation === FileOperation.WRITE && e.resource.toString() === this.userDataProfileService.currentProfile.keybindingsResource.toString()) {
734736
logService.debug('Keybindings file written');
735737
this.reloadConfigurationScheduler.schedule();
736738
}
737739
}));
740+
741+
this._register(userDataProfileService.onDidChangeCurrentProfile(e => {
742+
this.watch();
743+
e.join(this.reload().then(() => this.reloadConfigurationScheduler.schedule()));
744+
}));
745+
}
746+
747+
private watch(): void {
748+
this.watchDisposables.clear();
749+
this.watchDisposables.add(this.fileService.watch(dirname(this.userDataProfileService.currentProfile.keybindingsResource)));
750+
// Also listen to the resource incase the resource is a symlink - https://github.com/microsoft/vscode/issues/118134
751+
this.watchDisposables.add(this.fileService.watch(this.userDataProfileService.currentProfile.keybindingsResource));
738752
}
739753

740754
async initialize(): Promise<void> {
@@ -744,7 +758,7 @@ class UserKeybindings extends Disposable {
744758
private async reload(): Promise<boolean> {
745759
const existing = this._keybindings;
746760
try {
747-
const content = await this.fileService.readFile(this.keybindingsResource);
761+
const content = await this.fileService.readFile(this.userDataProfileService.currentProfile.keybindingsResource);
748762
const value = parse(content.value.toString());
749763
this._keybindings = isArray(value) ? value : [];
750764
} catch (e) {

src/vs/workbench/services/keybinding/common/keybindingEditing.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { setProperty } from 'vs/base/common/jsonEdit';
1111
import { Edit } from 'vs/base/common/jsonFormatter';
1212
import { Disposable, IReference } from 'vs/base/common/lifecycle';
1313
import { isArray } from 'vs/base/common/types';
14-
import { URI } from 'vs/base/common/uri';
1514
import { EditOperation } from 'vs/editor/common/core/editOperation';
1615
import { Range } from 'vs/editor/common/core/range';
1716
import { Selection } from 'vs/editor/common/core/selection';
@@ -47,8 +46,6 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
4746
public _serviceBrand: undefined;
4847
private queue: Queue<void>;
4948

50-
private resource: URI = this.userDataProfileService.currentProfile.keybindingsResource;
51-
5249
constructor(
5350
@ITextModelService private readonly textModelResolverService: ITextModelService,
5451
@ITextFileService private readonly textFileService: ITextFileService,
@@ -122,7 +119,7 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
122119
}
123120

124121
private save(): Promise<any> {
125-
return this.textFileService.save(this.resource);
122+
return this.textFileService.save(this.userDataProfileService.currentProfile.keybindingsResource);
126123
}
127124

128125
private updateKeybinding(keybindingItem: ResolvedKeybindingItem, newKey: string, when: string | undefined, model: ITextModel, userKeybindingEntryIndex: number): void {
@@ -244,18 +241,18 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding
244241
}
245242

246243
private resolveModelReference(): Promise<IReference<IResolvedTextEditorModel>> {
247-
return this.fileService.exists(this.resource)
244+
return this.fileService.exists(this.userDataProfileService.currentProfile.keybindingsResource)
248245
.then(exists => {
249246
const EOL = this.configurationService.getValue<{ eol: string }>('files', { overrideIdentifier: 'json' })['eol'];
250-
const result: Promise<any> = exists ? Promise.resolve(null) : this.textFileService.write(this.resource, this.getEmptyContent(EOL), { encoding: 'utf8' });
251-
return result.then(() => this.textModelResolverService.createModelReference(this.resource));
247+
const result: Promise<any> = exists ? Promise.resolve(null) : this.textFileService.write(this.userDataProfileService.currentProfile.keybindingsResource, this.getEmptyContent(EOL), { encoding: 'utf8' });
248+
return result.then(() => this.textModelResolverService.createModelReference(this.userDataProfileService.currentProfile.keybindingsResource));
252249
});
253250
}
254251

255252
private resolveAndValidate(): Promise<IReference<IResolvedTextEditorModel>> {
256253

257254
// Target cannot be dirty if not writing into buffer
258-
if (this.textFileService.isDirty(this.resource)) {
255+
if (this.textFileService.isDirty(this.userDataProfileService.currentProfile.keybindingsResource)) {
259256
return Promise.reject(new Error(localize('errorKeybindingsFileDirty', "Unable to write because the keybindings configuration file has unsaved changes. Please save it first and then try again.")));
260257
}
261258

0 commit comments

Comments
 (0)