Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { KeyChord, KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
7
import { Disposable, DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';
8
import { Schemas } from '../../../../base/common/network.js';
9
import { isBoolean, isObject, isString } from '../../../../base/common/types.js';
10
import { URI } from '../../../../base/common/uri.js';
11
import { ICodeEditor, isCodeEditor } from '../../../../editor/browser/editorBrowser.js';
12
import { EditorContributionInstantiation, registerEditorContribution } from '../../../../editor/browser/editorExtensions.js';
13
import { Context as SuggestContext } from '../../../../editor/contrib/suggest/browser/suggest.js';
14
import * as nls from '../../../../nls.js';
15
import { Categories } from '../../../../platform/action/common/actionCommonCategories.js';
16
import { Action2, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';
17
import { CommandsRegistry, ICommandService } from '../../../../platform/commands/common/commands.js';
18
import { ConfigurationTarget } from '../../../../platform/configuration/common/configuration.js';
19
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
20
import { InputFocusedContext, IsMacNativeContext } from '../../../../platform/contextkey/common/contextkeys.js';
21
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
22
import { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
23
import { KeybindingWeight, KeybindingsRegistry } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
24
import { ILabelService } from '../../../../platform/label/common/label.js';
25
import { IListService } from '../../../../platform/list/browser/listService.js';
26
import { Registry } from '../../../../platform/registry/common/platform.js';
27
import { IUserDataProfilesService } from '../../../../platform/userDataProfile/common/userDataProfile.js';
28
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';
29
import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from '../../../browser/actions/workspaceCommands.js';
30
import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';
31
import { resolveCommandsContext } from '../../../browser/parts/editor/editorCommandsContext.js';
32
import { RemoteNameContext, ResourceContextKey, WorkbenchStateContext } from '../../../common/contextkeys.js';
33
import { IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from '../../../common/contributions.js';
34
import { EditorExtensions, IEditorFactoryRegistry, IEditorSerializer } from '../../../common/editor.js';
35
import { EditorInput } from '../../../common/editor/editorInput.js';
36
import { IEditorGroup, IEditorGroupsService } from '../../../services/editor/common/editorGroupsService.js';
37
import { IEditorService } from '../../../services/editor/common/editorService.js';
38
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
39
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
40
import { KeybindingsEditorInput } from '../../../services/preferences/browser/keybindingsEditorInput.js';
41
import { DEFINE_KEYBINDING_EDITOR_CONTRIB_ID, IDefineKeybindingEditorContribution, IPreferencesService } from '../../../services/preferences/common/preferences.js';
42
import { PreferencesEditorInput, SettingsEditor2Input } from '../../../services/preferences/common/preferencesEditorInput.js';
43
import { SettingsEditorModel } from '../../../services/preferences/common/preferencesModels.js';
44
import { CURRENT_PROFILE_CONTEXT, IUserDataProfileService } from '../../../services/userDataProfile/common/userDataProfile.js';
45
import { ExplorerFolderContext, ExplorerRootContext } from '../../files/common/files.js';
46
import { CONTEXT_AI_SETTING_RESULTS_AVAILABLE, CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, CONTEXT_WHEN_FOCUS, KEYBINDINGS_EDITOR_COMMAND_ACCEPT_WHEN, KEYBINDINGS_EDITOR_COMMAND_ADD, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_HISTORY, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND_TITLE, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REJECT_WHEN, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_TOGGLE_AI_SEARCH } from '../common/preferences.js';
47
import { PreferencesContribution } from '../common/preferencesContribution.js';
48
import { KeybindingsEditor } from './keybindingsEditor.js';
49
import { ConfigureLanguageBasedSettingsAction } from './preferencesActions.js';
50
import { PreferencesEditor } from './preferencesEditor.js';
51
import { preferencesOpenSettingsIcon } from './preferencesIcons.js';
52
import { IPreferencesRenderer, UserSettingsRenderer, WorkspaceSettingsRenderer } from './preferencesRenderers.js';
53
import { SettingsEditor2, SettingsFocusContext } from './settingsEditor2.js';
54
55
const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search';
56
57
const SETTINGS_EDITOR_COMMAND_FOCUS_FILE = 'settings.action.focusSettingsFile';
58
const SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH = 'settings.action.focusSettingsFromSearch';
59
const SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST = 'settings.action.focusSettingsList';
60
const SETTINGS_EDITOR_COMMAND_FOCUS_TOC = 'settings.action.focusTOC';
61
const SETTINGS_EDITOR_COMMAND_FOCUS_CONTROL = 'settings.action.focusSettingControl';
62
const SETTINGS_EDITOR_COMMAND_FOCUS_UP = 'settings.action.focusLevelUp';
63
64
const SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON = 'settings.switchToJSON';
65
const SETTINGS_EDITOR_COMMAND_FILTER_ONLINE = 'settings.filterByOnline';
66
const SETTINGS_EDITOR_COMMAND_FILTER_UNTRUSTED = 'settings.filterUntrusted';
67
68
const SETTINGS_COMMAND_OPEN_SETTINGS = 'workbench.action.openSettings';
69
const SETTINGS_COMMAND_FILTER_TELEMETRY = 'settings.filterByTelemetry';
70
71
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
72
EditorPaneDescriptor.create(
73
SettingsEditor2,
74
SettingsEditor2.ID,
75
nls.localize('settingsEditor2', "Settings Editor 2")
76
),
77
[
78
new SyncDescriptor(SettingsEditor2Input)
79
]
80
);
81
82
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
83
EditorPaneDescriptor.create(
84
PreferencesEditor,
85
PreferencesEditor.ID,
86
nls.localize('preferencesEditor', "Preferences Editor")
87
),
88
[
89
new SyncDescriptor(PreferencesEditorInput)
90
]
91
);
92
93
class PreferencesEditorInputSerializer implements IEditorSerializer {
94
95
canSerialize(editorInput: EditorInput): boolean {
96
return true;
97
}
98
99
serialize(editorInput: EditorInput): string {
100
return '';
101
}
102
103
deserialize(instantiationService: IInstantiationService): EditorInput {
104
return instantiationService.createInstance(PreferencesEditorInput);
105
}
106
}
107
108
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
109
EditorPaneDescriptor.create(
110
KeybindingsEditor,
111
KeybindingsEditor.ID,
112
nls.localize('keybindingsEditor', "Keybindings Editor")
113
),
114
[
115
new SyncDescriptor(KeybindingsEditorInput)
116
]
117
);
118
119
class KeybindingsEditorInputSerializer implements IEditorSerializer {
120
121
canSerialize(editorInput: EditorInput): boolean {
122
return true;
123
}
124
125
serialize(editorInput: EditorInput): string {
126
return '';
127
}
128
129
deserialize(instantiationService: IInstantiationService): EditorInput {
130
return instantiationService.createInstance(KeybindingsEditorInput);
131
}
132
}
133
134
class SettingsEditor2InputSerializer implements IEditorSerializer {
135
136
canSerialize(editorInput: EditorInput): boolean {
137
return true;
138
}
139
140
serialize(input: SettingsEditor2Input): string {
141
return '';
142
}
143
144
deserialize(instantiationService: IInstantiationService): SettingsEditor2Input {
145
return instantiationService.createInstance(SettingsEditor2Input);
146
}
147
}
148
149
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(PreferencesEditorInput.ID, PreferencesEditorInputSerializer);
150
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(KeybindingsEditorInput.ID, KeybindingsEditorInputSerializer);
151
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(SettingsEditor2Input.ID, SettingsEditor2InputSerializer);
152
153
const OPEN_USER_SETTINGS_UI_TITLE = nls.localize2('openSettings2', "Open Settings (UI)");
154
const OPEN_USER_SETTINGS_JSON_TITLE = nls.localize2('openUserSettingsJson', "Open User Settings (JSON)");
155
const OPEN_APPLICATION_SETTINGS_JSON_TITLE = nls.localize2('openApplicationSettingsJson', "Open Application Settings (JSON)");
156
const category = Categories.Preferences;
157
158
interface IOpenSettingsActionOptions {
159
openToSide?: boolean;
160
query?: string;
161
revealSetting?: {
162
key: string;
163
edit?: boolean;
164
};
165
focusSearch?: boolean;
166
}
167
168
function sanitizeBoolean(arg: any): boolean | undefined {
169
return isBoolean(arg) ? arg : undefined;
170
}
171
172
function sanitizeString(arg: any): string | undefined {
173
return isString(arg) ? arg : undefined;
174
}
175
176
function sanitizeOpenSettingsArgs(args: any): IOpenSettingsActionOptions {
177
if (!isObject(args)) {
178
args = {};
179
}
180
181
let sanitizedObject: IOpenSettingsActionOptions = {
182
focusSearch: sanitizeBoolean(args?.focusSearch),
183
openToSide: sanitizeBoolean(args?.openToSide),
184
query: sanitizeString(args?.query)
185
};
186
187
if (isString(args?.revealSetting?.key)) {
188
sanitizedObject = {
189
...sanitizedObject,
190
revealSetting: {
191
key: args.revealSetting.key,
192
edit: sanitizeBoolean(args.revealSetting?.edit)
193
}
194
};
195
}
196
197
return sanitizedObject;
198
}
199
200
class PreferencesActionsContribution extends Disposable implements IWorkbenchContribution {
201
202
static readonly ID = 'workbench.contrib.preferencesActions';
203
204
constructor(
205
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
206
@IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService,
207
@IPreferencesService private readonly preferencesService: IPreferencesService,
208
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
209
@ILabelService private readonly labelService: ILabelService,
210
@IExtensionService private readonly extensionService: IExtensionService,
211
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
212
) {
213
super();
214
215
this.registerSettingsActions();
216
this.registerKeybindingsActions();
217
218
this.updatePreferencesEditorMenuItem();
219
this._register(workspaceContextService.onDidChangeWorkbenchState(() => this.updatePreferencesEditorMenuItem()));
220
this._register(workspaceContextService.onDidChangeWorkspaceFolders(() => this.updatePreferencesEditorMenuItemForWorkspaceFolders()));
221
}
222
223
private registerSettingsActions() {
224
this._register(registerAction2(class extends Action2 {
225
constructor() {
226
super({
227
id: SETTINGS_COMMAND_OPEN_SETTINGS,
228
title: {
229
...nls.localize2('settings', "Settings"),
230
mnemonicTitle: nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&Settings"),
231
},
232
keybinding: {
233
weight: KeybindingWeight.WorkbenchContrib,
234
when: null,
235
primary: KeyMod.CtrlCmd | KeyCode.Comma,
236
},
237
menu: [{
238
id: MenuId.GlobalActivity,
239
group: '2_configuration',
240
order: 2
241
}, {
242
id: MenuId.MenubarPreferencesMenu,
243
group: '2_configuration',
244
order: 2
245
}],
246
});
247
}
248
run(accessor: ServicesAccessor, args: string | IOpenSettingsActionOptions) {
249
// args takes a string for backcompat
250
const opts = typeof args === 'string' ? { query: args } : sanitizeOpenSettingsArgs(args);
251
return accessor.get(IPreferencesService).openSettings(opts);
252
}
253
}));
254
this._register(registerAction2(class extends Action2 {
255
constructor() {
256
super({
257
id: 'workbench.action.openSettings2',
258
title: nls.localize2('openSettings2', "Open Settings (UI)"),
259
category,
260
f1: true,
261
});
262
}
263
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
264
args = sanitizeOpenSettingsArgs(args);
265
return accessor.get(IPreferencesService).openSettings({ jsonEditor: false, ...args });
266
}
267
}));
268
269
this._register(registerAction2(class extends Action2 {
270
constructor() {
271
super({
272
id: 'workbench.action.openSettingsJson',
273
title: OPEN_USER_SETTINGS_JSON_TITLE,
274
metadata: {
275
description: nls.localize2('workbench.action.openSettingsJson.description', "Opens the JSON file containing the current user profile settings")
276
},
277
category,
278
f1: true,
279
});
280
}
281
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
282
args = sanitizeOpenSettingsArgs(args);
283
return accessor.get(IPreferencesService).openSettings({ jsonEditor: true, ...args });
284
}
285
}));
286
287
const that = this;
288
this._register(registerAction2(class extends Action2 {
289
constructor() {
290
super({
291
id: 'workbench.action.openApplicationSettingsJson',
292
title: OPEN_APPLICATION_SETTINGS_JSON_TITLE,
293
category,
294
menu: {
295
id: MenuId.CommandPalette,
296
when: ContextKeyExpr.notEquals(CURRENT_PROFILE_CONTEXT.key, that.userDataProfilesService.defaultProfile.id)
297
}
298
});
299
}
300
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
301
args = sanitizeOpenSettingsArgs(args);
302
return accessor.get(IPreferencesService).openApplicationSettings({ jsonEditor: true, ...args });
303
}
304
}));
305
306
// Opens the User tab of the Settings editor
307
this._register(registerAction2(class extends Action2 {
308
constructor() {
309
super({
310
id: 'workbench.action.openGlobalSettings',
311
title: nls.localize2('openGlobalSettings', "Open User Settings"),
312
category,
313
f1: true,
314
});
315
}
316
run(accessor: ServicesAccessor, args: IOpenSettingsActionOptions) {
317
args = sanitizeOpenSettingsArgs(args);
318
return accessor.get(IPreferencesService).openUserSettings(args);
319
}
320
}));
321
this._register(registerAction2(class extends Action2 {
322
constructor() {
323
super({
324
id: 'workbench.action.openRawDefaultSettings',
325
title: nls.localize2('openRawDefaultSettings', "Open Default Settings (JSON)"),
326
category,
327
f1: true,
328
});
329
}
330
run(accessor: ServicesAccessor) {
331
return accessor.get(IPreferencesService).openRawDefaultSettings();
332
}
333
}));
334
335
this._register(registerAction2(class extends Action2 {
336
constructor() {
337
super({
338
id: ConfigureLanguageBasedSettingsAction.ID,
339
title: ConfigureLanguageBasedSettingsAction.LABEL,
340
category,
341
f1: true,
342
});
343
}
344
run(accessor: ServicesAccessor) {
345
return accessor.get(IInstantiationService).createInstance(ConfigureLanguageBasedSettingsAction, ConfigureLanguageBasedSettingsAction.ID, ConfigureLanguageBasedSettingsAction.LABEL.value).run();
346
}
347
}));
348
this._register(registerAction2(class extends Action2 {
349
constructor() {
350
super({
351
id: 'workbench.action.openWorkspaceSettings',
352
title: nls.localize2('openWorkspaceSettings', "Open Workspace Settings"),
353
category,
354
menu: {
355
id: MenuId.CommandPalette,
356
when: WorkbenchStateContext.notEqualsTo('empty')
357
}
358
});
359
}
360
run(accessor: ServicesAccessor, args?: string | IOpenSettingsActionOptions) {
361
// Match the behaviour of workbench.action.openSettings
362
args = typeof args === 'string' ? { query: args } : sanitizeOpenSettingsArgs(args);
363
return accessor.get(IPreferencesService).openWorkspaceSettings(args);
364
}
365
}));
366
367
this._register(registerAction2(class extends Action2 {
368
constructor() {
369
super({
370
id: 'workbench.action.openAccessibilitySettings',
371
title: nls.localize2('openAccessibilitySettings', "Open Accessibility Settings"),
372
category,
373
menu: {
374
id: MenuId.CommandPalette,
375
when: WorkbenchStateContext.notEqualsTo('empty')
376
}
377
});
378
}
379
async run(accessor: ServicesAccessor) {
380
await accessor.get(IPreferencesService).openSettings({ jsonEditor: false, query: '@tag:accessibility' });
381
}
382
}));
383
this._register(registerAction2(class extends Action2 {
384
constructor() {
385
super({
386
id: 'workbench.action.openWorkspaceSettingsFile',
387
title: nls.localize2('openWorkspaceSettingsFile', "Open Workspace Settings (JSON)"),
388
category,
389
menu: {
390
id: MenuId.CommandPalette,
391
when: WorkbenchStateContext.notEqualsTo('empty')
392
}
393
});
394
}
395
run(accessor: ServicesAccessor, args?: IOpenSettingsActionOptions) {
396
args = sanitizeOpenSettingsArgs(args);
397
return accessor.get(IPreferencesService).openWorkspaceSettings({ jsonEditor: true, ...args });
398
}
399
}));
400
this._register(registerAction2(class extends Action2 {
401
constructor() {
402
super({
403
id: 'workbench.action.openFolderSettings',
404
title: nls.localize2('openFolderSettings', "Open Folder Settings"),
405
category,
406
menu: {
407
id: MenuId.CommandPalette,
408
when: WorkbenchStateContext.isEqualTo('workspace')
409
}
410
});
411
}
412
async run(accessor: ServicesAccessor, args?: IOpenSettingsActionOptions) {
413
const commandService = accessor.get(ICommandService);
414
const preferencesService = accessor.get(IPreferencesService);
415
const workspaceFolder = await commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND_ID);
416
if (workspaceFolder) {
417
args = sanitizeOpenSettingsArgs(args);
418
await preferencesService.openFolderSettings({ folderUri: workspaceFolder.uri, ...args });
419
}
420
}
421
}));
422
this._register(registerAction2(class extends Action2 {
423
constructor() {
424
super({
425
id: 'workbench.action.openFolderSettingsFile',
426
title: nls.localize2('openFolderSettingsFile', "Open Folder Settings (JSON)"),
427
category,
428
menu: {
429
id: MenuId.CommandPalette,
430
when: WorkbenchStateContext.isEqualTo('workspace')
431
}
432
});
433
}
434
async run(accessor: ServicesAccessor, args?: IOpenSettingsActionOptions) {
435
const commandService = accessor.get(ICommandService);
436
const preferencesService = accessor.get(IPreferencesService);
437
const workspaceFolder = await commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND_ID);
438
if (workspaceFolder) {
439
args = sanitizeOpenSettingsArgs(args);
440
await preferencesService.openFolderSettings({ folderUri: workspaceFolder.uri, jsonEditor: true, ...args });
441
}
442
}
443
}));
444
this._register(registerAction2(class extends Action2 {
445
constructor() {
446
super({
447
id: '_workbench.action.openFolderSettings',
448
title: nls.localize('openFolderSettings', "Open Folder Settings"),
449
category,
450
menu: {
451
id: MenuId.ExplorerContext,
452
group: '2_workspace',
453
order: 20,
454
when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext)
455
}
456
});
457
}
458
async run(accessor: ServicesAccessor, resource?: URI) {
459
if (URI.isUri(resource)) {
460
await accessor.get(IPreferencesService).openFolderSettings({ folderUri: resource });
461
} else {
462
const commandService = accessor.get(ICommandService);
463
const preferencesService = accessor.get(IPreferencesService);
464
const workspaceFolder = await commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND_ID);
465
if (workspaceFolder) {
466
await preferencesService.openFolderSettings({ folderUri: workspaceFolder.uri });
467
}
468
}
469
}
470
}));
471
this._register(registerAction2(class extends Action2 {
472
constructor() {
473
super({
474
id: SETTINGS_EDITOR_COMMAND_FILTER_ONLINE,
475
title: nls.localize({ key: 'miOpenOnlineSettings', comment: ['&& denotes a mnemonic'] }, "&&Online Services Settings"),
476
menu: {
477
id: MenuId.MenubarPreferencesMenu,
478
group: '3_settings',
479
order: 1,
480
}
481
});
482
}
483
run(accessor: ServicesAccessor) {
484
const editorPane = accessor.get(IEditorService).activeEditorPane;
485
if (editorPane instanceof SettingsEditor2) {
486
editorPane.focusSearch(`@tag:usesOnlineServices`);
487
} else {
488
accessor.get(IPreferencesService).openSettings({ jsonEditor: false, query: '@tag:usesOnlineServices' });
489
}
490
}
491
}));
492
this._register(registerAction2(class extends Action2 {
493
constructor() {
494
super({
495
id: SETTINGS_EDITOR_COMMAND_TOGGLE_AI_SEARCH,
496
precondition: CONTEXT_SETTINGS_EDITOR,
497
keybinding: {
498
primary: KeyMod.CtrlCmd | KeyCode.KeyI,
499
weight: KeybindingWeight.EditorContrib,
500
when: CONTEXT_AI_SETTING_RESULTS_AVAILABLE
501
},
502
category,
503
f1: true,
504
title: nls.localize2('settings.toggleAiSearch', "Toggle AI Settings Search")
505
});
506
}
507
run(accessor: ServicesAccessor) {
508
const editorPane = accessor.get(IEditorService).activeEditorPane;
509
if (editorPane instanceof SettingsEditor2) {
510
editorPane.toggleAiSearch();
511
}
512
}
513
}));
514
this._register(registerAction2(class extends Action2 {
515
constructor() {
516
super({
517
id: SETTINGS_EDITOR_COMMAND_FILTER_UNTRUSTED,
518
title: nls.localize2('filterUntrusted', "Show untrusted workspace settings"),
519
});
520
}
521
run(accessor: ServicesAccessor) {
522
accessor.get(IPreferencesService).openWorkspaceSettings({ jsonEditor: false, query: `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}` });
523
}
524
}));
525
526
this._register(registerAction2(class extends Action2 {
527
constructor() {
528
super({
529
id: SETTINGS_COMMAND_FILTER_TELEMETRY,
530
title: nls.localize({ key: 'miOpenTelemetrySettings', comment: ['&& denotes a mnemonic'] }, "&&Telemetry Settings")
531
});
532
}
533
run(accessor: ServicesAccessor) {
534
const editorPane = accessor.get(IEditorService).activeEditorPane;
535
if (editorPane instanceof SettingsEditor2) {
536
editorPane.focusSearch(`@tag:telemetry`);
537
} else {
538
accessor.get(IPreferencesService).openSettings({ jsonEditor: false, query: '@tag:telemetry' });
539
}
540
}
541
}));
542
543
this.registerSettingsEditorActions();
544
545
this.extensionService.whenInstalledExtensionsRegistered()
546
.then(() => {
547
const remoteAuthority = this.environmentService.remoteAuthority;
548
const hostLabel = this.labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority) || remoteAuthority;
549
this._register(registerAction2(class extends Action2 {
550
constructor() {
551
super({
552
id: 'workbench.action.openRemoteSettings',
553
title: nls.localize2('openRemoteSettings', "Open Remote Settings ({0})", hostLabel),
554
category,
555
menu: {
556
id: MenuId.CommandPalette,
557
when: RemoteNameContext.notEqualsTo('')
558
}
559
});
560
}
561
run(accessor: ServicesAccessor, args?: IOpenSettingsActionOptions) {
562
args = sanitizeOpenSettingsArgs(args);
563
return accessor.get(IPreferencesService).openRemoteSettings(args);
564
}
565
}));
566
this._register(registerAction2(class extends Action2 {
567
constructor() {
568
super({
569
id: 'workbench.action.openRemoteSettingsFile',
570
title: nls.localize2('openRemoteSettingsJSON', "Open Remote Settings (JSON) ({0})", hostLabel),
571
category,
572
menu: {
573
id: MenuId.CommandPalette,
574
when: RemoteNameContext.notEqualsTo('')
575
}
576
});
577
}
578
run(accessor: ServicesAccessor, args?: IOpenSettingsActionOptions) {
579
args = sanitizeOpenSettingsArgs(args);
580
return accessor.get(IPreferencesService).openRemoteSettings({ jsonEditor: true, ...args });
581
}
582
}));
583
});
584
}
585
586
private registerSettingsEditorActions() {
587
function getPreferencesEditor(accessor: ServicesAccessor): SettingsEditor2 | null {
588
const activeEditorPane = accessor.get(IEditorService).activeEditorPane;
589
if (activeEditorPane instanceof SettingsEditor2) {
590
return activeEditorPane;
591
}
592
return null;
593
}
594
595
function settingsEditorFocusSearch(accessor: ServicesAccessor) {
596
const preferencesEditor = getPreferencesEditor(accessor);
597
preferencesEditor?.focusSearch();
598
}
599
600
this._register(registerAction2(class extends Action2 {
601
constructor() {
602
super({
603
id: SETTINGS_EDITOR_COMMAND_SEARCH,
604
precondition: CONTEXT_SETTINGS_EDITOR,
605
keybinding: {
606
primary: KeyMod.CtrlCmd | KeyCode.KeyF,
607
weight: KeybindingWeight.EditorContrib,
608
when: null
609
},
610
category,
611
f1: true,
612
title: nls.localize2('settings.focusSearch', "Focus Settings Search")
613
});
614
}
615
616
run(accessor: ServicesAccessor) { settingsEditorFocusSearch(accessor); }
617
}));
618
619
this._register(registerAction2(class extends Action2 {
620
constructor() {
621
super({
622
id: SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS,
623
precondition: CONTEXT_SETTINGS_EDITOR,
624
keybinding: {
625
primary: KeyCode.Escape,
626
weight: KeybindingWeight.EditorContrib,
627
when: CONTEXT_SETTINGS_SEARCH_FOCUS
628
},
629
category,
630
f1: true,
631
title: nls.localize2('settings.clearResults', "Clear Settings Search Results")
632
});
633
}
634
635
run(accessor: ServicesAccessor) {
636
const preferencesEditor = getPreferencesEditor(accessor);
637
preferencesEditor?.clearSearchResults();
638
}
639
}));
640
641
this._register(registerAction2(class extends Action2 {
642
constructor() {
643
super({
644
id: SETTINGS_EDITOR_COMMAND_FOCUS_FILE,
645
precondition: ContextKeyExpr.and(CONTEXT_SETTINGS_SEARCH_FOCUS, SuggestContext.Visible.toNegated()),
646
keybinding: {
647
primary: KeyCode.DownArrow,
648
weight: KeybindingWeight.EditorContrib,
649
when: null
650
},
651
title: nls.localize('settings.focusFile', "Focus settings file")
652
});
653
}
654
655
run(accessor: ServicesAccessor, args: any): void {
656
const preferencesEditor = getPreferencesEditor(accessor);
657
preferencesEditor?.focusSettings();
658
}
659
}));
660
661
this._register(registerAction2(class extends Action2 {
662
constructor() {
663
super({
664
id: SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH,
665
precondition: ContextKeyExpr.and(CONTEXT_SETTINGS_SEARCH_FOCUS, SuggestContext.Visible.toNegated()),
666
keybinding: {
667
primary: KeyCode.DownArrow,
668
weight: KeybindingWeight.WorkbenchContrib,
669
when: null
670
},
671
title: nls.localize('settings.focusFile', "Focus settings file")
672
});
673
}
674
675
run(accessor: ServicesAccessor, args: any): void {
676
const preferencesEditor = getPreferencesEditor(accessor);
677
preferencesEditor?.focusSettings();
678
}
679
}));
680
681
this._register(registerAction2(class extends Action2 {
682
constructor() {
683
super({
684
id: SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST,
685
precondition: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_TOC_ROW_FOCUS),
686
keybinding: {
687
primary: KeyCode.Enter,
688
weight: KeybindingWeight.WorkbenchContrib,
689
when: null
690
},
691
title: nls.localize('settings.focusSettingsList', "Focus settings list")
692
});
693
}
694
695
run(accessor: ServicesAccessor): void {
696
const preferencesEditor = getPreferencesEditor(accessor);
697
if (preferencesEditor instanceof SettingsEditor2) {
698
preferencesEditor.focusSettings();
699
}
700
}
701
}));
702
703
this._register(registerAction2(class extends Action2 {
704
constructor() {
705
super({
706
id: SETTINGS_EDITOR_COMMAND_FOCUS_TOC,
707
precondition: CONTEXT_SETTINGS_EDITOR,
708
f1: true,
709
keybinding: [
710
{
711
primary: KeyCode.LeftArrow,
712
weight: KeybindingWeight.WorkbenchContrib,
713
when: CONTEXT_SETTINGS_ROW_FOCUS
714
}],
715
category,
716
title: nls.localize2('settings.focusSettingsTOC', "Focus Settings Table of Contents")
717
});
718
}
719
720
run(accessor: ServicesAccessor): void {
721
const preferencesEditor = getPreferencesEditor(accessor);
722
if (!(preferencesEditor instanceof SettingsEditor2)) {
723
return;
724
}
725
726
preferencesEditor.focusTOC();
727
}
728
}));
729
730
this._register(registerAction2(class extends Action2 {
731
constructor() {
732
super({
733
id: SETTINGS_EDITOR_COMMAND_FOCUS_CONTROL,
734
precondition: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS),
735
keybinding: {
736
primary: KeyCode.Enter,
737
weight: KeybindingWeight.WorkbenchContrib,
738
},
739
title: nls.localize('settings.focusSettingControl', "Focus Setting Control")
740
});
741
}
742
743
run(accessor: ServicesAccessor): void {
744
const preferencesEditor = getPreferencesEditor(accessor);
745
if (!(preferencesEditor instanceof SettingsEditor2)) {
746
return;
747
}
748
749
const activeElement = preferencesEditor.getContainer()?.ownerDocument.activeElement;
750
if (activeElement?.classList.contains('monaco-list')) {
751
preferencesEditor.focusSettings(true);
752
}
753
}
754
}));
755
756
this._register(registerAction2(class extends Action2 {
757
constructor() {
758
super({
759
id: SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU,
760
precondition: CONTEXT_SETTINGS_EDITOR,
761
keybinding: {
762
primary: KeyMod.Shift | KeyCode.F9,
763
weight: KeybindingWeight.WorkbenchContrib,
764
when: null
765
},
766
f1: true,
767
category,
768
title: nls.localize2('settings.showContextMenu', "Show Setting Context Menu")
769
});
770
}
771
772
run(accessor: ServicesAccessor): void {
773
const preferencesEditor = getPreferencesEditor(accessor);
774
if (preferencesEditor instanceof SettingsEditor2) {
775
preferencesEditor.showContextMenu();
776
}
777
}
778
}));
779
780
this._register(registerAction2(class extends Action2 {
781
constructor() {
782
super({
783
id: SETTINGS_EDITOR_COMMAND_FOCUS_UP,
784
precondition: ContextKeyExpr.and(CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS.toNegated(), CONTEXT_SETTINGS_JSON_EDITOR.toNegated()),
785
keybinding: {
786
primary: KeyCode.Escape,
787
weight: KeybindingWeight.WorkbenchContrib,
788
when: null
789
},
790
f1: true,
791
category,
792
title: nls.localize2('settings.focusLevelUp', "Move Focus Up One Level")
793
});
794
}
795
796
run(accessor: ServicesAccessor): void {
797
const preferencesEditor = getPreferencesEditor(accessor);
798
if (!(preferencesEditor instanceof SettingsEditor2)) {
799
return;
800
}
801
802
if (preferencesEditor.currentFocusContext === SettingsFocusContext.SettingControl) {
803
preferencesEditor.focusSettings();
804
} else if (preferencesEditor.currentFocusContext === SettingsFocusContext.SettingTree) {
805
preferencesEditor.focusTOC();
806
} else if (preferencesEditor.currentFocusContext === SettingsFocusContext.TableOfContents) {
807
preferencesEditor.focusSearch();
808
}
809
}
810
}));
811
}
812
813
private registerKeybindingsActions() {
814
const that = this;
815
const category = nls.localize2('preferences', "Preferences");
816
const id = 'workbench.action.openGlobalKeybindings';
817
this._register(registerAction2(class extends Action2 {
818
constructor() {
819
super({
820
id,
821
title: nls.localize2('openGlobalKeybindings', "Open Keyboard Shortcuts"),
822
shortTitle: nls.localize('keyboardShortcuts', "Keyboard Shortcuts"),
823
category,
824
icon: preferencesOpenSettingsIcon,
825
keybinding: {
826
when: null,
827
weight: KeybindingWeight.WorkbenchContrib,
828
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyS)
829
},
830
menu: [
831
{ id: MenuId.CommandPalette },
832
{
833
id: MenuId.EditorTitle,
834
when: ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.keybindingsResource.toString()),
835
group: 'navigation',
836
order: 1,
837
},
838
{
839
id: MenuId.GlobalActivity,
840
group: '2_configuration',
841
order: 4
842
}
843
]
844
});
845
}
846
run(accessor: ServicesAccessor, ...args: unknown[]) {
847
const query = typeof args[0] === 'string' ? args[0] : undefined;
848
const groupId = getEditorGroupFromArguments(accessor, args)?.id;
849
return accessor.get(IPreferencesService).openGlobalKeybindingSettings(false, { query, groupId });
850
}
851
}));
852
this._register(MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
853
command: {
854
id,
855
title: nls.localize('keyboardShortcuts', "Keyboard Shortcuts"),
856
},
857
group: '2_configuration',
858
order: 4
859
}));
860
this._register(registerAction2(class extends Action2 {
861
constructor() {
862
super({
863
id: 'workbench.action.openDefaultKeybindingsFile',
864
title: nls.localize2('openDefaultKeybindingsFile', "Open Default Keyboard Shortcuts (JSON)"),
865
category,
866
menu: { id: MenuId.CommandPalette }
867
});
868
}
869
run(accessor: ServicesAccessor) {
870
return accessor.get(IPreferencesService).openDefaultKeybindingsFile();
871
}
872
}));
873
this._register(registerAction2(class extends Action2 {
874
constructor() {
875
super({
876
id: 'workbench.action.openGlobalKeybindingsFile',
877
title: nls.localize2('openGlobalKeybindingsFile', "Open Keyboard Shortcuts (JSON)"),
878
category,
879
icon: preferencesOpenSettingsIcon,
880
menu: [
881
{ id: MenuId.CommandPalette },
882
{
883
id: MenuId.EditorTitle,
884
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
885
group: 'navigation',
886
}
887
]
888
});
889
}
890
run(accessor: ServicesAccessor, ...args: unknown[]) {
891
const groupId = getEditorGroupFromArguments(accessor, args)?.id;
892
return accessor.get(IPreferencesService).openGlobalKeybindingSettings(true, { groupId });
893
}
894
}));
895
this._register(registerAction2(class extends Action2 {
896
constructor() {
897
super({
898
id: KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS,
899
title: nls.localize2('showDefaultKeybindings', "Show System Keybindings"),
900
menu: [
901
{
902
id: MenuId.EditorTitle,
903
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
904
group: '1_keyboard_preferences_actions'
905
}
906
]
907
});
908
}
909
run(accessor: ServicesAccessor, ...args: unknown[]) {
910
const group = getEditorGroupFromArguments(accessor, args);
911
const editorPane = group?.activeEditorPane;
912
if (editorPane instanceof KeybindingsEditor) {
913
editorPane.search('@source:system');
914
}
915
}
916
}));
917
this._register(registerAction2(class extends Action2 {
918
constructor() {
919
super({
920
id: KEYBINDINGS_EDITOR_SHOW_EXTENSION_KEYBINDINGS,
921
title: nls.localize2('showExtensionKeybindings', "Show Extension Keybindings"),
922
menu: [
923
{
924
id: MenuId.EditorTitle,
925
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
926
group: '1_keyboard_preferences_actions'
927
}
928
]
929
});
930
}
931
run(accessor: ServicesAccessor, ...args: unknown[]) {
932
const group = getEditorGroupFromArguments(accessor, args);
933
const editorPane = group?.activeEditorPane;
934
if (editorPane instanceof KeybindingsEditor) {
935
editorPane.search('@source:extension');
936
}
937
}
938
}));
939
this._register(registerAction2(class extends Action2 {
940
constructor() {
941
super({
942
id: KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS,
943
title: nls.localize2('showUserKeybindings', "Show User Keybindings"),
944
menu: [
945
{
946
id: MenuId.EditorTitle,
947
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
948
group: '1_keyboard_preferences_actions'
949
}
950
]
951
});
952
}
953
run(accessor: ServicesAccessor, ...args: unknown[]) {
954
const group = getEditorGroupFromArguments(accessor, args);
955
const editorPane = group?.activeEditorPane;
956
if (editorPane instanceof KeybindingsEditor) {
957
editorPane.search('@source:user');
958
}
959
}
960
}));
961
this._register(registerAction2(class extends Action2 {
962
constructor() {
963
super({
964
id: KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS,
965
title: nls.localize('clear', "Clear Search Results"),
966
keybinding: {
967
weight: KeybindingWeight.WorkbenchContrib,
968
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS),
969
primary: KeyCode.Escape,
970
}
971
});
972
}
973
run(accessor: ServicesAccessor) {
974
const editorPane = accessor.get(IEditorService).activeEditorPane;
975
if (editorPane instanceof KeybindingsEditor) {
976
editorPane.clearSearchResults();
977
}
978
}
979
}));
980
981
this._register(registerAction2(class extends Action2 {
982
constructor() {
983
super({
984
id: KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_HISTORY,
985
title: nls.localize('clearHistory', "Clear Keyboard Shortcuts Search History"),
986
category,
987
menu: [
988
{
989
id: MenuId.CommandPalette,
990
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
991
}
992
]
993
});
994
}
995
run(accessor: ServicesAccessor) {
996
const editorPane = accessor.get(IEditorService).activeEditorPane;
997
if (editorPane instanceof KeybindingsEditor) {
998
editorPane.clearKeyboardShortcutSearchHistory();
999
}
1000
}
1001
}));
1002
1003
this.registerKeybindingEditorActions();
1004
}
1005
1006
private registerKeybindingEditorActions(): void {
1007
const that = this;
1008
1009
KeybindingsRegistry.registerCommandAndKeybindingRule({
1010
id: KEYBINDINGS_EDITOR_COMMAND_DEFINE,
1011
weight: KeybindingWeight.WorkbenchContrib,
1012
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS, CONTEXT_WHEN_FOCUS.toNegated()),
1013
primary: KeyCode.Enter,
1014
handler: (accessor, args: any) => {
1015
const editorPane = accessor.get(IEditorService).activeEditorPane;
1016
if (editorPane instanceof KeybindingsEditor) {
1017
editorPane.defineKeybinding(editorPane.activeKeybindingEntry!, false);
1018
}
1019
}
1020
});
1021
1022
KeybindingsRegistry.registerCommandAndKeybindingRule({
1023
id: KEYBINDINGS_EDITOR_COMMAND_ADD,
1024
weight: KeybindingWeight.WorkbenchContrib,
1025
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1026
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyA),
1027
handler: (accessor, args: any) => {
1028
const editorPane = accessor.get(IEditorService).activeEditorPane;
1029
if (editorPane instanceof KeybindingsEditor) {
1030
editorPane.defineKeybinding(editorPane.activeKeybindingEntry!, true);
1031
}
1032
}
1033
});
1034
1035
KeybindingsRegistry.registerCommandAndKeybindingRule({
1036
id: KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN,
1037
weight: KeybindingWeight.WorkbenchContrib,
1038
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1039
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyE),
1040
handler: (accessor, args: any) => {
1041
const editorPane = accessor.get(IEditorService).activeEditorPane;
1042
if (editorPane instanceof KeybindingsEditor && editorPane.activeKeybindingEntry!.keybindingItem.keybinding) {
1043
editorPane.defineWhenExpression(editorPane.activeKeybindingEntry!);
1044
}
1045
}
1046
});
1047
1048
KeybindingsRegistry.registerCommandAndKeybindingRule({
1049
id: KEYBINDINGS_EDITOR_COMMAND_REMOVE,
1050
weight: KeybindingWeight.WorkbenchContrib,
1051
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS, InputFocusedContext.toNegated()),
1052
primary: KeyCode.Delete,
1053
mac: {
1054
primary: KeyMod.CtrlCmd | KeyCode.Backspace
1055
},
1056
handler: (accessor, args: any) => {
1057
const editorPane = accessor.get(IEditorService).activeEditorPane;
1058
if (editorPane instanceof KeybindingsEditor) {
1059
editorPane.removeKeybinding(editorPane.activeKeybindingEntry!);
1060
}
1061
}
1062
});
1063
1064
KeybindingsRegistry.registerCommandAndKeybindingRule({
1065
id: KEYBINDINGS_EDITOR_COMMAND_RESET,
1066
weight: KeybindingWeight.WorkbenchContrib,
1067
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1068
primary: 0,
1069
handler: (accessor, args: any) => {
1070
const editorPane = accessor.get(IEditorService).activeEditorPane;
1071
if (editorPane instanceof KeybindingsEditor) {
1072
editorPane.resetKeybinding(editorPane.activeKeybindingEntry!);
1073
}
1074
}
1075
});
1076
1077
KeybindingsRegistry.registerCommandAndKeybindingRule({
1078
id: KEYBINDINGS_EDITOR_COMMAND_SEARCH,
1079
weight: KeybindingWeight.WorkbenchContrib,
1080
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
1081
primary: KeyMod.CtrlCmd | KeyCode.KeyF,
1082
handler: (accessor, args: any) => {
1083
const editorPane = accessor.get(IEditorService).activeEditorPane;
1084
if (editorPane instanceof KeybindingsEditor) {
1085
editorPane.focusSearch();
1086
}
1087
}
1088
});
1089
1090
KeybindingsRegistry.registerCommandAndKeybindingRule({
1091
id: KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS,
1092
weight: KeybindingWeight.WorkbenchContrib,
1093
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS),
1094
primary: KeyMod.Alt | KeyCode.KeyK,
1095
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyK },
1096
handler: (accessor, args: any) => {
1097
const editorPane = accessor.get(IEditorService).activeEditorPane;
1098
if (editorPane instanceof KeybindingsEditor) {
1099
editorPane.recordSearchKeys();
1100
}
1101
}
1102
});
1103
1104
KeybindingsRegistry.registerCommandAndKeybindingRule({
1105
id: KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE,
1106
weight: KeybindingWeight.WorkbenchContrib,
1107
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR),
1108
primary: KeyMod.Alt | KeyCode.KeyP,
1109
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyP },
1110
handler: (accessor, args: any) => {
1111
const editorPane = accessor.get(IEditorService).activeEditorPane;
1112
if (editorPane instanceof KeybindingsEditor) {
1113
editorPane.toggleSortByPrecedence();
1114
}
1115
}
1116
});
1117
1118
KeybindingsRegistry.registerCommandAndKeybindingRule({
1119
id: KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR,
1120
weight: KeybindingWeight.WorkbenchContrib,
1121
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1122
primary: 0,
1123
handler: (accessor, args: any) => {
1124
const editorPane = accessor.get(IEditorService).activeEditorPane;
1125
if (editorPane instanceof KeybindingsEditor) {
1126
editorPane.showSimilarKeybindings(editorPane.activeKeybindingEntry!);
1127
}
1128
}
1129
});
1130
1131
KeybindingsRegistry.registerCommandAndKeybindingRule({
1132
id: KEYBINDINGS_EDITOR_COMMAND_COPY,
1133
weight: KeybindingWeight.WorkbenchContrib,
1134
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS, CONTEXT_WHEN_FOCUS.negate()),
1135
primary: KeyMod.CtrlCmd | KeyCode.KeyC,
1136
handler: async (accessor, args: any) => {
1137
const editorPane = accessor.get(IEditorService).activeEditorPane;
1138
if (editorPane instanceof KeybindingsEditor) {
1139
await editorPane.copyKeybinding(editorPane.activeKeybindingEntry!);
1140
}
1141
}
1142
});
1143
1144
KeybindingsRegistry.registerCommandAndKeybindingRule({
1145
id: KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND,
1146
weight: KeybindingWeight.WorkbenchContrib,
1147
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1148
primary: 0,
1149
handler: async (accessor, args: any) => {
1150
const editorPane = accessor.get(IEditorService).activeEditorPane;
1151
if (editorPane instanceof KeybindingsEditor) {
1152
await editorPane.copyKeybindingCommand(editorPane.activeKeybindingEntry!);
1153
}
1154
}
1155
});
1156
1157
KeybindingsRegistry.registerCommandAndKeybindingRule({
1158
id: KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND_TITLE,
1159
weight: KeybindingWeight.WorkbenchContrib,
1160
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDING_FOCUS),
1161
primary: 0,
1162
handler: async (accessor, args: any) => {
1163
const editorPane = accessor.get(IEditorService).activeEditorPane;
1164
if (editorPane instanceof KeybindingsEditor) {
1165
await editorPane.copyKeybindingCommandTitle(editorPane.activeKeybindingEntry!);
1166
}
1167
}
1168
});
1169
1170
KeybindingsRegistry.registerCommandAndKeybindingRule({
1171
id: KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS,
1172
weight: KeybindingWeight.WorkbenchContrib,
1173
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS),
1174
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
1175
handler: (accessor, args: any) => {
1176
const editorPane = accessor.get(IEditorService).activeEditorPane;
1177
if (editorPane instanceof KeybindingsEditor) {
1178
editorPane.focusKeybindings();
1179
}
1180
}
1181
});
1182
1183
KeybindingsRegistry.registerCommandAndKeybindingRule({
1184
id: KEYBINDINGS_EDITOR_COMMAND_REJECT_WHEN,
1185
weight: KeybindingWeight.WorkbenchContrib,
1186
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_WHEN_FOCUS, SuggestContext.Visible.toNegated()),
1187
primary: KeyCode.Escape,
1188
handler: async (accessor, args: any) => {
1189
const editorPane = accessor.get(IEditorService).activeEditorPane;
1190
if (editorPane instanceof KeybindingsEditor) {
1191
editorPane.rejectWhenExpression(editorPane.activeKeybindingEntry!);
1192
}
1193
}
1194
});
1195
1196
KeybindingsRegistry.registerCommandAndKeybindingRule({
1197
id: KEYBINDINGS_EDITOR_COMMAND_ACCEPT_WHEN,
1198
weight: KeybindingWeight.WorkbenchContrib,
1199
when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_WHEN_FOCUS, SuggestContext.Visible.toNegated()),
1200
primary: KeyCode.Enter,
1201
handler: async (accessor, args: any) => {
1202
const editorPane = accessor.get(IEditorService).activeEditorPane;
1203
if (editorPane instanceof KeybindingsEditor) {
1204
editorPane.acceptWhenExpression(editorPane.activeKeybindingEntry!);
1205
}
1206
}
1207
});
1208
1209
const profileScopedActionDisposables = this._register(new DisposableStore());
1210
const registerProfileScopedActions = () => {
1211
profileScopedActionDisposables.clear();
1212
profileScopedActionDisposables.add(registerAction2(class DefineKeybindingAction extends Action2 {
1213
constructor() {
1214
const when = ResourceContextKey.Resource.isEqualTo(that.userDataProfileService.currentProfile.keybindingsResource.toString());
1215
super({
1216
id: 'editor.action.defineKeybinding',
1217
title: nls.localize2('defineKeybinding.start', "Define Keybinding"),
1218
f1: true,
1219
precondition: when,
1220
keybinding: {
1221
weight: KeybindingWeight.WorkbenchContrib,
1222
when,
1223
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyK)
1224
},
1225
menu: {
1226
id: MenuId.EditorContent,
1227
when,
1228
}
1229
});
1230
}
1231
1232
async run(accessor: ServicesAccessor): Promise<void> {
1233
const codeEditor = accessor.get(IEditorService).activeTextEditorControl;
1234
if (isCodeEditor(codeEditor)) {
1235
codeEditor.getContribution<IDefineKeybindingEditorContribution>(DEFINE_KEYBINDING_EDITOR_CONTRIB_ID)?.showDefineKeybindingWidget();
1236
}
1237
}
1238
}));
1239
};
1240
1241
registerProfileScopedActions();
1242
this._register(this.userDataProfileService.onDidChangeCurrentProfile(() => registerProfileScopedActions()));
1243
}
1244
1245
private updatePreferencesEditorMenuItem() {
1246
const commandId = '_workbench.openWorkspaceSettingsEditor';
1247
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && !CommandsRegistry.getCommand(commandId)) {
1248
CommandsRegistry.registerCommand(commandId, () => this.preferencesService.openWorkspaceSettings({ jsonEditor: false }));
1249
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
1250
command: {
1251
id: commandId,
1252
title: OPEN_USER_SETTINGS_UI_TITLE,
1253
icon: preferencesOpenSettingsIcon
1254
},
1255
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.workspaceSettingsResource!.toString()), WorkbenchStateContext.isEqualTo('workspace'), ContextKeyExpr.not('isInDiffEditor')),
1256
group: 'navigation',
1257
order: 1
1258
});
1259
}
1260
this.updatePreferencesEditorMenuItemForWorkspaceFolders();
1261
}
1262
1263
private updatePreferencesEditorMenuItemForWorkspaceFolders() {
1264
for (const folder of this.workspaceContextService.getWorkspace().folders) {
1265
const commandId = `_workbench.openFolderSettings.${folder.uri.toString()}`;
1266
if (!CommandsRegistry.getCommand(commandId)) {
1267
CommandsRegistry.registerCommand(commandId, (accessor: ServicesAccessor, ...args: any[]) => {
1268
const groupId = getEditorGroupFromArguments(accessor, args)?.id;
1269
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.FOLDER) {
1270
return this.preferencesService.openWorkspaceSettings({ jsonEditor: false, groupId });
1271
} else {
1272
return this.preferencesService.openFolderSettings({ folderUri: folder.uri, jsonEditor: false, groupId });
1273
}
1274
});
1275
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
1276
command: {
1277
id: commandId,
1278
title: OPEN_USER_SETTINGS_UI_TITLE,
1279
icon: preferencesOpenSettingsIcon
1280
},
1281
when: ContextKeyExpr.and(ResourceContextKey.Resource.isEqualTo(this.preferencesService.getFolderSettingsResource(folder.uri)!.toString()), ContextKeyExpr.not('isInDiffEditor')),
1282
group: 'navigation',
1283
order: 1
1284
});
1285
}
1286
}
1287
}
1288
}
1289
1290
class SettingsEditorTitleContribution extends Disposable implements IWorkbenchContribution {
1291
1292
static readonly ID = 'workbench.contrib.settingsEditorTitleBarActions';
1293
1294
constructor(
1295
@IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService,
1296
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
1297
) {
1298
super();
1299
this.registerSettingsEditorTitleActions();
1300
}
1301
1302
private registerSettingsEditorTitleActions() {
1303
const registerOpenUserSettingsEditorFromJsonActionDisposables = this._register(new MutableDisposable());
1304
const registerOpenUserSettingsEditorFromJsonAction = () => {
1305
const openUserSettingsEditorWhen = ContextKeyExpr.and(
1306
CONTEXT_SETTINGS_EDITOR.toNegated(),
1307
ContextKeyExpr.or(
1308
ResourceContextKey.Resource.isEqualTo(this.userDataProfileService.currentProfile.settingsResource.toString()),
1309
ResourceContextKey.Resource.isEqualTo(this.userDataProfilesService.defaultProfile.settingsResource.toString())),
1310
ContextKeyExpr.not('isInDiffEditor'));
1311
registerOpenUserSettingsEditorFromJsonActionDisposables.clear();
1312
registerOpenUserSettingsEditorFromJsonActionDisposables.value = registerAction2(class extends Action2 {
1313
constructor() {
1314
super({
1315
id: '_workbench.openUserSettingsEditor',
1316
title: OPEN_USER_SETTINGS_UI_TITLE,
1317
icon: preferencesOpenSettingsIcon,
1318
menu: [{
1319
id: MenuId.EditorTitle,
1320
when: openUserSettingsEditorWhen,
1321
group: 'navigation',
1322
order: 1
1323
}]
1324
});
1325
}
1326
run(accessor: ServicesAccessor, ...args: unknown[]) {
1327
const sanitizedArgs = sanitizeOpenSettingsArgs(args[0]);
1328
const groupId = getEditorGroupFromArguments(accessor, args)?.id;
1329
return accessor.get(IPreferencesService).openUserSettings({ jsonEditor: false, ...sanitizedArgs, groupId });
1330
}
1331
});
1332
};
1333
1334
registerOpenUserSettingsEditorFromJsonAction();
1335
this._register(this.userDataProfileService.onDidChangeCurrentProfile(() => {
1336
// Force the action to check the context again.
1337
registerOpenUserSettingsEditorFromJsonAction();
1338
}));
1339
1340
const openSettingsJsonWhen = ContextKeyExpr.and(CONTEXT_SETTINGS_JSON_EDITOR.toNegated(), CONTEXT_SETTINGS_EDITOR);
1341
this._register(registerAction2(class extends Action2 {
1342
constructor() {
1343
super({
1344
id: SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON,
1345
title: nls.localize2('openSettingsJson', "Open Settings (JSON)"),
1346
icon: preferencesOpenSettingsIcon,
1347
menu: [{
1348
id: MenuId.EditorTitle,
1349
when: openSettingsJsonWhen,
1350
group: 'navigation',
1351
order: 1
1352
}]
1353
});
1354
}
1355
run(accessor: ServicesAccessor, ...args: unknown[]) {
1356
const group = getEditorGroupFromArguments(accessor, args);
1357
const editorPane = group?.activeEditorPane;
1358
if (editorPane instanceof SettingsEditor2) {
1359
return editorPane.switchToSettingsFile();
1360
}
1361
return null;
1362
}
1363
}));
1364
}
1365
}
1366
1367
class SettingsEditorContribution extends Disposable {
1368
static readonly ID: string = 'editor.contrib.settings';
1369
1370
private currentRenderer: IPreferencesRenderer | undefined;
1371
private readonly disposables = this._register(new DisposableStore());
1372
1373
constructor(
1374
private readonly editor: ICodeEditor,
1375
@IInstantiationService private readonly instantiationService: IInstantiationService,
1376
@IPreferencesService private readonly preferencesService: IPreferencesService,
1377
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService
1378
) {
1379
super();
1380
this._createPreferencesRenderer();
1381
this._register(this.editor.onDidChangeModel(e => this._createPreferencesRenderer()));
1382
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this._createPreferencesRenderer()));
1383
}
1384
1385
private async _createPreferencesRenderer(): Promise<void> {
1386
this.disposables.clear();
1387
this.currentRenderer = undefined;
1388
1389
const model = this.editor.getModel();
1390
if (model && /\.(json|code-workspace)$/.test(model.uri.path)) {
1391
// Fast check: the preferences renderer can only appear
1392
// in settings files or workspace files
1393
const settingsModel = await this.preferencesService.createPreferencesEditorModel(model.uri);
1394
if (settingsModel instanceof SettingsEditorModel && this.editor.getModel()) {
1395
this.disposables.add(settingsModel);
1396
switch (settingsModel.configurationTarget) {
1397
case ConfigurationTarget.WORKSPACE:
1398
this.currentRenderer = this.disposables.add(this.instantiationService.createInstance(WorkspaceSettingsRenderer, this.editor, settingsModel));
1399
break;
1400
default:
1401
this.currentRenderer = this.disposables.add(this.instantiationService.createInstance(UserSettingsRenderer, this.editor, settingsModel));
1402
break;
1403
}
1404
}
1405
1406
this.currentRenderer?.render();
1407
}
1408
}
1409
}
1410
1411
1412
function getEditorGroupFromArguments(accessor: ServicesAccessor, args: unknown[]): IEditorGroup | undefined {
1413
const context = resolveCommandsContext(args, accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IListService));
1414
return context.groupedEditors[0]?.group;
1415
}
1416
1417
registerWorkbenchContribution2(PreferencesActionsContribution.ID, PreferencesActionsContribution, WorkbenchPhase.BlockStartup);
1418
registerWorkbenchContribution2(PreferencesContribution.ID, PreferencesContribution, WorkbenchPhase.BlockStartup);
1419
registerWorkbenchContribution2(SettingsEditorTitleContribution.ID, SettingsEditorTitleContribution, WorkbenchPhase.AfterRestored);
1420
1421
registerEditorContribution(SettingsEditorContribution.ID, SettingsEditorContribution, EditorContributionInstantiation.AfterFirstRender);
1422
1423
// Preferences menu
1424
1425
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
1426
title: nls.localize({ key: 'miPreferences', comment: ['&& denotes a mnemonic'] }, "&&Preferences"),
1427
submenu: MenuId.MenubarPreferencesMenu,
1428
group: '5_autosave',
1429
order: 2,
1430
when: IsMacNativeContext.toNegated() // on macOS native the preferences menu is separate under the application menu
1431
});
1432
1433